These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace NFePHP\Common\Certificate; |
||
4 | |||
5 | /** |
||
6 | * Obtain the encrypted data contained in a digital certificate PKCS #12. |
||
7 | * See Abstract Syntax Notation One (ASN.1) |
||
8 | * for Distinguished Encoding Rules (DER) |
||
9 | * This data may be formatted and encoded into multiple data formats, so to |
||
10 | * extracted it is necessary to identify which format was inserted then |
||
11 | * it can be decrypted in a readable structure |
||
12 | * @category NFePHP |
||
13 | * @package NFePHP\Common\Asn1 |
||
14 | * @copyright Copyright (c) 2008-2016 |
||
15 | * @license http://www.gnu.org/licenses/lesser.html LGPL v3 |
||
16 | * @author Roberto L. Machado <linux.rlm at gmail dot com> |
||
17 | * @link http://github.com/nfephp-org/nfephp for the canonical source repository |
||
18 | */ |
||
19 | |||
20 | class Asn1 |
||
21 | { |
||
22 | /** |
||
23 | * Get CNPJ owner number from digital certificate |
||
24 | * (more specifically, from public key) |
||
25 | * @param string $publickeyUnformated |
||
26 | * @return string CNPJ |
||
27 | */ |
||
28 | 18 | public static function getCNPJ($publickeyUnformated) |
|
29 | { |
||
30 | //CNPJ |
||
31 | //OID = 2.16.76.1.3.3 |
||
0 ignored issues
–
show
|
|||
32 | 18 | return self::getOIDdata('2.16.76.1.3.3', $publickeyUnformated); |
|
33 | } |
||
34 | |||
35 | /** |
||
36 | * CPF |
||
37 | * OID = 2.16.76.1.3.1 e |
||
38 | * conteúdo = nas primeiras 8 (oito) posições, |
||
39 | * a data de nascimento do titular, |
||
40 | * no formato ddmmaaaa; |
||
41 | * nas 11 (onze) posições subseqüentes, |
||
42 | * o Cadastro de Pessoa Física (CPF) do titular; |
||
43 | * nas 11 (onze) posições subseqüentes, |
||
44 | * o número de inscrição do titular no PIS/PASEP; |
||
45 | * nas 11 (onze) posições subseqüentes, |
||
46 | * o número do Registro Geral - RG do titular; |
||
47 | * nas 6 (seis) posições subseqüentes, |
||
48 | * as siglas do órgão expedidor do RG |
||
49 | * e respectiva UF. |
||
50 | */ |
||
51 | |||
52 | /** |
||
53 | * Recovers information regarding the OID contained in the certificate |
||
54 | * method assumes that the OID is embedded within a structure of |
||
55 | * type "sequence", as the first element of the structure |
||
56 | * @param string $publickeyUnformated |
||
57 | * @param string $oidNumber OID formated number |
||
58 | * @return string |
||
59 | */ |
||
60 | 18 | public static function getOIDdata($oidNumber, $publickeyUnformated) |
|
61 | { |
||
62 | 18 | $ret = ''; |
|
63 | 18 | $certder = base64_decode($publickeyUnformated); |
|
64 | //converts the OID number from text to hexadecimal |
||
65 | 18 | $oidMarker = self::oidHexMarker($oidNumber); |
|
66 | //Divide the certificate using the OID as a marker, |
||
67 | //geting the first part before the OID marker and |
||
68 | //the other containing the OID data and so own. |
||
69 | //Usually the certificate will be divided into only two parts, |
||
70 | //because there are usually only one OID of each type in |
||
71 | //the certificate, but can be more. In this case only |
||
72 | //first occurency will be returned. |
||
73 | 18 | if (!strpos($certder, $oidMarker)) { |
|
74 | //OID not found return empty |
||
75 | 9 | return ''; |
|
76 | } |
||
77 | 15 | $partes = explode($oidMarker, $certder); |
|
78 | //if count($partes) > 1 so OID was located |
||
79 | 15 | $tot = count($partes); |
|
80 | 15 | if ($tot > 1) { |
|
81 | //The beginning of the sequence that interests us, can be 3 or 2 |
||
82 | //digits before the start of OID, it depends on the number of |
||
83 | //bytes used to identify the size of this data sequence,and before |
||
84 | //len digits exists a separator digit like 0x30 |
||
85 | 15 | $xcv4 = substr($partes[0], -4); |
|
86 | 15 | $xcv = substr($xcv4, -2); |
|
87 | //exists Hex 030 |
||
88 | 15 | if ($xcv4[0] == chr(0x30)) { |
|
89 | $xcv = $xcv4; |
||
90 | 15 | } elseif ($xcv4[1] == chr(0x30)) { |
|
91 | $xcv = substr($xcv4, -3); |
||
92 | } |
||
93 | //rebuild the sequency |
||
94 | 15 | $data = $xcv . $oidMarker . $partes[1]; |
|
95 | //converts do decimal the second digit of sequency |
||
96 | 15 | $bytes = strlen($oidMarker); |
|
97 | //get length of OID data |
||
98 | 15 | $len = self::getLength($data); |
|
99 | //get only a string with bytes belongs to OID |
||
100 | 15 | $oidData = substr($data, 2 + $bytes, $len-($bytes)); |
|
101 | //parse OID data many possibel formats and structures |
||
102 | 15 | $head = strlen($oidData) - strlen($xcv) - 2; |
|
103 | 15 | $ret = substr($oidData, -$head); |
|
104 | } |
||
105 | 15 | return $ret; |
|
106 | } |
||
107 | |||
108 | /** |
||
109 | * Get length of data field of a sequency from certifcate |
||
110 | * @param string $data |
||
111 | * @return integer |
||
112 | */ |
||
113 | 15 | protected static function getLength($data) |
|
114 | { |
||
115 | 15 | $len = ord($data[1]); |
|
116 | //check if len <= 127 bytes, |
||
117 | //if so, then $lenis length of content |
||
118 | 15 | if ($len > 127) { |
|
119 | $bytes = $len & 0x0f; |
||
120 | $len = 0; |
||
121 | for ($i = 0; $i < $bytes; $i++) { |
||
122 | $len = ($len << 8) | ord($data[$i + 2]); |
||
123 | } |
||
124 | } |
||
125 | 15 | return $len; |
|
126 | } |
||
127 | |||
128 | /** |
||
129 | * Convert number OID in ASC Hex representation includes |
||
130 | * in DER format certificate |
||
131 | * @param string $oid OID formated number |
||
132 | * @return string hexadecimal representation |
||
133 | */ |
||
134 | 18 | protected static function oidHexMarker($oid) |
|
135 | { |
||
136 | 18 | $abBinary = array(); |
|
137 | 18 | $partes = explode('.', $oid); |
|
138 | 18 | $bun = 0; |
|
139 | 18 | $npart = count($partes); |
|
140 | 18 | for ($num = 0; $num < $npart; $num++) { |
|
141 | 18 | if ($num == 0) { |
|
142 | 18 | $bun = 40 * $partes[$num]; |
|
143 | 18 | } elseif ($num == 1) { |
|
144 | 18 | $bun += $partes[$num]; |
|
145 | 18 | $abBinary[] = $bun; |
|
146 | } else { |
||
147 | 18 | $abBinary = self::xBase128($abBinary, (integer) $partes[$num], true); |
|
148 | } |
||
149 | } |
||
150 | 18 | $value = chr(0x06) . chr(count($abBinary)); |
|
151 | 18 | foreach ($abBinary as $item) { |
|
152 | 18 | $value .= chr($item); |
|
153 | } |
||
154 | 18 | return $value; |
|
155 | } |
||
156 | |||
157 | /** |
||
158 | * Converts to Base128 |
||
159 | * @param array $abIn |
||
160 | * @param integer $qIn |
||
161 | * @param boolean $flag |
||
162 | * @return array |
||
163 | */ |
||
164 | 18 | protected static function xBase128($abIn, $qIn, $flag) |
|
165 | { |
||
166 | 18 | $abc = $abIn; |
|
167 | 18 | if ($qIn > 127) { |
|
168 | $abc = self::xBase128($abc, floor($qIn/128), false); |
||
169 | } |
||
170 | 18 | $qIn2 = $qIn % 128; |
|
171 | 18 | if ($flag) { |
|
172 | 18 | $abc[] = $qIn2; |
|
173 | } else { |
||
174 | $abc[] = 0x80 | $qIn2; |
||
175 | } |
||
176 | 18 | return $abc; |
|
177 | } |
||
178 | } |
||
179 |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.