1 /** 2 * IF 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.if_algo; 12 13 import botan.constants; 14 static if (BOTAN_HAS_PUBLIC_KEY_CRYPTO): 15 16 import botan.rng.rng; 17 public import botan.pubkey.pubkey; 18 import botan.math.bigint.bigint; 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.asn1.der_enc; 24 import botan.asn1.ber_dec; 25 26 /** 27 * This class represents public keys 28 * of integer factorization based (IF) public key schemes. 29 */ 30 class IFSchemePublicKey : PublicKey 31 { 32 public: 33 this(T)(in T options, in AlgorithmIdentifier, const ref SecureVector!ubyte key_bits) 34 { 35 decodeOptions(options); 36 BERDecoder(key_bits) 37 .startCons(ASN1Tag.SEQUENCE) 38 .decode(m_n) 39 .decode(m_e) 40 .verifyEnd() 41 .endCons(); 42 } 43 44 this(T)(in T options, auto ref BigInt n, auto ref BigInt e) 45 { 46 decodeOptions(options); 47 m_n = n.move(); 48 m_e = e.move(); 49 } 50 51 final void decodeOptions(T)(in T options) { 52 static if (__traits(hasMember, T, "checkKey")) 53 m_check_key = &options.checkKey; 54 static if (__traits(hasMember, T, "algoName")) 55 m_algo_name = options.algoName; 56 else static assert(false, "No algoName found in " ~ T.stringof); 57 } 58 59 60 /// Used for object casting to the right type in the factory. 61 final override @property string algoName() const { 62 return m_algo_name; 63 } 64 65 /* 66 * Check IF Scheme Public Parameters 67 */ 68 override bool checkKey(RandomNumberGenerator rng, bool strong) const 69 { 70 if (m_n < 35 || m_n.isEven() || m_e < 2) 71 return false; 72 return true; 73 } 74 75 76 final AlgorithmIdentifier algorithmIdentifier() const 77 { 78 return AlgorithmIdentifier(getOid(), AlgorithmIdentifierImpl.USE_NULL_PARAM); 79 } 80 81 final Vector!ubyte x509SubjectPublicKey() const 82 { 83 auto der_enc = DEREncoder() 84 .startCons(ASN1Tag.SEQUENCE) 85 .encode(m_n) 86 .encode(m_e); 87 der_enc.endCons(); 88 return der_enc.getContentsUnlocked(); 89 } 90 91 /** 92 * Returns: public modulus 93 */ 94 final ref const(BigInt) getN() const { return m_n; } 95 96 /** 97 * Returns: public exponent 98 */ 99 final ref const(BigInt) getE() const { return m_e; } 100 101 final size_t maxInputBits() const { return (m_n.bits() - 1); } 102 103 final override size_t messagePartSize() const { 104 return 0; 105 } 106 107 final override size_t messageParts() const { 108 return 1; 109 } 110 111 override final size_t estimatedStrength() const 112 { 113 return dlWorkFactor(m_n.bits()); 114 } 115 116 protected: 117 BigInt m_n, m_e; 118 119 // options 120 string m_algo_name; 121 bool function(in IFSchemePrivateKey, RandomNumberGenerator, bool) m_check_key; 122 } 123 124 /** 125 * This class represents public keys 126 * of integer factorization based (IF) public key schemes. 127 */ 128 final class IFSchemePrivateKey : IFSchemePublicKey, PrivateKey 129 { 130 public: 131 this(T)(in T options, RandomNumberGenerator rng, 132 in AlgorithmIdentifier aid, const ref SecureVector!ubyte key_bits) 133 { 134 BigInt n, e; 135 BERDecoder(key_bits).startCons(ASN1Tag.SEQUENCE) 136 .decodeAndCheck!size_t(0, "Unknown PKCS #1 key format version") 137 .decode(n) 138 .decode(e) 139 .decode(m_d) 140 .decode(m_p) 141 .decode(m_q) 142 .decode(m_d1) 143 .decode(m_d2) 144 .decode(m_c) 145 .endCons(); 146 147 super(options, n, e); 148 149 loadCheck(rng); 150 } 151 152 this(T)(in T options, 153 RandomNumberGenerator rng, 154 BigInt prime1, 155 BigInt prime2, 156 BigInt exp, 157 BigInt d_exp, 158 BigInt mod) 159 { 160 m_p = prime1.move(); 161 m_q = prime2.move(); 162 BigInt n = mod.isNonzero() ? mod.move() : m_p * m_q; 163 super(options, n.move(), exp.move()); // defines m_e and m_n 164 165 m_d = d_exp.move(); 166 167 if (m_d == 0) 168 { 169 auto mp_minus_1 = m_p - 1; 170 auto mq_minus_1 = m_q - 1; 171 BigInt inv_for_d = lcm(&mp_minus_1, &mq_minus_1); 172 if (m_e.isEven()) 173 inv_for_d >>= 1; 174 175 m_d = inverseMod(&m_e, &inv_for_d); 176 } 177 178 m_d1 = m_d % (m_p - 1); 179 m_d2 = m_d % (m_q - 1); 180 m_c = inverseMod(&m_q, &m_p); 181 182 loadCheck(rng); 183 184 } 185 186 override AlgorithmIdentifier pkcs8AlgorithmIdentifier() const { return super.algorithmIdentifier(); } 187 188 /* 189 * Check IF Scheme Private Parameters 190 */ 191 override bool checkKey(RandomNumberGenerator rng, bool strong) const 192 { 193 if (m_check_key) 194 return m_check_key(this, rng, strong); 195 return checkKeyImpl(rng, strong); 196 } 197 198 final bool checkKeyImpl(RandomNumberGenerator rng, bool strong) const 199 { 200 auto p_q = m_p*m_q; 201 if (m_n < 35 || m_n.isEven() || m_e < 2 || m_d < 2 || m_p < 3 || m_q < 3 || p_q != m_n) 202 return false; 203 204 if (m_d1 != m_d % (m_p - 1) || m_d2 != m_d % (m_q - 1) || m_c != inverseMod(&m_q, &m_p)) 205 return false; 206 207 const size_t prob = (strong) ? 56 : 12; 208 209 if (!isPrime(&m_p, rng, prob) || !isPrime(&m_q, rng, prob)) 210 return false; 211 return true; 212 } 213 214 /** 215 * Get the first prime p. 216 * Returns: prime p 217 */ 218 ref const(BigInt) getP() const { return m_p; } 219 220 /** 221 * Get the second prime q. 222 * Returns: prime q 223 */ 224 ref const(BigInt) getQ() const { return m_q; } 225 226 /** 227 * Get d with exp * d = 1 mod (p - 1, q - 1). 228 * Returns: d 229 */ 230 ref const(BigInt) getD() const { return m_d; } 231 232 ref const(BigInt) getC() const { return m_c; } 233 ref const(BigInt) getD1() const { return m_d1; } 234 ref const(BigInt) getD2() const { return m_d2; } 235 236 SecureVector!ubyte pkcs8PrivateKey() const 237 { 238 return DEREncoder() 239 .startCons(ASN1Tag.SEQUENCE) 240 .encode(cast(size_t)(0)) 241 .encode(m_n) 242 .encode(m_e) 243 .encode(m_d) 244 .encode(m_p) 245 .encode(m_q) 246 .encode(m_d1) 247 .encode(m_d2) 248 .encode(m_c) 249 .endCons() 250 .getContents(); 251 } 252 253 protected: 254 BigInt m_d, m_p, m_q, m_d1, m_d2, m_c; 255 }