1 /**
2 * ECDSA Signature
3 * 
4 * Copyright:
5 * (C) 2007 Falko Strenzke, FlexSecure GmbH
6 * (C) 2008-2010 Jack Lloyd
7 * (C) 2014-2015 Etienne Cimon
8 *
9 * License:
10 * Botan is released under the Simplified BSD License (see LICENSE.md)
11 */
12 module botan.cert.cvc.ecdsa_sig;
13 
14 import botan.constants;
15 static if (BOTAN_HAS_CARD_VERIFIABLE_CERTIFICATES):
16 
17 import botan.math.bigint.bigint;
18 import botan.asn1.der_enc;
19 import botan.asn1.ber_dec;
20 import botan.utils.mem_ops;
21 
22 /**
23 * Class representing an ECDSA signature
24 */
25 class ECDSASignature
26 {
27 public:
28     this() {}
29 
30     this()(auto const ref BigInt r, auto const ref BigInt s) {
31         m_r = r.dup;
32         m_s = s.dup;
33     }
34 
35     this(const ref Vector!ubyte ber)
36     {
37         BERDecoder(ber)
38                 .startCons(ASN1Tag.SEQUENCE)
39                 .decode(m_r)
40                 .decode(m_s)
41                 .endCons()
42                 .verifyEnd();
43     }
44 
45     @property ECDSASignature dup() const
46     {
47         return new ECDSASignature(m_r.dup, m_s.dup);
48     }
49 
50     ref const(BigInt) getR() const { return m_r; }
51     ref const(BigInt) getS() const { return m_s; }
52 
53     /**
54     * return the r||s
55     */
56     const(Vector!ubyte) getConcatenation() const
57     {
58         // use the larger
59         const size_t enc_len = m_r > m_s ? m_r.bytes() : m_s.bytes();
60         
61         
62         SecureVector!ubyte result = BigInt.encode1363(m_r, enc_len);
63         result ~= BigInt.encode1363(m_s, enc_len);
64         return unlock(result);
65     }
66 
67     Vector!ubyte DER_encode() const
68     {
69         return DEREncoder()
70                 .startCons(ASN1Tag.SEQUENCE)
71                 .encode(getR())
72                 .encode(getS())
73                 .endCons()
74                 .getContentsUnlocked();
75     }
76 
77 
78     bool opEquals(in ECDSASignature other) const
79     {
80         return (getR() == other.getR() && getS() == other.getS());
81     }
82 
83     int opCmp(in ECDSASignature rhs) const
84     {
85         if (this == rhs) return 0;
86         else return -1;
87     }
88 
89 private:
90     BigInt m_r;
91     BigInt m_s;
92 }
93 
94 ECDSASignature decodeConcatenation(const ref Vector!ubyte concat)
95 {
96     if (concat.length % 2 != 0)
97         throw new InvalidArgument("Erroneous length of signature");
98     
99     const size_t rs_len = concat.length / 2;
100     
101     BigInt r = BigInt.decode(concat.ptr, rs_len);
102     BigInt s = BigInt.decode(concat.ptr + rs_len, rs_len);
103     
104     return new ECDSASignature(r, s);
105 }