Passed
Push — master ( ce8345...b82e2f )
by Roberto
54s queued 10s
created

Asn1::getCPF()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
ccs 0
cts 2
cp 0
rs 9.4285
cc 1
eloc 2
nc 1
nop 1
crap 2
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
     * Get CPF owner number from digital certificate
53
     * (more specifically, from public key)
54
     * @param string $publickeyUnformated
55
     * @return string CPF
56
     */
57
    public static function getCPF($publickeyUnformated)
58
    {
59
        //CPF
60
        //OID = 2.16.76.1.3.1
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...
61
        return self::getOIDdata('2.16.76.1.3.1', $publickeyUnformated);
62
    }
63
64
    /**
65
     * Recovers information regarding the OID contained in the certificate
66
     * method assumes that the OID is embedded within a structure of
67
     * type "sequence", as the first element of the structure
68
     * @param string $publickeyUnformated
69
     * @param string $oidNumber OID formated number
70
     * @return string
71
     */
72 18
    public static function getOIDdata($oidNumber, $publickeyUnformated)
73
    {
74 18
        $ret = '';
75 18
        $certder = base64_decode($publickeyUnformated);
76
        //converts the OID number from text to hexadecimal
77 18
        $oidMarker = self::oidHexMarker($oidNumber);
78
        //Divide the certificate using the OID as a marker,
79
        //geting the first part before the OID marker and
80
        //the other containing the OID data and so own.
81
        //Usually the certificate will be divided into only two parts,
82
        //because there are usually only one OID of each type in
83
        //the certificate, but can be more. In this case only
84
        //first occurency will be returned.
85 18
        if (!strpos($certder, $oidMarker)) {
86
            //OID not found return empty
87 9
            return '';
88
        }
89 15
        $partes = explode($oidMarker, $certder);
90
        //if count($partes) > 1 so OID was located
91 15
        $tot = count($partes);
92 15
        if ($tot > 1) {
93
            //The beginning of the sequence that interests us, can be 3 or 2
94
            //digits before the start of OID, it depends on the number of
95
            //bytes used to identify the size of this data sequence,and before
96
            //len digits exists a separator digit like 0x30
97 15
            $xcv4 = substr($partes[0], -4);
98 15
            $xcv = substr($xcv4, -2);
99
            //exists Hex 030
100 15
            if ($xcv4[0] == chr(0x30)) {
101
                $xcv = $xcv4;
102 15
            } elseif ($xcv4[1] == chr(0x30)) {
103
                $xcv = substr($xcv4, -3);
104
            }
105
            //rebuild the sequency
106 15
            $data = $xcv . $oidMarker . $partes[1];
107
            //converts do decimal the second digit of sequency
108 15
            $bytes = strlen($oidMarker);
109
            //get length of OID data
110 15
            $len = self::getLength($data);
111
            //get only a string with bytes belongs to OID
112 15
            $oidData = substr($data, 2 + $bytes, $len-($bytes));
113
            //parse OID data many possibel formats and structures
114 15
            $head = strlen($oidData) - strlen($xcv) - 2;
115 15
            $ret = substr($oidData, -$head);
116
        }
117 15
        return $ret;
118
    }
119
    
120
    /**
121
     * Get length of data field of a sequency from certifcate
122
     * @param string $data
123
     * @return integer
124
     */
125 15
    protected static function getLength($data)
126
    {
127 15
        $len = ord($data[1]);
128
        //check if len <= 127 bytes,
129
        //if so, then $lenis length of content
130 15
        if ($len > 127) {
131
            $bytes = $len & 0x0f;
132
            $len = 0;
133
            for ($i = 0; $i < $bytes; $i++) {
134
                $len = ($len << 8) | ord($data[$i + 2]);
135
            }
136
        }
137 15
        return $len;
138
    }
139
    
140
    /**
141
     * Convert number OID in ASC Hex representation includes
142
     * in DER format certificate
143
     * @param string $oid OID formated number
144
     * @return string hexadecimal representation
145
     */
146 18
    protected static function oidHexMarker($oid)
147
    {
148 18
        $abBinary = array();
149 18
        $partes = explode('.', $oid);
150 18
        $bun = 0;
151 18
        $npart = count($partes);
152 18
        for ($num = 0; $num < $npart; $num++) {
153 18
            if ($num == 0) {
154 18
                $bun = 40 * $partes[$num];
155 18
            } elseif ($num == 1) {
156 18
                $bun +=  $partes[$num];
157 18
                $abBinary[] = $bun;
158
            } else {
159 18
                $abBinary = self::xBase128($abBinary, (integer) $partes[$num], true);
160
            }
161
        }
162 18
        $value = chr(0x06) . chr(count($abBinary));
163 18
        foreach ($abBinary as $item) {
164 18
            $value .= chr($item);
165
        }
166 18
        return $value;
167
    }
168
169
    /**
170
     * Converts to Base128
171
     * @param array $abIn
172
     * @param integer $qIn
173
     * @param boolean $flag
174
     * @return array
175
     */
176 18
    protected static function xBase128($abIn, $qIn, $flag)
177
    {
178 18
        $abc = $abIn;
179 18
        if ($qIn > 127) {
180
            $abc = self::xBase128($abc, floor($qIn/128), false);
181
        }
182 18
        $qIn2 = $qIn % 128;
183 18
        if ($flag) {
184 18
            $abc[] = $qIn2;
185
        } else {
186
            $abc[] = 0x80 | $qIn2;
187
        }
188 18
        return $abc;
189
    }
190
}
191