1 | <?php |
||
17 | class DerSignatureSerializer implements DerSignatureSerializerInterface |
||
18 | { |
||
19 | /** |
||
20 | * @var EcAdapter |
||
21 | */ |
||
22 | private $ecAdapter; |
||
23 | |||
24 | /** |
||
25 | * @param EcAdapter $adapter |
||
26 | */ |
||
27 | 204 | public function __construct(EcAdapter $adapter) |
|
31 | |||
32 | /** |
||
33 | * @return EcAdapterInterface |
||
34 | */ |
||
35 | 186 | public function getEcAdapter() |
|
39 | |||
40 | /** |
||
41 | * @return Template |
||
42 | */ |
||
43 | 172 | private function getInnerTemplate() |
|
52 | |||
53 | /** |
||
54 | * @return Template |
||
55 | */ |
||
56 | 204 | private function getOuterTemplate() |
|
63 | |||
64 | /** |
||
65 | * @param SignatureInterface $signature |
||
66 | * @return BufferInterface |
||
67 | */ |
||
68 | 38 | public function serialize(SignatureInterface $signature) |
|
69 | { |
||
70 | 38 | $math = $this->ecAdapter->getMath(); |
|
71 | |||
72 | // Ensure that the R and S hex's are of even length |
||
73 | 38 | $rBin = pack('H*', $math->decHex($math->toString($signature->getR()))); |
|
74 | 38 | $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 | 38 | $rt = $rBin[0] & pack('H*', '80'); |
|
79 | 38 | if (ord($rt) === 128) { |
|
80 | 14 | $rBin = pack('H*', '00') . $rBin; |
|
81 | } |
||
82 | |||
83 | 38 | $st = $sBin[0] & pack('H*', '80'); |
|
84 | 38 | if (ord($st) === 128) { |
|
85 | 10 | $sBin = pack('H*', '00') . $sBin; |
|
86 | 2 | } |
|
87 | |||
88 | 38 | return $this->getOuterTemplate()->write([ |
|
89 | 38 | 0x30, |
|
90 | 38 | $this->getInnerTemplate()->write([ |
|
91 | 38 | 0x02, |
|
92 | 38 | new Buffer($rBin, null, $math), |
|
93 | 38 | 0x02, |
|
94 | 38 | new Buffer($sBin, null, $math) |
|
95 | 2 | ]) |
|
96 | 2 | ]); |
|
97 | } |
||
98 | |||
99 | /** |
||
100 | * @param Parser $parser |
||
101 | * @return Signature |
||
102 | * @throws ParserOutOfRange |
||
103 | */ |
||
104 | 190 | public function fromParser(Parser $parser) |
|
105 | { |
||
106 | try { |
||
107 | 190 | list (, $inner) = $this->getOuterTemplate()->parse($parser); |
|
108 | 158 | list (, $r, , $s) = $this->getInnerTemplate()->parse(new Parser($inner)); |
|
109 | /** @var Buffer $r */ |
||
110 | /** @var Buffer $s */ |
||
111 | |||
112 | 154 | return new Signature( |
|
113 | 154 | $this->ecAdapter, |
|
114 | 154 | $r->getGmp(), |
|
115 | 152 | $s->getGmp() |
|
116 | ); |
||
117 | 44 | } catch (ParserOutOfRange $e) { |
|
118 | 40 | 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 | 190 | public function parse($string) |
|
133 | } |
||
134 |