Passed
Pull Request — master (#119)
by Roberto
02:33
created

Asn1   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 137
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 85.19%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 16
c 1
b 0
f 0
lcom 1
cbo 0
dl 0
loc 137
ccs 46
cts 54
cp 0.8519
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A getCNPJ() 0 4 1
B getOIDdata() 0 43 4
A getLength() 0 14 3
B oidHexMarker() 0 21 5
A xBase128() 0 14 3
1
<?php
2
3
namespace NFePHP\Common\Certificate;
4
5
/**
6
 * Class to obtain the encrypted data contained in a digital
7
 * certificate PKCS #12.
8
 * See Abstract Syntax Notation One (ASN.1)
9
 * for Distinguished Encoding Rules (DER)
10
 * This data may be formatted and encoded into multiple data formats, so to
11
 * extracted it is necessary to identify which format was inserted then
12
 * it can be decrypted in a readable structure
13
 * @category   NFePHP
14
 * @package    NFePHP\Common\Asn1
15
 * @copyright  Copyright (c) 2008-2016
16
 * @license    http://www.gnu.org/licenses/lesser.html LGPL v3
17
 * @author     Roberto L. Machado <linux.rlm at gmail dot com>
18
 * @link       http://github.com/nfephp-org/nfephp for the canonical source repository
19
 */
20
21
use NFePHP\Common\Certificate;
22
23
class Asn1
24
{
25
    /**
26
     * Get CNPJ owner number from digital certificate
27
     * (more specifically, from public key)
28
     * @param string $publickeyUnformated
29
     * @return string CNPJ
30
     */
31 17
    public static function getCNPJ($publickeyUnformated)
32
    {
33 17
        return self::getOIDdata('2.16.76.1.3.3', $publickeyUnformated);
34
    }
35
36
    /**
37
     * Recovers information regarding the OID contained in the certificate
38
     * method assumes that the OID is embedded within a structure of
39
     * type "sequence", as the first element of the structure
40
     * @param string $publickeyUnformated
41
     * @param string $oidNumber OID formated number
42
     * @return array
43
     */
44 17
    public static function getOIDdata($oidNumber, $publickeyUnformated)
45
    {
46 17
        $ret = '';
47 17
        $certder = base64_decode($publickeyUnformated);
48
        //converts the OID number from text to hexadecimal
49 17
        $oidMarker = self::oidHexMarker($oidNumber);
50
        //Divide the certificate using the OID as a marker,
51
        //geting the first part before the OID marker and
52
        //the other containing the OID data and so own.
53
        //Usually the certificate will be divided into only two parts,
54
        //because there are usually only one OID of each type in
55
        //the certificate, but can be more. In this case only
56
        //first occurency will be returned.
57 17
        $partes = explode($oidMarker, $certder);
58
        //if count($partes) > 1 so OID was located
59 17
        $tot = count($partes);
60 17
        if ($tot > 1) {
61
            //The beginning of the sequence that interests us, can be 3 or 2
62
            //digits before the start of OID, it depends on the number of
63
            //bytes used to identify the size of this data sequence,and before
64
            //len digits exists a separator digit like 0x30
65 14
            $xcv4 = substr($partes[0], -4);
66 14
            $xcv = substr($xcv4, -2);
67
            //exists Hex 030
68 14
            if ($xcv4[0] == chr(0x30)) {
69
                $xcv = $xcv4;
70 14
            } elseif ($xcv4[1] == chr(0x30)) {
71
                $xcv = substr($xcv4, -3);
72
            }
73
            //rebuild the sequency
74 14
            $data = $xcv . $oidMarker . $partes[1];
75
            //converts do decimal the second digit of sequency
76 14
            $bytes = strlen($oidMarker);
77
            //get length of OID data
78 14
            $len = self::getLength((string) $data);
79
            //get only a string with bytes belongs to OID
80 14
            $oidData = substr($data, 2 + $bytes, $len-($bytes));
81
            //parse OID data many possibel formats and structures
82 14
            $head = strlen($oidData) - strlen($xcv) - 2;
83 14
            $ret = substr($oidData, -$head);
84
        }
85 17
        return $ret;
86
    }
87
    
88
    /**
89
     * Get length of data field of a sequency from certifcate
90
     * @param integer $len
0 ignored issues
show
Bug introduced by
There is no parameter named $len. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
91
     * @param integer $bytes
0 ignored issues
show
Bug introduced by
There is no parameter named $bytes. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
92
     * @param string $data
93
     * @return integer
94
     */
95 14
    protected static function getLength($data)
96
    {
97 14
        $len = ord($data[1]);
98
        //check if len <= 127 bytes,
99
        //if so, then $lenis length of content
100 14
        if ($len > 127) {
101
            $bytes = $len & 0x0f;
102
            $len = 0;
103
            for ($i = 0; $i < $bytes; $i++) {
104
                $len = ($len << 8) | ord($data[$i + 2]);
105
            }
106
        }
107 14
        return $len;
108
    }
109
    
110
    /**
111
     * Convert number OID in ASC Hex representation includes
112
     * in DER format certificate
113
     * @param string $oid OID formated number
114
     * @return string hexadecimal representation
115
     */
116 17
    protected static function oidHexMarker($oid)
117
    {
118 17
        $abBinary = array();
119 17
        $partes = explode('.', $oid);
120 17
        $bun = 0;
121 17
        for ($num = 0; $num < count($partes); $num++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
122 17
            if ($num == 0) {
123 17
                $bun = 40 * $partes[$num];
124 17
            } elseif ($num == 1) {
125 17
                $bun +=  $partes[$num];
126 17
                $abBinary[] = $bun;
127
            } else {
128 17
                $abBinary = self::xBase128((array) $abBinary, (integer) $partes[$num], true);
129
            }
130
        }
131 17
        $value = chr(0x06) . chr(count($abBinary));
132 17
        foreach ($abBinary as $item) {
133 17
            $value .= chr($item);
134
        }
135 17
        return $value;
136
    }
137
138
    /**
139
     * Converts to Base128
140
     * @param array $abIn
141
     * @param integer $qIn
142
     * @param boolean $flag
143
     * @return integer
144
     */
145 17
    protected static function xBase128($abIn, $qIn, $flag)
146
    {
147 17
        $abc = $abIn;
148 17
        if ($qIn > 127) {
149
            $abc = $this->xBase128($abc, floor($qIn/128), false);
0 ignored issues
show
Bug introduced by
The variable $this does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
150
        }
151 17
        $qIn2 = $qIn % 128;
152 17
        if ($flag) {
153 17
            $abc[] = $qIn2;
154
        } else {
155
            $abc[] = 0x80 | $qIn2;
156
        }
157 17
        return $abc;
158
    }
159
}
160