diff --git a/lib/modules/Crypto/rsa.pike b/lib/modules/Crypto/rsa.pike index b9d317225eef653203d96683cca21b02bb686a5b..f7dc3443fddd87ee8694d307833fa2e92c98da0a 100644 --- a/lib/modules/Crypto/rsa.pike +++ b/lib/modules/Crypto/rsa.pike @@ -1,76 +1,224 @@ -/* $Id: rsa.pike,v 1.19 2000/05/04 11:22:56 grubba Exp $ +/* $Id: rsa.pike,v 1.20 2000/05/04 16:04:41 grubba Exp $ * * Follow the PKCS#1 standard for padding and encryption. */ #if constant(Gmp.mpz) -inherit Crypto._rsa; - #define bignum object(Gmp.mpz) #define BIGNUM (Gmp.mpz) -bignum get_prime(int bits, function r) +#ifdef USE_RSA_WRAPPER +static class rsa_wrapper { - int len = (bits + 7) / 8; - int bit_to_set = 1 << ( (bits - 1) % 8); + object _rsa_c; + object _rsa_pike; - object p; - - do { - string s = r(len); - p = BIGNUM(sprintf("%c%s", (s[0] & (bit_to_set - 1)) - | bit_to_set, s[1..]), - 256)->next_prime(); - } while (p->size() > bits); - - return p; -} + string n = "n is not in the API"; + string e = "e is not in the API"; + string d = "d is not in the API"; + string size = "size is not in the API"; -bignum rsa_pad(string message, int type, mixed|void random) -{ - string cookie; - int len; + string p = "p is not in the API"; + string q = "q is not in the API"; - len = size - 3 - strlen(message); - /* write(sprintf("%d, %d, %d, %s", len, size, strlen(message), message)); */ - if (len < 8) - throw( ({ "Crypto.rsa->rsa_pad: Too large block.\n", - backtrace() }) ); + object set_public_key(bignum modulo, bignum pub) + { + _rsa_pike->set_public_key(modulo, pub); + _rsa_c->set_public_key(modulo, pub); - switch(type) - { - case 1: - cookie = sprintf("%@c", replace(allocate(len), 0, 0xff)); - break; - case 2: - if (random) - cookie = replace(random(len), "\0", "\1"); - else - cookie = sprintf("%@c", Array.map(allocate(len), lambda(int dummy) - { - return predef::random(255) + 1; - } )); - break; - default: - throw( ({ "Crypto.rsa->rsa_pad: Unknown type.\n", - backtrace() }) ); - } - return BIGNUM(sprintf("%c", type) + cookie + "\0" + message, 256); + return this_object(); + } + + object set_private_key(bignum priv, array(bignum)|void extra) + { + _rsa_pike->set_private_key(priv, extra); + _rsa_c->set_private_key(priv, extra); + + return this_object(); + } + + int query_blocksize() + { + int res1 = _rsa_pike->query_blocksize(); + int res2 = _rsa_c->query_blocksize(); + + if (res1 != res2) { + werror("RSA: query_blocksize() failed!\n"); + error(sprintf("res1:%O != res2:%O\n", res1, res2)); + } + return res1; + } + + bignum rsa_pad(string message, int type, mixed|void random) + { + bignum res1 = _rsa_pike->rsa_pad(message, type, random); + bignum res2 = _rsa_c->rsa_pad(message, type, random); + + if (res1 != res2) { + werror("RSA: rsa_pad() failed!\n"); + error(sprintf("res1:%O != res2:%O\n", res1, res2)); + } + return res1; + } + + string rsa_unpad(bignum block, int type) + { + string res1 = _rsa_pike->rsa_unpad(block, type); + string res2 = _rsa_c->rsa_unpad(block, type); + + if (res1 != res2) { + werror("RSA: rsa_unpad() failed!\n"); + error(sprintf("res1:%O != res2:%O\n", res1, res2)); + } + return res1; + } + + bignum raw_sign(string digest) + { + bignum res1 = _rsa_pike->raw_sign(digest); + bignum res2 = Gmp.mpz(_rsa_c->cooked_sign(digest), 256); + + if (res1 != res2) { + werror("RSA: rsa_sign() failed!\n"); + error(sprintf("res1:%O != res2:%O\n", res1, res2)); + } + return res1; + } + + string cooked_sign(string digest) + { + string res1 = _rsa_pike->cooked_sign(digest); + string res2 = _rsa_c->cooked_sign(digest); + + if (res1 != res2) { + werror("RSA: cooked_sign() failed!\n"); + error(sprintf("res1:%O != res2:%O\n", res1, res2)); + } + return res1; + } + + int raw_verify(string digest, bignum s) + { + int res1 = _rsa_pike->cooked_sign(digest, s); + int res2 = _rsa_c->cooked_sign(digest, s); + + if (res1 != res2) { + werror("RSA: rsa_verify() failed!\n"); + error(sprintf("res1:%O != res2:%O\n", res1, res2)); + } + return res1; + } + + string encrypt(string s, mixed|void r) + { + string res1 = _rsa_pike->encrypt(s, r); + string res2 = _rsa_c->encrypt(s, r); + + if (res1 != res2) { + werror("RSA: encrypt() failed!\n"); + error(sprintf("res1:%O != res2:%O\n", res1, res2)); + } + return res1; + } + + string decrypt(string s) + { + string res1 = _rsa_pike->decrypt(s); + string res2 = _rsa_c->decrypt(s); + + if (res1 != res2) { + werror("RSA: decrypt() failed!\n"); + error(sprintf("res1:%O != res2:%O\n", res1, res2)); + } + return res1; + } + + int rsa_size() + { + int res1 = _rsa_pike->rsa_size(); + int res2 = _rsa_c->rsa_size(); + + if (res1 != res2) { + werror("RSA: rsa_size() failed!\n"); + error(sprintf("res1:%O != res2:%O\n", res1, res2)); + } + return res1; + } + + int public_key_equal(object rsa_wrapper) + { + int res1 = _rsa_pike->public_key_equal(rsa_wrapper->_rsa_pike); + int res2 = _rsa_c->public_key_equal(rsa_wrapper->_rsa_c); + + if (res1 != res2) { + werror("RSA: public_key_equal() failed!\n"); + error(sprintf("res1:%O != res2:%O\n", res1, res2)); + } + return res1; + } + + object get_n() + { + object res1 = _rsa_pike->get_n(); + object res2 = BIGNUM(_rsa_c->cooked_get_n(), 256); + + if (res1 != res2) { + werror("RSA: get_n() failed!\n"); + error(sprintf("res1:%O != res2:%O\n", res1, res2)); + } + return res1; + } + + object get_e() + { + object res1 = _rsa_pike->get_e(); + object res2 = BIGNUM(_rsa_c->cooked_get_e(), 256); + + if (res1 != res2) { + werror("RSA: get_e() failed!\n"); + error(sprintf("res1:%O != res2:%O\n", res1, res2)); + } + return res1; + } + + static void create() + { + werror("RSA: Using rsa_wrapper\n"); + _rsa_c = _Crypto._rsa(); + _rsa_pike = ((program)"_rsa.pike")(); + } } +inherit rsa_wrapper; +#else /* !USE_RSA_WRAPPER */ +#ifdef USE_PIKE_RSA +inherit "_rsa.pike"; +#else /* !USE_PIKE_RSA */ +inherit Crypto._rsa; +#endif /* USE_PIKE_RSA */ +#endif /* !USE_RSA_WRAPPER */ -#if constant(_Crypto.rsa) +#if !defined(USE_PIKE_RSA) && !defined(USE_RSA_WRAPPER) && constant(_Crypto._rsa) // Only the cooked variant is implemented in C. */ -object raw_sign(string digest) +bignum raw_sign(string digest) { return BIGNUM(cooked_sign(digest), 256); } -#endif /* constant(_Crypto.rsa) */ + +bignum get_n() +{ + return BIGNUM(cooked_get_n(), 256); +} + +bignum get_e() +{ + return BIGNUM(cooked_get_e(), 256); +} +#endif /* !USE_PIKE_RSA && !USE_RSA_WRAPPER && constant(_Crypto._rsa) */ object sign(string message, program h) { - string digest = Standards.PKCS.Signature.build_digestinfo(message, h()); - return raw_sign(digest); + return raw_sign(Standards.PKCS.Signature.build_digestinfo(message, h())); } int verify(string msg, program h, object sign) @@ -104,6 +252,23 @@ int sha_verify(string message, string signature) return raw_verify(s, BIGNUM(signature, 256)); } +bignum get_prime(int bits, function r) +{ + int len = (bits + 7) / 8; + int bit_to_set = 1 << ( (bits - 1) % 8); + + object p; + + do { + string s = r(len); + p = BIGNUM(sprintf("%c%s", (s[0] & (bit_to_set - 1)) + | bit_to_set, s[1..]), + 256)->next_prime(); + } while (p->size() > bits); + + return p; +} + object generate_key(int bits, function|void r) { if (!r) @@ -118,8 +283,8 @@ object generate_key(int bits, function|void r) do { - p = get_prime(s1, r); - q = get_prime(s2, r); + object p = get_prime(s1, r); + object q = get_prime(s2, r); bignum phi = Gmp.mpz(p-1)*Gmp.mpz(q-1); array gs; /* gcd(pub, phi), and pub^-1 mod phi */ @@ -134,7 +299,7 @@ object generate_key(int bits, function|void r) gs[1] += phi; set_public_key(p * q, pub); - set_private_key(gs[1]); + set_private_key(gs[1], ({ p, q })); // werror(sprintf("p = %s\nq = %s\ne = %s\nd = %s\n", // p->digits(), q->digits(), pub->digits(), gs[1]->digits())); @@ -142,6 +307,12 @@ object generate_key(int bits, function|void r) return this_object(); } +/* + * Block cipher compatibility. + */ + +int encrypt_mode; /* For block cipher compatible functions */ + object set_encrypt_key(array(bignum) key) { set_public_key(key[0], key[1]);