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 }