1 | <?php |
||
17 | class DerSignatureSerializer implements DerSignatureSerializerInterface |
||
18 | { |
||
19 | /** |
||
20 | * @var EcAdapter |
||
21 | */ |
||
22 | private $ecAdapter; |
||
23 | |||
24 | /** |
||
25 | * @param EcAdapter $adapter |
||
26 | */ |
||
27 | 102 | public function __construct(EcAdapter $adapter) |
|
31 | |||
32 | /** |
||
33 | * @return EcAdapterInterface |
||
34 | */ |
||
35 | 95 | public function getEcAdapter() |
|
39 | |||
40 | /** |
||
41 | * @return Template |
||
42 | */ |
||
43 | 86 | private function getInnerTemplate() |
|
52 | |||
53 | /** |
||
54 | * @return Template |
||
55 | */ |
||
56 | 102 | private function getOuterTemplate() |
|
63 | |||
64 | /** |
||
65 | * @param SignatureInterface $signature |
||
66 | * @return BufferInterface |
||
67 | */ |
||
68 | 19 | public function serialize(SignatureInterface $signature) |
|
69 | { |
||
70 | 19 | $math = $this->ecAdapter->getMath(); |
|
71 | |||
72 | // Ensure that the R and S hex's are of even length |
||
73 | 19 | $rBin = pack('H*', $math->decHex($math->toString($signature->getR()))); |
|
74 | 19 | $sBin = pack('H*', $math->decHex($math->toString($signature->getS()))); |
|
75 | |||
76 | // Pad R and S if their highest bit is flipped, ie, |
||
77 | // they are negative. |
||
78 | 19 | $rt = $rBin[0] & pack('H*', '80'); |
|
79 | 19 | if (ord($rt) === 128) { |
|
80 | 7 | $rBin = pack('H*', '00') . $rBin; |
|
81 | } |
||
82 | |||
83 | 19 | $st = $sBin[0] & pack('H*', '80'); |
|
84 | 19 | if (ord($st) === 128) { |
|
85 | 5 | $sBin = pack('H*', '00') . $sBin; |
|
86 | 1 | } |
|
87 | |||
88 | 19 | return $this->getOuterTemplate()->write([ |
|
89 | 19 | 0x30, |
|
90 | 19 | $this->getInnerTemplate()->write([ |
|
91 | 19 | 0x02, |
|
92 | 19 | new Buffer($rBin, null, $math), |
|
93 | 19 | 0x02, |
|
94 | 19 | new Buffer($sBin, null, $math) |
|
95 | 1 | ]) |
|
96 | 1 | ]); |
|
97 | } |
||
98 | |||
99 | /** |
||
100 | * @param Parser $parser |
||
101 | * @return Signature |
||
102 | * @throws ParserOutOfRange |
||
103 | */ |
||
104 | 97 | public function fromParser(Parser $parser) |
|
105 | { |
||
106 | try { |
||
107 | 97 | list (, $inner) = $this->getOuterTemplate()->parse($parser); |
|
108 | 81 | list (, $r, , $s) = $this->getInnerTemplate()->parse(new Parser($inner)); |
|
109 | /** @var Buffer $r */ |
||
110 | /** @var Buffer $s */ |
||
111 | |||
112 | 79 | return new Signature( |
|
113 | 79 | $this->ecAdapter, |
|
114 | 79 | $r->getGmp(), |
|
115 | 78 | $s->getGmp() |
|
116 | ); |
||
117 | 22 | } catch (ParserOutOfRange $e) { |
|
118 | 20 | throw new ParserOutOfRange('Failed to extract full signature from parser'); |
|
119 | } |
||
120 | } |
||
121 | |||
122 | /** |
||
123 | * @param BufferInterface|$string |
||
124 | * @return Signature |
||
125 | * @throws ParserOutOfRange |
||
126 | */ |
||
127 | 97 | public function parse($string) |
|
133 | } |
||
134 |