1 /** 2 * DL Scheme 3 * 4 * Copyright: 5 * (C) 1999-2007 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 module botan.pubkey.algo.dl_algo; 12 13 import botan.constants; 14 static if (BOTAN_HAS_PUBLIC_KEY_CRYPTO): 15 16 public import botan.pubkey.algo.dl_group; 17 public import botan.pubkey.pubkey; 18 import botan.utils.mem_ops; 19 import botan.pubkey.x509_key; 20 import botan.pubkey.pkcs8; 21 import botan.math.numbertheory.numthry; 22 import botan.pubkey.workfactor; 23 import botan.rng.rng; 24 import botan.asn1.der_enc; 25 import botan.asn1.ber_dec; 26 27 /** 28 * This class represents discrete logarithm (DL) public keys. 29 */ 30 class DLSchemePublicKey : PublicKey 31 { 32 public: 33 override bool checkKey(RandomNumberGenerator rng, bool strong) const 34 { 35 return (cast(DLSchemePublicKey)this).checkKey(rng, strong); 36 } 37 38 final bool checkKey(RandomNumberGenerator rng, bool strong) 39 { 40 if (m_y < 2 || m_y >= groupP()) 41 return false; 42 if (!m_group.verifyGroup(rng, strong)) 43 return false; 44 return true; 45 } 46 47 final void decodeOptions(T)(in T options) { 48 static if (__traits(hasMember, T, "checkKey")) 49 m_check_key = &options.checkKey; 50 static if (__traits(hasMember, T, "msgParts")) 51 m_msg_parts = options.msgParts; 52 53 static if (__traits(hasMember, T, "format")) 54 m_format = options.format; 55 else static assert(false, "No format found in " ~ T.stringof); 56 57 static if (__traits(hasMember, T, "algoName")) 58 m_algo_name = options.algoName; 59 else static assert(false, "No algoName found in " ~ T.stringof); 60 61 } 62 63 /// Used for object casting to the right type in the factory. 64 final override @property string algoName() const { 65 return m_algo_name; 66 } 67 68 final override size_t messageParts() const { 69 return m_msg_parts; 70 } 71 72 final override size_t maxInputBits() const { 73 if (m_msg_parts == 1 && algoName != "DH" && algoName != "ElGamal") 74 return 0; 75 76 if (algoName == "NR" || algoName == "ElGamal") 77 return groupQ().bits() - 1; 78 79 return groupQ().bits(); 80 } 81 82 final size_t messagePartSize() const { 83 if (m_msg_parts == 1) return 0; 84 return groupQ().bytes(); 85 } 86 87 final AlgorithmIdentifier algorithmIdentifier() const 88 { 89 return AlgorithmIdentifier(getOid(), m_group.DER_encode(m_format)); 90 } 91 92 final Vector!ubyte x509SubjectPublicKey() const 93 { 94 return DEREncoder().encode(m_y).getContentsUnlocked(); 95 } 96 97 /* 98 * Return the public value for key agreement 99 */ 100 Vector!ubyte publicValue() const 101 { 102 return unlock(BigInt.encode1363(getY(), groupP().bytes())); 103 } 104 105 /** 106 * Get the DL domain parameters of this key. 107 * Returns: DL domain parameters of this key 108 */ 109 final ref const(DLGroup) getDomain() const { return m_group; } 110 111 /** 112 * Get the public value m_y with m_y = g^m_x mod p where m_x is the secret key. 113 */ 114 final ref const(BigInt) getY() const { return m_y; } 115 116 /** 117 * Set the value m_y 118 */ 119 final void setY(BigInt y) { m_y = y.move(); } 120 121 /** 122 * Get the prime p of the underlying DL m_group. 123 * Returns: prime p 124 */ 125 final ref const(BigInt) groupP() const { return m_group.getP(); } 126 127 /** 128 * Get the prime q of the underlying DL m_group. 129 * Returns: prime q 130 */ 131 final ref const(BigInt) groupQ() const { return m_group.getQ(); } 132 133 /** 134 * Get the generator g of the underlying DL m_group. 135 * Returns: generator g 136 */ 137 final ref const(BigInt) groupG() const { return m_group.getG(); } 138 139 override final size_t estimatedStrength() const 140 { 141 return dlWorkFactor(m_group.getP().bits()); 142 } 143 144 this(T)(in T options, 145 in AlgorithmIdentifier alg_id, 146 auto const ref SecureVector!ubyte key_bits) 147 { 148 decodeOptions(options); 149 m_group.BER_decode(alg_id.parameters, m_format); 150 BERDecoder(key_bits).decode(m_y); 151 } 152 153 this(T)(in T options, DLGroup grp, BigInt y1) 154 { 155 decodeOptions(options); 156 m_group = grp.move; 157 m_y = y1.move; 158 } 159 160 protected: 161 /** 162 * The DL public key 163 */ 164 BigInt m_y; 165 166 /** 167 * The DL group 168 */ 169 DLGroup m_group; 170 171 /// options 172 DLGroup.Format m_format; 173 string m_algo_name; 174 short m_msg_parts = 1; 175 bool function(in DLSchemePrivateKey, RandomNumberGenerator, bool) m_check_key; 176 } 177 178 /** 179 * This class represents discrete logarithm (DL) private keys. 180 */ 181 final class DLSchemePrivateKey : DLSchemePublicKey, PrivateKey, PKKeyAgreementKey 182 { 183 public: 184 185 override AlgorithmIdentifier pkcs8AlgorithmIdentifier() const { return super.algorithmIdentifier(); } 186 187 override bool checkKey(RandomNumberGenerator rng, bool strong) const 188 { 189 if (m_check_key) 190 return m_check_key(this, rng, strong); 191 192 return checkKeyImpl(rng, strong); 193 } 194 195 final bool checkKeyImpl(RandomNumberGenerator rng, bool strong) const 196 { 197 const BigInt* p = &groupP(); 198 const BigInt* g = &groupG(); 199 if (m_y < 2 || m_y >= *p || m_x < 2 || m_x >= *p) { 200 return false; 201 } 202 if (!m_group.verifyGroup(rng, strong)) { 203 return false; 204 } 205 206 if (!strong) 207 return true; 208 209 if (m_y != powerMod(g, &m_x, p)) 210 { 211 return false; 212 } 213 return true; 214 } 215 216 /** 217 * Get the secret key m_x. 218 * Returns: secret key 219 */ 220 ref const(BigInt) getX() const { return m_x; } 221 222 SecureVector!ubyte pkcs8PrivateKey() const 223 { 224 return DEREncoder().encode(m_x).getContents(); 225 } 226 227 this(T)(in T options, in AlgorithmIdentifier alg_id, 228 const ref SecureVector!ubyte key_bits) 229 { 230 BERDecoder(key_bits).decode(m_x); 231 DLGroup grp; 232 grp.BER_decode(alg_id.parameters, options.format); 233 BigInt y = powerMod(&grp.getG(), &m_x, &grp.getP()); 234 super(options, grp.move, y.move); 235 } 236 237 this(T)(in T options, 238 DLGroup grp, 239 BigInt y1, BigInt x_arg) 240 { 241 //logTrace("grp: ", grp.toString()); 242 m_x = x_arg.move; 243 //logTrace("x: ", m_x.toString()); 244 super(options, grp.move, y1.move); 245 } 246 247 /* 248 * Return the public value for key agreement 249 */ 250 override Vector!ubyte publicValue() const 251 { 252 return super.publicValue(); 253 } 254 255 256 package: 257 /** 258 * The DL private key 259 */ 260 BigInt m_x; 261 }