diff --git a/.gitattributes b/.gitattributes index d16fb4b3c12d13ea39379a07558d3db20ca9dd71..19bb79bfc060a9d18be4e09a78a7a7903e35bc10 100644 --- a/.gitattributes +++ b/.gitattributes @@ -34,6 +34,7 @@ testfont binary /lib/master.pike.in foreign_ident /lib/modules/ADT.pmod/Queue.pike foreign_ident /lib/modules/ADT.pmod/Table.pmod foreign_ident +/lib/modules/Crypto/_rsa.pike foreign_ident /lib/modules/Crypto/des3.pike foreign_ident /lib/modules/Crypto/des3_cbc.pike foreign_ident /lib/modules/Crypto/des_cbc.pike foreign_ident diff --git a/lib/modules/Crypto/_rsa.pike b/lib/modules/Crypto/_rsa.pike new file mode 100644 index 0000000000000000000000000000000000000000..8c124f9bef6d8ba51f103c160b21407af36b7d22 --- /dev/null +++ b/lib/modules/Crypto/_rsa.pike @@ -0,0 +1,121 @@ +/* $Id: _rsa.pike,v 1.1 2000/05/04 11:22:56 grubba Exp $ + * + * Follow the PKCS#1 standard for padding and encryption. + */ + +#if constant(Gmp.mpz) + +#define bignum object(Gmp.mpz) +#define BIGNUM (Gmp.mpz) + +bignum n; /* modulo */ +bignum e; /* public exponent */ +bignum d; /* private exponent (if known) */ +int size; + +/* Extra info associated with a private key. Not currently used. */ + +bignum p; +bignum q; + +int encrypt_mode; /* For block cipher compatible functions */ + +object set_public_key(bignum modulo, bignum pub) +{ + n = modulo; + e = pub; + size = n->size(256); + if (size < 12) + throw( ({ "Crypto.rsa->set_public_key: Too small modulo.\n", + backtrace() }) ); + return this_object(); +} + +object set_private_key(bignum priv, array(bignum)|void extra) +{ + d = priv; + if (extra) + { + p = extra[0]; + q = extra[1]; + } + return this_object(); +} + +int query_blocksize() { return size - 3; } + +bignum rsa_pad(string message, int type, mixed|void random) +{ + string cookie; + int len; + + 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() }) ); + + 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); +} + +string rsa_unpad(bignum block, int type) +{ + string s = block->digits(256); + int i = search(s, "\0"); + + if ((i < 9) || (strlen(s) != (size - 1)) || (s[0] != type)) + return 0; + return s[i+1..]; +} + +object raw_sign(string digest) +{ + return rsa_pad(digest, 1, 0)->powm(d, n); +} + +string cooked_sign(string digest) +{ + return raw_sign(digest)->digits(256); +} + +int raw_verify(string digest, object s) +{ + return s->powm(e, n) == rsa_pad(digest, 1, 0); +} + +string encrypt(string s, mixed|void r) +{ + return rsa_pad(s, 2, r)->powm(e, n)->digits(256); +} + +string decrypt(string s) +{ + return rsa_unpad(BIGNUM(s, 256)->powm(d, n), 2); +} + +int rsa_size() { return n->size(); } + +int public_key_equal (object rsa) +{ + return n == rsa->n && e == rsa->e; +} + +#endif diff --git a/lib/modules/Crypto/rsa.pike b/lib/modules/Crypto/rsa.pike index df5163ad678d85cbbb0766176a0883fc8e99cb1c..b9d317225eef653203d96683cca21b02bb686a5b 100644 --- a/lib/modules/Crypto/rsa.pike +++ b/lib/modules/Crypto/rsa.pike @@ -1,49 +1,15 @@ -/* $Id: rsa.pike,v 1.18 1999/08/27 15:33:37 grubba Exp $ +/* $Id: rsa.pike,v 1.19 2000/05/04 11:22:56 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) -import Standards.PKCS; - -bignum n; /* modulo */ -bignum e; /* public exponent */ -bignum d; /* private exponent (if known) */ -int size; - -/* Extra info associated with a private key. Not currently used. */ - -bignum p; -bignum q; - -int encrypt_mode; /* For block cipher compatible functions */ - -object set_public_key(bignum modulo, bignum pub) -{ - n = modulo; - e = pub; - size = n->size(256); - if (size < 12) - throw( ({ "Crypto.rsa->set_public_key: Too small modulo.\n", - backtrace() }) ); - return this_object(); -} - -object set_private_key(bignum priv, array(bignum)|void extra) -{ - d = priv; - if (extra) - { - p = extra[0]; - q = extra[1]; - } - return this_object(); -} - bignum get_prime(int bits, function r) { int len = (bits + 7) / 8; @@ -61,8 +27,6 @@ bignum get_prime(int bits, function r) return p; } -int query_blocksize() { return size - 3; } - bignum rsa_pad(string message, int type, mixed|void random) { string cookie; @@ -95,61 +59,41 @@ bignum rsa_pad(string message, int type, mixed|void random) return BIGNUM(sprintf("%c", type) + cookie + "\0" + message, 256); } -string rsa_unpad(bignum block, int type) -{ - string s = block->digits(256); - int i = search(s, "\0"); - - if ((i < 9) || (strlen(s) != (size - 1)) || (s[0] != type)) - return 0; - return s[i+1..]; -} - +#if constant(_Crypto.rsa) +// Only the cooked variant is implemented in C. */ object raw_sign(string digest) { - return rsa_pad(digest, 1, 0)->powm(d, n); -} - -int raw_verify(string digest, object s) -{ - return s->powm(e, n) == rsa_pad(digest, 1, 0); + return BIGNUM(cooked_sign(digest), 256); } +#endif /* constant(_Crypto.rsa) */ -object sign(string message, program h, mixed|void r) +object sign(string message, program h) { - // FIXME: The r argument is ignored and should be removed - return raw_sign(Signature.build_digestinfo(message, h())); + string digest = Standards.PKCS.Signature.build_digestinfo(message, h()); + return raw_sign(digest); } int verify(string msg, program h, object sign) { - // FIXME: Use raw_verify() - // werror(sprintf("msg: '%s'\n", Crypto.string_to_hex(msg))); - string s = Signature.build_digestinfo(msg, h()); + string s = Standards.PKCS.Signature.build_digestinfo(msg, h()); // werror(sprintf("rsa: s = '%s'\n", s)); - // werror(sprintf("decrypted: '%s'\n", sign->powm(e, n)->digits(256))); - string s2 = rsa_unpad(sign->powm(e, n), 1); - // werror(sprintf("rsa: s2 = '%s'\n", s2)); - return s == s2; + return raw_verify(s, sign); } string sha_sign(string message, mixed|void r) { - // FIXME: Use raw_sign() object hash = Crypto.sha(); string s; hash->update(message); s = hash->digest(); s = sprintf("%c%s%c%s", 4, "sha1", strlen(s), s); - return rsa_pad(s, 1, r)->powm(d, n)->digits(256); + return cooked_sign(s); } int sha_verify(string message, string signature) { - // FIXME: Use raw_verify() - object hash = Crypto.sha(); string s; @@ -157,7 +101,7 @@ int sha_verify(string message, string signature) s = hash->digest(); s = sprintf("%c%s%c%s", 4, "sha1", strlen(s), s); - return s == rsa_unpad(BIGNUM(signature, 256)->powm(e, n), 1); + return raw_verify(s, BIGNUM(signature, 256)); } object generate_key(int bits, function|void r) @@ -198,16 +142,6 @@ object generate_key(int bits, function|void r) return this_object(); } -string encrypt(string s, mixed|void r) -{ - return rsa_pad(s, 2, r)->powm(e, n)->digits(256); -} - -string decrypt(string s) -{ - return rsa_unpad(BIGNUM(s, 256)->powm(d, n), 2); -} - object set_encrypt_key(array(bignum) key) { set_public_key(key[0], key[1]); @@ -228,11 +162,4 @@ string crypt_block(string s) return (encrypt_mode ? encrypt(s) : decrypt(s)); } -int rsa_size() { return n->size(); } - -int public_key_equal (object rsa) -{ - return n == rsa->n && e == rsa->e; -} - #endif