Completed
Push — master ( f64a2b...48aedc )
by thomas
05:58
created

RequestSignerTest::testSignOperation()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 61
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 61
rs 8.6806
cc 6
eloc 38
nc 8
nop 4

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Bip70\Test\X509;
6
7
use Bip70\Exception\X509Exception;
8
use Bip70\Protobuf\Proto\PaymentDetails;
9
use Bip70\Protobuf\Proto\X509Certificates;
10
use Bip70\X509\PKIType;
11
use Bip70\X509\RequestSigner;
12
use Bip70\X509\RequestValidation;
13
use Bip70\X509\TrustStoreLoader;
14
use PHPUnit\Framework\TestCase;
15
use Sop\CryptoEncoding\PEM;
16
use Sop\CryptoEncoding\PEMBundle;
17
use Sop\CryptoTypes\Asymmetric\PrivateKeyInfo;
18
use X509\Certificate\Certificate;
19
use X509\Certificate\CertificateBundle;
20
use X509\CertificationPath\PathValidation\PathValidationConfig;
21
22
class RequestSignerTest extends TestCase
23
{
24
    public function testSignRequiresPkiType()
25
    {
26
        $details = new PaymentDetails();
27
        $privateKey = PrivateKeyInfo::fromPEM(PEM::fromFile(__DIR__ . "/../../data/selfsigned.key.pem"));
28
        $cert = Certificate::fromPEM(PEM::fromFile(__DIR__ . "/../../data/selfsigned.cert.pem"));
29
        $certBundle = new CertificateBundle();
30
        $requestSigner = new RequestSigner();
31
32
        $this->expectExceptionMessage("Don't call sign with pki_type = none");
33
        $this->expectException(\UnexpectedValueException::class);
34
35
        $requestSigner->sign($details, PKIType::NONE, $privateKey, $cert, $certBundle);
36
    }
37
38
    public function testSignRequiresValidPkiType()
39
    {
40
        $details = new PaymentDetails();
41
        $privateKey = PrivateKeyInfo::fromPEM(PEM::fromFile(__DIR__ . "/../../data/selfsigned.key.pem"));
42
        $cert = Certificate::fromPEM(PEM::fromFile(__DIR__ . "/../../data/selfsigned.cert.pem"));
43
        $certBundle = new CertificateBundle();
44
        $requestSigner = new RequestSigner();
45
46
        $this->expectExceptionMessage("Unknown signature scheme");
47
        $this->expectException(X509Exception::class);
48
49
        $requestSigner->sign($details, "purebs", $privateKey, $cert, $certBundle);
50
    }
51
52
    /**
53
     * @return array
54
     */
55
    public function getSignFixtures(): array
56
    {
57
        $keySelfSigned = PrivateKeyInfo::fromPEM(PEM::fromFile(__DIR__ . "/../../data/selfsigned.key.pem"));
58
        $certSelfSigned = Certificate::fromPEM(PEM::fromFile(__DIR__ . "/../../data/selfsigned.cert.pem"));
59
        $selfSignedStore = new CertificateBundle($certSelfSigned);
60
        $emptyBundle = new CertificateBundle();
61
62
        $keySigned = PrivateKeyInfo::fromPEM(PEM::fromFile(__DIR__ . "/../../data/testnet-only-cert-not-valid.key"));
63
        $certs = CertificateBundle::fromPEMBundle(PEMBundle::fromFile(__DIR__ . "/../../data/testnet-only-cert-not-valid.cabundle.pem"));
64
        $certSigned = $certs->all()[0];
65
        $certBundle = new CertificateBundle(...array_slice($certs->all(), 1));
66
67
        $systemStore = TrustStoreLoader::fromSystem();
68
        return [
69
            // test a self signed case
70
            [$selfSignedStore, $keySelfSigned, $certSelfSigned, $emptyBundle],
71
            [$systemStore, $keySigned, $certSigned, $certBundle],
72
        ];
73
    }
74
75
    /**
76
     * @param PrivateKeyInfo $privateKey
77
     * @param Certificate $cert
78
     * @param CertificateBundle $certBundle
79
     * @param CertificateBundle $trustStore
80
     * @dataProvider getSignFixtures
81
     */
82
    public function testSignOperation(CertificateBundle $trustStore, PrivateKeyInfo $privateKey, Certificate $cert, CertificateBundle $certBundle)
83
    {
84
        $now = time();
85
86
        $details = new PaymentDetails();
87
        $details->setTime($now);
88
89
        $requestSigner = new RequestSigner();
90
        // 10/12/2017 ish
91
        $now = new \DateTimeImmutable();
92
        $now = $now->setTimestamp(1509692666);
93
94
        $requestValidator = new RequestValidation(new PathValidationConfig($now, 10), $trustStore);
95
96
        foreach ([PKIType::X509_SHA256, PKIType::X509_SHA1] as $pkiType) {
97
            $request = $requestSigner->sign($details, $pkiType, $privateKey, $cert, $certBundle);
98
            $this->assertTrue($request->hasSignature());
99
            $this->assertTrue($request->hasPkiData());
100
            $this->assertTrue($request->hasPkiType());
101
102
            $this->assertEquals($pkiType, $request->getPkiType());
103
104
            try {
105
                $requestValidator->validateX509Signature($cert, $request);
106
            } catch (\Exception $e) {
107
                $this->fail("verification of own signature should always succeed");
108
                return;
109
            }
110
111
            $x509 = new X509Certificates();
112
            $x509->parse($request->getPkiData());
113
114
            $this->assertEquals(1 + count($certBundle), count($x509->getCertificateList()));
115
116
            /** @var Certificate[] $allCerts */
117
            $allCerts = array_merge([$cert], $certBundle->all());
118
            foreach ($allCerts as $i => $certificate) {
119
                $this->assertEquals($certificate->toDER(), $x509->getCertificate($i));
120
            }
121
122
            try {
123
                $qualifiedCert = $requestValidator->validateCertificateChain($x509);
124
            } catch (\Exception $e) {
125
                $this->fail("certificate chain validation shouldn't fail");
126
                return;
127
            }
128
129
            $this->assertTrue($cert->equals($qualifiedCert->getPath()->endEntityCertificate()));
130
131
            try {
132
                $result = $requestValidator->verifyX509Details($request);
133
                $threw = false;
134
            } catch (\Exception $e) {
135
                $threw = true;
136
            }
137
138
            $this->assertFalse($threw, "verifying cert details shouldn't fail");
139
140
            $this->assertTrue($result->certificate()->equals($cert));
141
        }
142
    }
143
}
144