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 BigInt inv_for_d = lcm(m_p - 1, m_q - 1); 170 if (m_e.isEven()) 171 inv_for_d >>= 1; 172 173 m_d = inverseMod(m_e, inv_for_d); 174 } 175 176 m_d1 = m_d % (m_p - 1); 177 m_d2 = m_d % (m_q - 1); 178 m_c = inverseMod(m_q, m_p); 179 180 loadCheck(rng); 181 182 } 183 184 override AlgorithmIdentifier pkcs8AlgorithmIdentifier() const { return super.algorithmIdentifier(); } 185 186 /* 187 * Check IF Scheme Private Parameters 188 */ 189 override bool checkKey(RandomNumberGenerator rng, bool strong) const 190 { 191 if (m_check_key) 192 return m_check_key(this, rng, strong); 193 return checkKeyImpl(rng, strong); 194 } 195 196 final bool checkKeyImpl(RandomNumberGenerator rng, bool strong) const 197 { 198 auto p_q = m_p*m_q; 199 if (m_n < 35 || m_n.isEven() || m_e < 2 || m_d < 2 || m_p < 3 || m_q < 3 || p_q != m_n) 200 return false; 201 202 if (m_d1 != m_d % (m_p - 1) || m_d2 != m_d % (m_q - 1) || m_c != inverseMod(m_q, m_p)) 203 return false; 204 205 const size_t prob = (strong) ? 56 : 12; 206 207 if (!isPrime(m_p, rng, prob) || !isPrime(m_q, rng, prob)) 208 return false; 209 return true; 210 } 211 212 /** 213 * Get the first prime p. 214 * Returns: prime p 215 */ 216 ref const(BigInt) getP() const { return m_p; } 217 218 /** 219 * Get the second prime q. 220 * Returns: prime q 221 */ 222 ref const(BigInt) getQ() const { return m_q; } 223 224 /** 225 * Get d with exp * d = 1 mod (p - 1, q - 1). 226 * Returns: d 227 */ 228 ref const(BigInt) getD() const { return m_d; } 229 230 ref const(BigInt) getC() const { return m_c; } 231 ref const(BigInt) getD1() const { return m_d1; } 232 ref const(BigInt) getD2() const { return m_d2; } 233 234 SecureVector!ubyte pkcs8PrivateKey() const 235 { 236 return DEREncoder() 237 .startCons(ASN1Tag.SEQUENCE) 238 .encode(cast(size_t)(0)) 239 .encode(m_n) 240 .encode(m_e) 241 .encode(m_d) 242 .encode(m_p) 243 .encode(m_q) 244 .encode(m_d1) 245 .encode(m_d2) 246 .encode(m_c) 247 .endCons() 248 .getContents(); 249 } 250 251 protected: 252 BigInt m_d, m_p, m_q, m_d1, m_d2, m_c; 253 }