Passed
Push — master ( 463105...84cd59 )
by Roberto
04:47
created

Asn1::oidHexMarker()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 21
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 5

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 21
ccs 15
cts 15
cp 1
rs 8.7624
cc 5
eloc 16
nc 8
nop 1
crap 5
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 12
    public static function getCNPJ($publickeyUnformated)
32
    {
33 12
        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 12
    public static function getOIDdata($oidNumber, $publickeyUnformated)
45
    {
46 12
        $ret = '';
47 12
        $certder = base64_decode($publickeyUnformated);
48
        //converts the OID number from text to hexadecimal
49 12
        $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 12
        $partes = explode($oidMarker, $certder);
58
        //if count($partes) > 1 so OID was located
59 12
        $tot = count($partes);
60 12
        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 9
            $xcv4 = substr($partes[0], -4);
66 9
            $xcv = substr($xcv4, -2);
67
            //exists Hex 030
68 9
            if ($xcv4[0] == chr(0x30)) {
69
                $xcv = $xcv4;
70 9
            } elseif ($xcv4[1] == chr(0x30)) {
71
                $xcv = substr($xcv4, -3);
72
            }
73
            //rebuild the sequency
74 9
            $data = $xcv . $oidMarker . $partes[1];
75
            //converts do decimal the second digit of sequency
76 9
            $len = (integer) ord($data[1]);
0 ignored issues
show
Unused Code introduced by
$len is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
77 9
            $bytes = strlen($oidMarker);
78
            //get length of OID data
79 9
            $len = self::getLength((string) $data);
80
            //get only a string with bytes belongs to OID
81 9
            $oidData = substr($data, 2 + $bytes, $len-($bytes));
82
            //parse OID data many possibel formats and structures
83 9
            $head = strlen($oidData) - strlen($xcv) - 2;
84 9
            $ret = substr($oidData, -$head);
85
        }
86 12
        return $ret;
87
    }
88
    
89
    /**
90
     * Get length of data field of a sequency from certifcate
91
     * @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...
92
     * @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...
93
     * @param string $data
94
     * @return void
95
     */
96 9
    protected static function getLength($data)
97
    {
98 9
        $len = ord($data[1]);
99 9
        $bytes = 0;
0 ignored issues
show
Unused Code introduced by
$bytes is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
100
        //check if len <= 127 bytes,
101
        //if so, then $lenis length of content
102 9
        if ($len > 127) {
103
            $bytes = $len & 0x0f;
104
            $len = 0;
105
            for ($i = 0; $i < $bytes; $i++) {
106
                $len = ($len << 8) | ord($data[$i + 2]);
107
            }
108
        }
109 9
        return $len;
110
    }
111
    
112
    /**
113
     * Convert number OID in ASC Hex representation includes
114
     * in DER format certificate
115
     * @param string $oid OID formated number
116
     * @return string hexadecimal representation
117
     */
118 12
    protected static function oidHexMarker($oid)
119
    {
120 12
        $abBinary = array();
121 12
        $partes = explode('.', $oid);
122 12
        $bun = 0;
123 12
        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...
124 12
            if ($num == 0) {
125 12
                $bun = 40 * $partes[$num];
126 12
            } elseif ($num == 1) {
127 12
                $bun +=  $partes[$num];
128 12
                $abBinary[] = $bun;
129
            } else {
130 12
                $abBinary = self::xBase128((array) $abBinary, (integer) $partes[$num], true);
131
            }
132
        }
133 12
        $value = chr(0x06) . chr(count($abBinary));
134 12
        foreach ($abBinary as $item) {
135 12
            $value .= chr($item);
136
        }
137 12
        return $value;
138
    }
139
140
    /**
141
     * Converts to Base128
142
     * @param array $abIn
143
     * @param integer $qIn
144
     * @param boolean $flag
145
     * @return integer
146
     */
147 12
    protected static function xBase128($abIn, $qIn, $flag)
148
    {
149 12
        $abc = $abIn;
150 12
        if ($qIn > 127) {
151
            $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...
152
        }
153 12
        $qIn2 = $qIn % 128;
154 12
        if ($flag) {
155 12
            $abc[] = $qIn2;
156
        } else {
157
            $abc[] = 0x80 | $qIn2;
158
        }
159 12
        return $abc;
160
    }
161
}
162