cPKey
size
is an integer representing the desired key size. Keys
smaller than 1024 should be considered insecure.
exponent
is an odd number normally 3, 17, or 65537.
static VALUE ossl_rsa_s_generate(int argc, VALUE *argv, VALUE klass) { /* why does this method exist? why can't initialize take an optional exponent? */ RSA *rsa; VALUE size, exp; VALUE obj; rb_scan_args(argc, argv, "11", &size, &exp); rsa = rsa_generate(NUM2INT(size), NIL_P(exp) ? RSA_F4 : NUM2INT(exp)); /* err handled by rsa_instance */ obj = rsa_instance(klass, rsa); if (obj == Qfalse) { RSA_free(rsa); ossl_raise(eRSAError, NULL); } return obj; }
size
is an integer representing the desired key size.
encoded_key
is a string containing PEM or DER encoded key.
pass
is an optional string with the password to decrypt the
encoded key.
static VALUE ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; RSA *rsa; BIO *in; char *passwd = NULL; VALUE arg, pass; GetPKey(self, pkey); if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) { rsa = RSA_new(); } else if (FIXNUM_P(arg)) { rsa = rsa_generate(FIX2INT(arg), NIL_P(pass) ? RSA_F4 : NUM2INT(pass)); if (!rsa) ossl_raise(eRSAError, NULL); } else { if (!NIL_P(pass)) passwd = StringValuePtr(pass); arg = ossl_to_der_if_possible(arg); in = ossl_obj2bio(arg); rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd); if (!rsa) { (void)BIO_reset(in); rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL); } if (!rsa) { (void)BIO_reset(in); rsa = PEM_read_bio_RSA_PUBKEY(in, NULL, NULL, NULL); } if (!rsa) { (void)BIO_reset(in); rsa = d2i_RSAPrivateKey_bio(in, NULL); } if (!rsa) { (void)BIO_reset(in); rsa = d2i_RSAPublicKey_bio(in, NULL); } if (!rsa) { (void)BIO_reset(in); rsa = d2i_RSA_PUBKEY_bio(in, NULL); } BIO_free(in); if (!rsa) ossl_raise(eRSAError, "Neither PUB key nor PRIV key:"); } if (!EVP_PKEY_assign_RSA(pkey, rsa)) { RSA_free(rsa); ossl_raise(eRSAError, NULL); } return self; }
static VALUE ossl_rsa_blinding_off(VALUE self) { EVP_PKEY *pkey; GetPKeyRSA(self, pkey); RSA_blinding_off(pkey->pkey.rsa); return self; }
static VALUE ossl_rsa_blinding_on(VALUE self) { EVP_PKEY *pkey; GetPKeyRSA(self, pkey); if (RSA_blinding_on(pkey->pkey.rsa, ossl_bn_ctx) != 1) { ossl_raise(eRSAError, NULL); } return self; }
cipher
is a Cipher object.
pass
is a string.
rsa.to_pem -> aString
rsa.to_pem(cipher, pass) -> aString
static VALUE ossl_rsa_export(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; BIO *out; const EVP_CIPHER *ciph = NULL; char *passwd = NULL; VALUE cipher, pass, str; GetPKeyRSA(self, pkey); rb_scan_args(argc, argv, "02", &cipher, &pass); if (!NIL_P(cipher)) { ciph = GetCipherPtr(cipher); if (!NIL_P(pass)) { passwd = StringValuePtr(pass); } } if (!(out = BIO_new(BIO_s_mem()))) { ossl_raise(eRSAError, NULL); } if (RSA_HAS_PRIVATE(pkey->pkey.rsa)) { if (!PEM_write_bio_RSAPrivateKey(out, pkey->pkey.rsa, ciph, NULL, 0, ossl_pem_passwd_cb, passwd)) { BIO_free(out); ossl_raise(eRSAError, NULL); } } else { if (!PEM_write_bio_RSAPublicKey(out, pkey->pkey.rsa)) { BIO_free(out); ossl_raise(eRSAError, NULL); } } str = ossl_membio2str(out); return str; }
Stores all parameters of key to the hash INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! Don't use :-)) (I's up to you)
static VALUE ossl_rsa_get_params(VALUE self) { EVP_PKEY *pkey; VALUE hash; GetPKeyRSA(self, pkey); hash = rb_hash_new(); rb_hash_aset(hash, rb_str_new2("n"), ossl_bn_new(pkey->pkey.rsa->n)); rb_hash_aset(hash, rb_str_new2("e"), ossl_bn_new(pkey->pkey.rsa->e)); rb_hash_aset(hash, rb_str_new2("d"), ossl_bn_new(pkey->pkey.rsa->d)); rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.rsa->p)); rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(pkey->pkey.rsa->q)); rb_hash_aset(hash, rb_str_new2("dmp1"), ossl_bn_new(pkey->pkey.rsa->dmp1)); rb_hash_aset(hash, rb_str_new2("dmq1"), ossl_bn_new(pkey->pkey.rsa->dmq1)); rb_hash_aset(hash, rb_str_new2("iqmp"), ossl_bn_new(pkey->pkey.rsa->iqmp)); return hash; }
static VALUE ossl_rsa_is_private(VALUE self) { EVP_PKEY *pkey; GetPKeyRSA(self, pkey); return (RSA_PRIVATE(self, pkey->pkey.rsa)) ? Qtrue : Qfalse; }
static VALUE ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; int buf_len, pad; VALUE str, buffer, padding; GetPKeyRSA(self, pkey); if (!RSA_PRIVATE(self, pkey->pkey.rsa)) { ossl_raise(eRSAError, "private key needed."); } rb_scan_args(argc, argv, "11", &buffer, &padding); pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); StringValue(buffer); str = rb_str_new(0, ossl_rsa_buf_size(pkey)); buf_len = RSA_private_decrypt(RSTRING_LEN(buffer), (unsigned char *)RSTRING_PTR(buffer), (unsigned char *)RSTRING_PTR(str), pkey->pkey.rsa, pad); if (buf_len < 0) ossl_raise(eRSAError, NULL); rb_str_set_len(str, buf_len); return str; }
static VALUE ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; int buf_len, pad; VALUE str, buffer, padding; GetPKeyRSA(self, pkey); if (!RSA_PRIVATE(self, pkey->pkey.rsa)) { ossl_raise(eRSAError, "private key needed."); } rb_scan_args(argc, argv, "11", &buffer, &padding); pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); StringValue(buffer); str = rb_str_new(0, ossl_rsa_buf_size(pkey)); buf_len = RSA_private_encrypt(RSTRING_LEN(buffer), (unsigned char *)RSTRING_PTR(buffer), (unsigned char *)RSTRING_PTR(str), pkey->pkey.rsa, pad); if (buf_len < 0) ossl_raise(eRSAError, NULL); rb_str_set_len(str, buf_len); return str; }
The return value is always true since every private key is also a public key.
static VALUE ossl_rsa_is_public(VALUE self) { EVP_PKEY *pkey; GetPKeyRSA(self, pkey); /* * This method should check for n and e. BUG. */ return Qtrue; }
static VALUE ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; int buf_len, pad; VALUE str, buffer, padding; GetPKeyRSA(self, pkey); rb_scan_args(argc, argv, "11", &buffer, &padding); pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); StringValue(buffer); str = rb_str_new(0, ossl_rsa_buf_size(pkey)); buf_len = RSA_public_decrypt(RSTRING_LEN(buffer), (unsigned char *)RSTRING_PTR(buffer), (unsigned char *)RSTRING_PTR(str), pkey->pkey.rsa, pad); if (buf_len < 0) ossl_raise(eRSAError, NULL); rb_str_set_len(str, buf_len); return str; }
static VALUE ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; int buf_len, pad; VALUE str, buffer, padding; GetPKeyRSA(self, pkey); rb_scan_args(argc, argv, "11", &buffer, &padding); pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); StringValue(buffer); str = rb_str_new(0, ossl_rsa_buf_size(pkey)); buf_len = RSA_public_encrypt(RSTRING_LEN(buffer), (unsigned char *)RSTRING_PTR(buffer), (unsigned char *)RSTRING_PTR(str), pkey->pkey.rsa, pad); if (buf_len < 0) ossl_raise(eRSAError, NULL); rb_str_set_len(str, buf_len); return str; }
Makes new instance RSA PUBLIC_KEY from PRIVATE_KEY
static VALUE ossl_rsa_to_public_key(VALUE self) { EVP_PKEY *pkey; RSA *rsa; VALUE obj; GetPKeyRSA(self, pkey); /* err check performed by rsa_instance */ rsa = RSAPublicKey_dup(pkey->pkey.rsa); obj = rsa_instance(CLASS_OF(self), rsa); if (obj == Qfalse) { RSA_free(rsa); ossl_raise(eRSAError, NULL); } return obj; }
static VALUE ossl_rsa_to_der(VALUE self) { EVP_PKEY *pkey; int (*i2d_func)_((const RSA*, unsigned char**)); unsigned char *p; long len; VALUE str; GetPKeyRSA(self, pkey); if(RSA_HAS_PRIVATE(pkey->pkey.rsa)) i2d_func = i2d_RSAPrivateKey; else i2d_func = i2d_RSAPublicKey; if((len = i2d_func(pkey->pkey.rsa, NULL)) <= 0) ossl_raise(eRSAError, NULL); str = rb_str_new(0, len); p = (unsigned char *)RSTRING_PTR(str); if(i2d_func(pkey->pkey.rsa, &p) < 0) ossl_raise(eRSAError, NULL); ossl_str_adjust(str, p); return str; }
Prints all parameters of key to buffer INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! Don't use :-)) (It's up to you)
static VALUE ossl_rsa_to_text(VALUE self) { EVP_PKEY *pkey; BIO *out; VALUE str; GetPKeyRSA(self, pkey); if (!(out = BIO_new(BIO_s_mem()))) { ossl_raise(eRSAError, NULL); } if (!RSA_print(out, pkey->pkey.rsa, 0)) { /* offset = 0 */ BIO_free(out); ossl_raise(eRSAError, NULL); } str = ossl_membio2str(out); return str; }