1 /** 2 * RFC 6979 Deterministic Nonce Generator 3 * 4 * Copyright: 5 * (C) 2014 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.rfc6979; 12 13 import botan.constants; 14 static if (BOTAN_HAS_PUBLIC_KEY_CRYPTO && BOTAN_HAS_RFC6979_GENERATOR): 15 16 import botan.libstate.libstate; 17 import botan.math.bigint.bigint; 18 import botan.rng.hmac_drbg; 19 import botan.utils.types; 20 21 /** 22 * Params: 23 * x = the secret (EC)DSA key 24 * q = the group order 25 * h = the message hash already reduced mod q 26 * hash = the hash function used to generate h 27 */ 28 BigInt generateRfc6979Nonce(const ref BigInt x, const ref BigInt q, const ref BigInt h, in string hash) 29 { 30 AlgorithmFactory af = globalState().algorithmFactory(); 31 32 auto rng = scoped!HMAC_DRBG(af.makeMac("HMAC(" ~ hash ~ ")"), null); 33 34 const size_t qlen = q.bits(); 35 const size_t rlen = qlen / 8 + (qlen % 8 ? 1 : 0); 36 37 SecureVector!ubyte input = BigInt.encode1363(x, rlen); 38 39 input ~= BigInt.encode1363(h, rlen); 40 41 rng.addEntropy(input.ptr, input.length); 42 43 BigInt k; 44 45 SecureVector!ubyte kbits = SecureVector!ubyte(rlen); 46 47 while (k == 0 || k >= q) 48 { 49 rng.randomize(kbits.ptr, kbits.length); 50 k = BigInt.decode(kbits) >> (8*rlen - qlen); 51 } 52 53 return k; 54 } 55 56 static if (BOTAN_TEST): 57 import botan.test; 58 import botan.codec.hex; 59 60 size_t rfc6979Testcase(string q_str, 61 string x_str, 62 string h_str, 63 string exp_k_str, 64 string hash, 65 size_t testcase) 66 { 67 const BigInt q = BigInt(q_str); 68 const BigInt x = BigInt(x_str); 69 const BigInt h = BigInt(h_str); 70 const BigInt exp_k = BigInt(exp_k_str); 71 72 const BigInt gen_k = generateRfc6979Nonce(x, q, h, hash); 73 74 if (gen_k != exp_k) 75 { 76 logTrace("RFC 6979 test #", testcase, " failed; generated k=", gen_k.toString()); 77 return 1; 78 } 79 80 return 0; 81 } 82 83 static if (BOTAN_HAS_TESTS && !SKIP_RFC6979_TEST) unittest 84 { 85 logDebug("Testing rfc6979.d ..."); 86 87 size_t fails = 0; 88 89 // From RFC 6979 A.1.1 90 fails += rfc6979Testcase("0x4000000000000000000020108A2E0CC0D99F8A5EF", 91 "0x09A4D6792295A7F730FC3F2B49CBC0F62E862272F", 92 "0x01795EDF0D54DB760F156D0DAC04C0322B3A204224", 93 "0x23AF4074C90A02B3FE61D286D5C87F425E6BDD81B", 94 "SHA-256", 1); 95 96 // DSA 1024 bits test #1 97 fails += rfc6979Testcase("0x996F967F6C8E388D9E28D01E205FBA957A5698B1", 98 "0x411602CB19A6CCC34494D79D98EF1E7ED5AF25F7", 99 "0x8151325DCDBAE9E0FF95F9F9658432DBEDFDB209", 100 "0x7BDB6B0FF756E1BB5D53583EF979082F9AD5BD5B", 101 "SHA-1", 2); 102 103 testReport("RFC 6979", 2, fails); 104 }