Passed
Push — master ( 94ec3f...85a6b6 )
by Roberto
04:23 queued 02:12
created

src/Certificate/Asn1.php (1 issue)

Upgrade to new PHP Analysis Engine

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
Unused Code Comprehensibility introduced by
56% of this comment could be valid code. Did you maybe forget this after debugging?

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.

Loading history...
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