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

Certificate   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 150
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 73.91%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 16
c 1
b 0
f 0
lcom 1
cbo 4
dl 0
loc 150
ccs 34
cts 46
cp 0.7391
rs 10

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A readPfx() 0 18 4
A writePfx() 0 18 2
A getCompanyName() 0 4 1
A getValidFrom() 0 4 1
A getValidTo() 0 4 1
A isExpired() 0 4 1
A getCnpj() 0 4 1
A sign() 0 4 1
A verify() 0 4 1
A __toString() 0 8 2
1
<?php
2
3
namespace NFePHP\Common;
4
5
/**
6
 * Certificate class for management and use of digital certificates A1 (PKCS # 12)
7
 * @category   NFePHP
8
 * @package    NFePHP\Common\Certificate
9
 * @copyright  Copyright (c) 2008-2017
10
 * @license    http://www.gnu.org/licenses/lesser.html LGPL v3
11
 * @author     Antonio Spinelli <tonicospinelli85 at gmail dot com>
12
 * @link       http://github.com/nfephp-org/sped-common for the canonical source repository
13
 */
14
15
use NFePHP\Common\Certificate\PrivateKey;
16
use NFePHP\Common\Certificate\PublicKey;
17
use NFePHP\Common\Certificate\CertificationChain;
18
use NFePHP\Common\Certificate\SignatureInterface;
19
use NFePHP\Common\Certificate\VerificationInterface;
20
use NFePHP\Common\Exception\CertificateException;
21
22
class Certificate implements SignatureInterface, VerificationInterface
23
{
24
    /**
25
     * @var PrivateKey
26
     */
27
    public $privateKey;
28
29
    /**
30
     * @var PublicKey
31
     */
32
    public $publicKey;
33
    
34
    /**
35
     * @var CertificationChain
36
     */
37
    public $chainKeys;
38
    
39
    /**
40
     * Constructor
41
     * @param PrivateKey $privateKey
42
     * @param PublicKey $publicKey
43
     * @param CertificationChain $chainKeys
44
     */
45 4
    public function __construct(PrivateKey $privateKey, PublicKey $publicKey, CertificationChain $chainKeys = null)
46
    {
47 4
        $this->privateKey = $privateKey;
48 4
        $this->publicKey = $publicKey;
49 4
        $this->chainKeys = $chainKeys;
50 4
    }
51
    
52
    /**
53
     * Read PFX and return this class
54
     * @param string $content
55
     * @param string $password
56
     * @return \static
57
     * @throws CertificateException
58
     */
59 3
    public static function readPfx($content, $password)
60
    {
61 3
        $certs = [];
62 3
        if (!openssl_pkcs12_read($content, $certs, $password)) {
63 1
            throw CertificateException::unableToRead();
64
        }
65 2
        $chain = '';
66 2
        if (!empty($certs['extracerts'])) {
67 2
            foreach ($certs['extracerts'] as $ec) {
68 2
                $chain .= $ec;
69
            }
70
        }
71 2
        return new static(
72 2
            new PrivateKey($certs['pkey']),
73 2
            new PublicKey($certs['cert']),
74 2
            new CertificationChain($chain)
75
        );
76
    }
77
    
78
    /**
79
     * Returns a PFX string with certification chain if exists
80
     * @param string $password
81
     * @return string
82
     */
83
    public function writePfx($password)
84
    {
85
        $password = trim($password);
86
        if (empty($password)) {
87
            return '';
88
        }
89
        $x509_cert = openssl_x509_read("{$this->publicKey}");
90
        $privateKey_resource = openssl_pkey_get_private("{$this->privateKey}");
91
        $pfxstring = '';
92
        openssl_pkcs12_export(
93
            $x509_cert,
94
            $pfxstring,
95
            $privateKey_resource,
96
            $password,
97
            $chainKeys->getExtraCertsForPFX()
0 ignored issues
show
Bug introduced by
The variable $chainKeys 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...
98
        );
99
        return $pfxstring;
100
    }
101
102
    /**
103
     * Gets company name.
104
     * @return string
105
     */
106 2
    public function getCompanyName()
107
    {
108 2
        return $this->publicKey->commonName;
109
    }
110
111
    /**
112
     * Gets start date.
113
     * @return \DateTime Returns start date.
114
     */
115 2
    public function getValidFrom()
116
    {
117 2
        return $this->publicKey->validFrom;
118
    }
119
120
    /**
121
     * Gets end date.
122
     * @return \DateTime Returns end date.
123
     */
124 2
    public function getValidTo()
125
    {
126 2
        return $this->publicKey->validTo;
127
    }
128
129
    /**
130
     * Check if certificate has been expired.
131
     * @return bool Returns true when it is truth, otherwise false.
132
     */
133 2
    public function isExpired()
134
    {
135 2
        return $this->publicKey->isExpired();
136
    }
137
    
138
    /**
139
     * Gets CNPJ by OID '2.16.76.1.3.3' from ASN.1 certificate struture
140
     * @return string
141
     */
142
    public function getCnpj()
143
    {
144
        return $this->publicKey->cnpj;
145
    }
146
147
    /**
148
     * {@inheritdoc}
149
     */
150 3
    public function sign($content, $algorithm = OPENSSL_ALGO_SHA1)
151
    {
152 3
        return $this->privateKey->sign($content, $algorithm);
153
    }
154
155
    /**
156
     * {@inheritdoc}
157
     */
158 2
    public function verify($data, $signature, $algorithm = OPENSSL_ALGO_SHA1)
159
    {
160 2
        return $this->publicKey->verify($data, $signature, $algorithm);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->publicKey-...signature, $algorithm); (boolean) is incompatible with the return type declared by the interface NFePHP\Common\Certificat...cationInterface::verify of type integer.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
161
    }
162
    
163 1
    public function __toString()
164
    {
165 1
        $chainKeys = '';
166 1
        if ($this->chainKeys != null) {
167 1
            $chainKeys = "{$this->chainKeys}";
168
        }
169 1
        return "{$this->publicKey}{$chainKeys}";
170
    }
171
}
172