From 6c7608c0b190ff1f6564c18de2325894e37b5bd2 Mon Sep 17 00:00:00 2001 From: drbrain Date: Fri, 10 Dec 2010 23:13:47 +0000 Subject: Document RSA, RSA encryption/decryption and PKCS #5 encryption/decryption git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@30174 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl.c | 66 ++++++++++++++++++++++- ext/openssl/ossl_pkey_rsa.c | 129 +++++++++++++++++++++++++------------------- 2 files changed, 140 insertions(+), 55 deletions(-) (limited to 'ext/openssl') diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index aa6f9f9200..1e4f9353d1 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -469,6 +469,70 @@ ossl_debug_set(VALUE self, VALUE val) * key4_pem = File.read 'private.secure.pem' * key4 = OpenSSL::PKey::RSA.new key4_pem, pass_phrase * + * == RSA Encryption + * + * RSA provides ecryption and decryption using the public and private keys. + * You can use a variety of padding methods depending upon the intended use of + * encrypted data. + * + * === Encryption + * + * Documents encrypted with the public key can only be decrypted with the + * private key. + * + * public_encrypted = key.public_encrypt 'top secret document' + * + * Documents encrypted with the private key can only be decrypted with the + * public key. + * + * private_encrypted = key.private_encrypt 'public release document' + * + * === Decryption + * + * Use the opposite key type do decrypt the document + * + * top_secret = key.public_decrypt public_encrypted + * + * public_release = key.private_decrypt private_encrypted + * + * == PKCS #5 Password-based Encryption + * + * PKCS #5 is a password-based encryption standard documented at + * RFC2898[http://www.ietf.org/rfc/rfc2898.txt]. It allows a short password or + * passphrase to be used to create a secure encryption key. + * + * PKCS #5 uses a Cipher, a pass phrase and a salt to generate an encryption + * key. + * + * pass_phrase = 'my secure pass phrase goes here' + * salt = '8 octets' + * + * === Encryption + * + * First set up the cipher for encryption + * + * encrypter = OpenSSL::Cipher::Cipher.new 'AES-128-CBC' + * encrypter.encrypt + * encrypter.pkcs5_keyivgen pass_phrase, salt + * + * Then pass the data you want to encrypt through + * + * encrypted = encrypter.update 'top secret document' + * encrypted << encrypter.final + * + * === Decryption + * + * Use a new Cipher instance set up for decryption + * + * decrypter = OpenSSL::Cipher::Cipher.new 'AES-128-CBC' + * decrypter.decrypt + * decrypter.pkcs5_keyivgen pass_phrase, salt + * + * Then pass the data you want to decrypt through + * + * plain = decrypter.update encrypted + * plain << decrypter.final + * * == X509 Certificates * * === Creating a Certificate @@ -538,7 +602,7 @@ ossl_debug_set(VALUE self, VALUE val) * * ca_key = OpenSSL::PKey::RSA.new 2048 * - * cipher = OpenSSL::Cipher::AES.new 128, :CBC + * cipher = OpenSSL::Cipher::Cipher.new 'AES-128-CBC' * * open 'ca_key.pem', 'w', 0400 do |io| * io.write key.export(cipher, pass_phrase) diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c index 83a1e6a4b2..4ccfded70d 100644 --- a/ext/openssl/ossl_pkey_rsa.c +++ b/ext/openssl/ossl_pkey_rsa.c @@ -85,13 +85,13 @@ rsa_generate(int size, int exp) } /* - * call-seq: - * RSA.generate(size [, exponent]) -> rsa - * - * === Parameters - * * +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. + * call-seq: + * RSA.generate(size) => RSA instance + * RSA.generate(size, exponent) => RSA instance * + * Generates an RSA keypair. +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) @@ -115,18 +115,24 @@ ossl_rsa_s_generate(int argc, VALUE *argv, VALUE klass) } /* - * call-seq: - * RSA.new([size | encoded_key] [, pass]) -> rsa + * call-seq: + * RSA.new(key_size) => RSA instance + * RSA.new(encoded_key) => RSA instance + * RSA.new(encoded_key, pass_phrase) => RSA instance + * + * Generates or loads an RSA keypair. If an integer +key_size+ is given it + * represents the desired key size. Keys less than 1024 bits should be + * considered insecure. + * + * A key can instead be loaded from an +encoded_key+ which must be PEM or DER + * encoded. A +pass_phrase+ can be used to decrypt the key. If none is given + * OpenSSL will prompt for the pass phrase. * - * === Parameters - * * +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. + * = Examples * - * === Examples - * * RSA.new(2048) -> rsa - * * RSA.new(File.read("rsa.pem")) -> rsa - * * RSA.new(File.read("rsa.pem"), "mypassword") -> rsa + * OpenSSL::PKey::RSA.new 2048 + * OpenSSL::PKey::RSA.new File.read 'rsa.pem' + * OpenSSL::PKey::RSA.new File.read('rsa.pem'), 'my pass phrase' */ static VALUE ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) @@ -182,11 +188,11 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) } /* - * call-seq: - * rsa.public? -> true - * - * The return value is always true since every private key is also a public key. + * call-seq: + * rsa.public? => true * + * The return value is always true since every private key is also a public + * key. */ static VALUE ossl_rsa_is_public(VALUE self) @@ -201,9 +207,10 @@ ossl_rsa_is_public(VALUE self) } /* - * call-seq: - * rsa.private? -> true | false + * call-seq: + * rsa.private? => true | false * + * Does this keypair contain a private key? */ static VALUE ossl_rsa_is_private(VALUE self) @@ -216,16 +223,13 @@ ossl_rsa_is_private(VALUE self) } /* - * call-seq: - * rsa.to_pem([cipher, pass]) -> aString - * - * === Parameters - * * +cipher+ is a Cipher object. - * * +pass+ is a string. + * call-seq: + * rsa.to_pem => PEM-format String + * rsa.to_pem(cipher, pass_phrase) => PEM-format String * - * === Examples - * * rsa.to_pem -> aString - * * rsa.to_pem(cipher, pass) -> aString + * Outputs this keypair in PEM encoding. If +cipher+ and +pass_phrase+ are + * given they will be used to encrypt the key. +cipher+ must be an + * OpenSSL::Cipher::Cipher instance. */ static VALUE ossl_rsa_export(int argc, VALUE *argv, VALUE self) @@ -267,9 +271,10 @@ ossl_rsa_export(int argc, VALUE *argv, VALUE self) } /* - * call-seq: - * rsa.to_der -> aString + * call-seq: + * rsa.to_der => DER-format String * + * Outputs this keypair in DER encoding. */ static VALUE ossl_rsa_to_der(VALUE self) @@ -299,9 +304,12 @@ ossl_rsa_to_der(VALUE self) #define ossl_rsa_buf_size(pkey) (RSA_size((pkey)->pkey.rsa)+16) /* - * call-seq: - * rsa.public_encrypt(string [, padding]) -> aString + * call-seq: + * rsa.public_encrypt(string) => String + * rsa.public_encrypt(string, padding) => String * + * Encrypt +string+ with the public key. +padding+ defaults to PKCS1_PADDING. + * The encrypted string output can be decrypted using #private_decrypt. */ static VALUE ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self) @@ -325,9 +333,12 @@ ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self) } /* - * call-seq: - * rsa.public_decrypt(string [, padding]) -> aString + * call-seq: + * rsa.public_decrypt(string) => String + * rsa.public_decrypt(string, padding) => String * + * Decrypt +string+, which has been encrypted with the private key, with the + * public key. +padding+ defaults to PKCS1_PADDING. */ static VALUE ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self) @@ -351,9 +362,12 @@ ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self) } /* - * call-seq: - * rsa.private_encrypt(string [, padding]) -> aString + * call-seq: + * rsa.private_encrypt(string) => String + * rsa.private_encrypt(string, padding) => String * + * Encrypt +string+ with the private key. +padding+ defaults to PKCS1_PADDING. + * The encrypted string output can be decrypted using #public_decrypt. */ static VALUE ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self) @@ -379,11 +393,13 @@ ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self) return str; } - /* - * call-seq: - * rsa.private_decrypt(string [, padding]) -> aString + * call-seq: + * rsa.private_decrypt(string) => String + * rsa.private_decrypt(string, padding) => String * + * Decrypt +string+, which has been encrypted with the public key, with the + * private key. +padding+ defaults to PKCS1_PADDING. */ static VALUE ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self) @@ -410,12 +426,15 @@ ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self) } /* - * call-seq: - * rsa.params -> hash + * call-seq: + * rsa.params => hash * - * Stores all parameters of key to the hash - * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! - * Don't use :-)) (I's up to you) + * THIS METHOD IS INSECURE, PRIVATE INFORMATION CAN LEAK OUT!!! + * + * Stores all parameters of key to the hash. The hash has keys 'n', 'e', 'd', + * 'p', 'q', 'dmp1', 'dmq1', 'iqmp'. + * + * Don't use :-)) (It's up to you) */ static VALUE ossl_rsa_get_params(VALUE self) @@ -440,11 +459,13 @@ ossl_rsa_get_params(VALUE self) } /* - * call-seq: - * rsa.to_text -> aString + * call-seq: + * rsa.to_text => String + * + * THIS METHOD IS INSECURE, PRIVATE INFORMATION CAN LEAK OUT!!! + * + * Dumps all parameters of a keypair to a String * - * Prints all parameters of key to buffer - * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! * Don't use :-)) (It's up to you) */ static VALUE @@ -468,10 +489,10 @@ ossl_rsa_to_text(VALUE self) } /* - * call-seq: - * rsa.public_key -> aRSA + * call-seq: + * rsa.public_key -> RSA * - * Makes new instance RSA PUBLIC_KEY from PRIVATE_KEY + * Makes new RSA instance containing the public key from the private key. */ static VALUE ossl_rsa_to_public_key(VALUE self) -- cgit v1.2.3