Completed
Pull Request — master (#18)
by Frederik
01:37
created

Sha256Signer::fromString()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 5
cts 5
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 2
crap 2
1
<?php
2
declare(strict_types=1);
3
4
namespace Genkgo\Mail\Dkim;
5
6
use Genkgo\Mail\Exception\FailedToSignHeadersException;
7
8
/**
9
 * Class Sha256Signer
10
 * @package Genkgo\Mail\Dkim
11
 */
12
final class Sha256Signer implements SignInterface
13
{
14
    /**
15
     *
16
     */
17
    private CONST SIGN_ALGORITHM = OPENSSL_ALGO_SHA256;
18
19
    /**
20
     *
21
     */
22
    private CONST HASH_ALGORITHM = 'sha256';
23
24
    /**
25
     * @var resource
26
     */
27
    private $privateKey;
28
29
    /**
30
     * Sha256Signer constructor.
31
     * @param $key
32
     */
33 6
    public function __construct($key)
34
    {
35 6
        if (!is_resource($key) || get_resource_type($key) !== 'OpenSSL key') {
36 1
            throw new \InvalidArgumentException('Expected a private key resource');
37
        }
38
39 5
        $this->privateKey = $key;
40 5
    }
41
42
    /**
43
     * @param string $canonicalizedBody
44
     * @return string
45
     */
46 4
    public function hashBody(string $canonicalizedBody): string
47
    {
48 4
        return hash(self::HASH_ALGORITHM, $canonicalizedBody, true);
49
    }
50
51
    /**
52
     * @param string $canonicalizedHeaders
53
     * @return string
54
     * @throws \Exception
55
     */
56 4
    public function signHeaders(string $canonicalizedHeaders): string
57
    {
58 4
        if (openssl_sign($canonicalizedHeaders, $signature, $this->privateKey, self::SIGN_ALGORITHM)) {
59 4
            return $signature;
60
        }
61
62
        // @codeCoverageIgnoreStart
63
        throw new FailedToSignHeadersException(
64
            sprintf('Unable to sign DKIM Hash, openssl error: %s', openssl_error_string())
65
        );
66
        // @codeCoverageIgnoreEnd
67
    }
68
69
    /**
70
     * @return string
71
     */
72 2
    public function name(): string
73
    {
74 2
        return 'rsa-sha256';
75
    }
76
77
    /**
78
     * @param string $file
79
     * @param string|null $passphrase
80
     * @return Sha256Signer
81
     * @throws \Exception
82
     */
83 7
    public static function fromFile(string $file, string $passphrase = ''): self
84
    {
85 7
        if (!file_exists($file)) {
86 1
            throw new \InvalidArgumentException('File does not exist');
87
        }
88
89 6
        return self::fromString(file_get_contents($file), $passphrase);
90
    }
91
92
    /**
93
     * @param string $privateKeyString
94
     * @param string $passphrase
95
     * @return Sha256Signer
96
     * @throws \Exception
97
     */
98 7
    public static function fromString(string $privateKeyString, string $passphrase = ''): self
99
    {
100 7
        $key = openssl_pkey_get_private($privateKeyString, $passphrase);
101
102 7
        if ($key === false) {
103 2
            throw new \InvalidArgumentException('Cannot create resource from private key string');
104
        }
105
106 5
        return new self($key);
107
    }
108
}