/* * INIT */ void Init_ossl_x509crl() { eX509CRLError = rb_define_class_under(mX509, "CRLError", eOSSLError); cX509CRL = rb_define_class_under(mX509, "CRL", rb_cObject); rb_define_alloc_func(cX509CRL, ossl_x509crl_alloc); rb_define_method(cX509CRL, "initialize", ossl_x509crl_initialize, -1); rb_define_copy_func(cX509CRL, ossl_x509crl_copy); rb_define_method(cX509CRL, "version", ossl_x509crl_get_version, 0); rb_define_method(cX509CRL, "version=", ossl_x509crl_set_version, 1); rb_define_method(cX509CRL, "signature_algorithm", ossl_x509crl_get_signature_algorithm, 0); rb_define_method(cX509CRL, "issuer", ossl_x509crl_get_issuer, 0); rb_define_method(cX509CRL, "issuer=", ossl_x509crl_set_issuer, 1); rb_define_method(cX509CRL, "last_update", ossl_x509crl_get_last_update, 0); rb_define_method(cX509CRL, "last_update=", ossl_x509crl_set_last_update, 1); rb_define_method(cX509CRL, "next_update", ossl_x509crl_get_next_update, 0); rb_define_method(cX509CRL, "next_update=", ossl_x509crl_set_next_update, 1); rb_define_method(cX509CRL, "revoked", ossl_x509crl_get_revoked, 0); rb_define_method(cX509CRL, "revoked=", ossl_x509crl_set_revoked, 1); rb_define_method(cX509CRL, "add_revoked", ossl_x509crl_add_revoked, 1); rb_define_method(cX509CRL, "sign", ossl_x509crl_sign, 2); rb_define_method(cX509CRL, "verify", ossl_x509crl_verify, 1); rb_define_method(cX509CRL, "to_der", ossl_x509crl_to_der, 0); rb_define_method(cX509CRL, "to_pem", ossl_x509crl_to_pem, 0); rb_define_alias(cX509CRL, "to_s", "to_pem"); rb_define_method(cX509CRL, "to_text", ossl_x509crl_to_text, 0); rb_define_method(cX509CRL, "extensions", ossl_x509crl_get_extensions, 0); rb_define_method(cX509CRL, "extensions=", ossl_x509crl_set_extensions, 1); rb_define_method(cX509CRL, "add_extension", ossl_x509crl_add_extension, 1); }
/* * INIT */ void Init_ossl_cipher(void) { #if 0 /* let rdoc know about mOSSL */ mOSSL = rb_define_module("OpenSSL"); #endif mCipher = rb_define_module_under(mOSSL, "Cipher"); eCipherError = rb_define_class_under(mOSSL, "CipherError", eOSSLError); cCipher = rb_define_class_under(mCipher, "Cipher", rb_cObject); rb_define_alloc_func(cCipher, ossl_cipher_alloc); rb_define_copy_func(cCipher, ossl_cipher_copy); rb_define_module_function(mCipher, "ciphers", ossl_s_ciphers, 0); rb_define_method(cCipher, "initialize", ossl_cipher_initialize, 1); rb_define_method(cCipher, "reset", ossl_cipher_reset, 0); rb_define_method(cCipher, "encrypt", ossl_cipher_encrypt, -1); rb_define_method(cCipher, "decrypt", ossl_cipher_decrypt, -1); rb_define_method(cCipher, "pkcs5_keyivgen", ossl_cipher_pkcs5_keyivgen, -1); rb_define_method(cCipher, "update", ossl_cipher_update, 1); rb_define_method(cCipher, "<<", ossl_cipher_update_deprecated, 1); rb_define_method(cCipher, "final", ossl_cipher_final, 0); rb_define_method(cCipher, "name", ossl_cipher_name, 0); rb_define_method(cCipher, "key=", ossl_cipher_set_key, 1); rb_define_method(cCipher, "key_len=", ossl_cipher_set_key_length, 1); rb_define_method(cCipher, "key_len", ossl_cipher_key_length, 0); rb_define_method(cCipher, "iv=", ossl_cipher_set_iv, 1); rb_define_method(cCipher, "iv_len", ossl_cipher_iv_length, 0); rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0); rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1); }
/* * INIT */ void Init_ossl_digest() { rb_require("digest"); #if 0 /* let rdoc know about mOSSL */ mOSSL = rb_define_module("OpenSSL"); #endif cDigest = rb_define_class_under(mOSSL, "Digest", rb_path2class("Digest::Class")); eDigestError = rb_define_class_under(cDigest, "DigestError", eOSSLError); rb_objc_define_method(*(VALUE *)cDigest, "alloc", ossl_digest_alloc, 0); rb_objc_define_method(cDigest, "initialize", ossl_digest_initialize, -1); rb_define_copy_func(cDigest, ossl_digest_copy); rb_objc_define_method(cDigest, "reset", ossl_digest_reset, 0); rb_objc_define_method(cDigest, "update", ossl_digest_update, 1); rb_define_alias(cDigest, "<<", "update"); rb_objc_define_private_method(cDigest, "finish", ossl_digest_finish, -1); rb_objc_define_method(cDigest, "digest_length", ossl_digest_size, 0); rb_objc_define_method(cDigest, "block_length", ossl_digest_block_length, 0); rb_objc_define_method(cDigest, "name", ossl_digest_name, 0); }
void Init_ossl_cms() { cCMS = rb_define_class_under(mOSSL, "CMS", rb_cObject); eCMSError = rb_define_class_under(cCMS, "CMSError", rb_eStandardError); rb_define_singleton_method(cCMS, "read_cms", ossl_cms_s_read_cms, 1); rb_attr(cCMS, rb_intern("data"), 1, 0, Qfalse); rb_attr(cCMS, rb_intern("error_string"), 1, 1, Qfalse); rb_define_alloc_func(cCMS, ossl_cms_alloc); rb_define_copy_func(cCMS, ossl_cms_copy); rb_define_method(cCMS, "initialize", ossl_cms_initialize, -1); rb_define_method(cCMS, "verify", ossl_cms_verify, -1); rb_define_method(cCMS, "to_pem", ossl_cms_to_pem, 0); rb_define_alias(cCMS, "to_s", "to_pem"); rb_define_method(cCMS, "to_der", ossl_cms_to_der, 0); }
/* * INIT * (NOTE: ordering of methods is the same as in 'man bn') */ void Init_ossl_bn() { #if 0 /* let rdoc know about mOSSL */ mOSSL = rb_define_module("OpenSSL"); #endif if (!(ossl_bn_ctx = BN_CTX_new())) { ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX"); } eBNError = rb_define_class_under(mOSSL, "BNError", eOSSLError); cBN = rb_define_class_under(mOSSL, "BN", rb_cObject); rb_define_alloc_func(cBN, ossl_bn_alloc); rb_define_method(cBN, "initialize", ossl_bn_initialize, -1); rb_define_copy_func(cBN, ossl_bn_copy); rb_define_method(cBN, "copy", ossl_bn_copy, 1); /* swap (=coerce?) */ rb_define_method(cBN, "num_bytes", ossl_bn_num_bytes, 0); rb_define_method(cBN, "num_bits", ossl_bn_num_bits, 0); /* num_bits_word */ rb_define_method(cBN, "+", ossl_bn_add, 1); rb_define_method(cBN, "-", ossl_bn_sub, 1); rb_define_method(cBN, "*", ossl_bn_mul, 1); rb_define_method(cBN, "sqr", ossl_bn_sqr, 0); rb_define_method(cBN, "/", ossl_bn_div, 1); rb_define_method(cBN, "%", ossl_bn_mod, 1); /* nnmod */ rb_define_method(cBN, "mod_add", ossl_bn_mod_add, 2); rb_define_method(cBN, "mod_sub", ossl_bn_mod_sub, 2); rb_define_method(cBN, "mod_mul", ossl_bn_mod_mul, 2); rb_define_method(cBN, "mod_sqr", ossl_bn_mod_sqr, 1); rb_define_method(cBN, "**", ossl_bn_exp, 1); rb_define_method(cBN, "mod_exp", ossl_bn_mod_exp, 2); rb_define_method(cBN, "gcd", ossl_bn_gcd, 1); /* add_word * sub_word * mul_word * div_word * mod_word */ rb_define_method(cBN, "cmp", ossl_bn_cmp, 1); rb_define_alias(cBN, "<=>", "cmp"); rb_define_method(cBN, "ucmp", ossl_bn_ucmp, 1); rb_define_method(cBN, "eql?", ossl_bn_eql, 1); rb_define_alias(cBN, "==", "eql?"); rb_define_alias(cBN, "===", "eql?"); rb_define_method(cBN, "zero?", ossl_bn_is_zero, 0); rb_define_method(cBN, "one?", ossl_bn_is_one, 0); /* is_word */ rb_define_method(cBN, "odd?", ossl_bn_is_odd, 0); /* zero * one * value_one - DON'T IMPL. * set_word * get_word */ rb_define_singleton_method(cBN, "rand", ossl_bn_s_rand, -1); rb_define_singleton_method(cBN, "pseudo_rand", ossl_bn_s_pseudo_rand, -1); rb_define_singleton_method(cBN, "rand_range", ossl_bn_s_rand_range, 1); rb_define_singleton_method(cBN, "pseudo_rand_range", ossl_bn_s_pseudo_rand_range, 1); rb_define_singleton_method(cBN, "generate_prime", ossl_bn_s_generate_prime, -1); rb_define_method(cBN, "prime?", ossl_bn_is_prime, -1); rb_define_method(cBN, "set_bit!", ossl_bn_set_bit, 1); rb_define_method(cBN, "clear_bit!", ossl_bn_clear_bit, 1); rb_define_method(cBN, "bit_set?", ossl_bn_is_bit_set, 1); rb_define_method(cBN, "mask_bits!", ossl_bn_mask_bits, 1); rb_define_method(cBN, "<<", ossl_bn_lshift, 1); rb_define_method(cBN, ">>", ossl_bn_rshift, 1); rb_define_method(cBN, "lshift!", ossl_bn_self_lshift, 1); rb_define_method(cBN, "rshift!", ossl_bn_self_rshift, 1); /* lshift1 - DON'T IMPL. */ /* rshift1 - DON'T IMPL. */ /* * bn2bin * bin2bn * bn2hex * bn2dec * hex2bn * dec2bn - all these are implemented in ossl_bn_initialize, and ossl_bn_to_s * print - NOT IMPL. * print_fp - NOT IMPL. * bn2mpi * mpi2bn */ rb_define_method(cBN, "to_s", ossl_bn_to_s, -1); rb_define_method(cBN, "to_i", ossl_bn_to_i, 0); rb_define_alias(cBN, "to_int", "to_i"); rb_define_method(cBN, "to_bn", ossl_bn_to_bn, 0); rb_define_method(cBN, "coerce", ossl_bn_coerce, 1); /* * TODO: * But how to: from_bin, from_mpi? PACK? * to_bin * to_mpi */ rb_define_method(cBN, "mod_inverse", ossl_bn_mod_inverse, 1); /* RECiProcal * MONTgomery */ /* * TODO: * Where to belong these? */ rb_define_method(cBN, "prime_fasttest?", ossl_bn_is_prime_fasttest, -1); }
/* * INIT */ void Init_ossl_dh(void) { #if 0 mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL and mPKey */ mPKey = rb_define_module_under(mOSSL, "PKey"); #endif /* Document-class: OpenSSL::PKey::DHError * * Generic exception that is raised if an operation on a DH PKey * fails unexpectedly or in case an instantiation of an instance of DH * fails due to non-conformant input data. */ eDHError = rb_define_class_under(mPKey, "DHError", ePKeyError); /* Document-class: OpenSSL::PKey::DH * * An implementation of the Diffie-Hellman key exchange protocol based on * discrete logarithms in finite fields, the same basis that DSA is built * on. * * === Accessor methods for the Diffie-Hellman parameters * * DH#p * The prime (an OpenSSL::BN) of the Diffie-Hellman parameters. * * DH#g * The generator (an OpenSSL::BN) g of the Diffie-Hellman parameters. * * DH#pub_key * The per-session public key (an OpenSSL::BN) matching the private key. * This needs to be passed to DH#compute_key. * * DH#priv_key * The per-session private key, an OpenSSL::BN. * * === Example of a key exchange * dh1 = OpenSSL::PKey::DH.new(2048) * der = dh1.public_key.to_der #you may send this publicly to the participating party * dh2 = OpenSSL::PKey::DH.new(der) * dh2.generate_key! #generate the per-session key pair * symm_key1 = dh1.compute_key(dh2.pub_key) * symm_key2 = dh2.compute_key(dh1.pub_key) * * puts symm_key1 == symm_key2 # => true */ cDH = rb_define_class_under(mPKey, "DH", cPKey); rb_define_singleton_method(cDH, "generate", ossl_dh_s_generate, -1); rb_define_method(cDH, "initialize", ossl_dh_initialize, -1); rb_define_copy_func(cDH, ossl_dh_initialize_copy); rb_define_method(cDH, "public?", ossl_dh_is_public, 0); rb_define_method(cDH, "private?", ossl_dh_is_private, 0); rb_define_method(cDH, "to_text", ossl_dh_to_text, 0); rb_define_method(cDH, "export", ossl_dh_export, 0); rb_define_alias(cDH, "to_pem", "export"); rb_define_alias(cDH, "to_s", "export"); rb_define_method(cDH, "to_der", ossl_dh_to_der, 0); rb_define_method(cDH, "public_key", ossl_dh_to_public_key, 0); rb_define_method(cDH, "params_ok?", ossl_dh_check_params, 0); rb_define_method(cDH, "generate_key!", ossl_dh_generate_key, 0); rb_define_method(cDH, "compute_key", ossl_dh_compute_key, 1); DEF_OSSL_PKEY_BN(cDH, dh, p); DEF_OSSL_PKEY_BN(cDH, dh, q); DEF_OSSL_PKEY_BN(cDH, dh, g); DEF_OSSL_PKEY_BN(cDH, dh, pub_key); DEF_OSSL_PKEY_BN(cDH, dh, priv_key); rb_define_method(cDH, "set_pqg", ossl_dh_set_pqg, 3); rb_define_method(cDH, "set_key", ossl_dh_set_key, 2); rb_define_method(cDH, "params", ossl_dh_get_params, 0); }
/* * INIT */ void Init_ossl_pkcs7() { cPKCS7 = rb_define_class_under(mOSSL, "PKCS7", rb_cObject); ePKCS7Error = rb_define_class_under(cPKCS7, "PKCS7Error", eOSSLError); rb_define_singleton_method(cPKCS7, "read_smime", ossl_pkcs7_s_read_smime, 1); rb_define_singleton_method(cPKCS7, "write_smime", ossl_pkcs7_s_write_smime, -1); rb_define_singleton_method(cPKCS7, "sign", ossl_pkcs7_s_sign, -1); rb_define_singleton_method(cPKCS7, "encrypt", ossl_pkcs7_s_encrypt, -1); rb_attr(cPKCS7, rb_intern("data"), 1, 0, Qfalse); rb_attr(cPKCS7, rb_intern("error_string"), 1, 1, Qfalse); rb_define_alloc_func(cPKCS7, ossl_pkcs7_alloc); rb_define_copy_func(cPKCS7, ossl_pkcs7_copy); rb_define_method(cPKCS7, "initialize", ossl_pkcs7_initialize, -1); rb_define_method(cPKCS7, "type=", ossl_pkcs7_set_type, 1); rb_define_method(cPKCS7, "type", ossl_pkcs7_get_type, 0); rb_define_method(cPKCS7, "detached=", ossl_pkcs7_set_detached, 1); rb_define_method(cPKCS7, "detached", ossl_pkcs7_get_detached, 0); rb_define_method(cPKCS7, "detached?", ossl_pkcs7_detached_p, 0); rb_define_method(cPKCS7, "cipher=", ossl_pkcs7_set_cipher, 1); rb_define_method(cPKCS7, "add_signer", ossl_pkcs7_add_signer, 1); rb_define_method(cPKCS7, "signers", ossl_pkcs7_get_signer, 0); rb_define_method(cPKCS7, "add_recipient", ossl_pkcs7_add_recipient, 1); rb_define_method(cPKCS7, "recipients", ossl_pkcs7_get_recipient, 0); rb_define_method(cPKCS7, "add_certificate", ossl_pkcs7_add_certificate, 1); rb_define_method(cPKCS7, "certificates=", ossl_pkcs7_set_certificates, 1); rb_define_method(cPKCS7, "certificates", ossl_pkcs7_get_certificates, 0); rb_define_method(cPKCS7, "add_crl", ossl_pkcs7_add_crl, 1); rb_define_method(cPKCS7, "crls=", ossl_pkcs7_set_crls, 1); rb_define_method(cPKCS7, "crls", ossl_pkcs7_get_crls, 0); rb_define_method(cPKCS7, "add_data", ossl_pkcs7_add_data, 1); rb_define_alias(cPKCS7, "data=", "add_data"); rb_define_method(cPKCS7, "verify", ossl_pkcs7_verify, -1); rb_define_method(cPKCS7, "decrypt", ossl_pkcs7_decrypt, -1); rb_define_method(cPKCS7, "to_pem", ossl_pkcs7_to_pem, 0); rb_define_alias(cPKCS7, "to_s", "to_pem"); rb_define_method(cPKCS7, "to_der", ossl_pkcs7_to_der, 0); cPKCS7Signer = rb_define_class_under(cPKCS7, "SignerInfo", rb_cObject); rb_define_const(cPKCS7, "Signer", cPKCS7Signer); rb_define_alloc_func(cPKCS7Signer, ossl_pkcs7si_alloc); rb_define_method(cPKCS7Signer, "initialize", ossl_pkcs7si_initialize,3); rb_define_method(cPKCS7Signer, "issuer", ossl_pkcs7si_get_issuer, 0); rb_define_alias(cPKCS7Signer, "name", "issuer"); rb_define_method(cPKCS7Signer, "serial", ossl_pkcs7si_get_serial,0); rb_define_method(cPKCS7Signer,"signed_time",ossl_pkcs7si_get_signed_time,0); cPKCS7Recipient = rb_define_class_under(cPKCS7,"RecipientInfo",rb_cObject); rb_define_alloc_func(cPKCS7Recipient, ossl_pkcs7ri_alloc); rb_define_method(cPKCS7Recipient, "initialize", ossl_pkcs7ri_initialize,1); rb_define_method(cPKCS7Recipient, "issuer", ossl_pkcs7ri_get_issuer,0); rb_define_method(cPKCS7Recipient, "serial", ossl_pkcs7ri_get_serial,0); rb_define_method(cPKCS7Recipient, "enc_key", ossl_pkcs7ri_get_enc_key,0); #define DefPKCS7Const(x) rb_define_const(cPKCS7, #x, INT2NUM(PKCS7_##x)) DefPKCS7Const(TEXT); DefPKCS7Const(NOCERTS); DefPKCS7Const(NOSIGS); DefPKCS7Const(NOCHAIN); DefPKCS7Const(NOINTERN); DefPKCS7Const(NOVERIFY); DefPKCS7Const(DETACHED); DefPKCS7Const(BINARY); DefPKCS7Const(NOATTR); DefPKCS7Const(NOSMIMECAP); }
/* * INIT */ void Init_ossl_cipher(void) { #if 0 mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */ #endif /* Document-class: OpenSSL::Cipher * * Provides symmetric algorithms for encryption and decryption. The * algorithms that are available depend on the particular version * of OpenSSL that is installed. * * === Listing all supported algorithms * * A list of supported algorithms can be obtained by * * puts OpenSSL::Cipher.ciphers * * === Instantiating a Cipher * * There are several ways to create a Cipher instance. Generally, a * Cipher algorithm is categorized by its name, the key length in bits * and the cipher mode to be used. The most generic way to create a * Cipher is the following * * cipher = OpenSSL::Cipher.new('<name>-<key length>-<mode>') * * That is, a string consisting of the hyphenated concatenation of the * individual components name, key length and mode. Either all uppercase * or all lowercase strings may be used, for example: * * cipher = OpenSSL::Cipher.new('AES-128-CBC') * * For each algorithm supported, there is a class defined under the * Cipher class that goes by the name of the cipher, e.g. to obtain an * instance of AES, you could also use * * # these are equivalent * cipher = OpenSSL::Cipher::AES.new(128, :CBC) * cipher = OpenSSL::Cipher::AES.new(128, 'CBC') * cipher = OpenSSL::Cipher::AES.new('128-CBC') * * Finally, due to its wide-spread use, there are also extra classes * defined for the different key sizes of AES * * cipher = OpenSSL::Cipher::AES128.new(:CBC) * cipher = OpenSSL::Cipher::AES192.new(:CBC) * cipher = OpenSSL::Cipher::AES256.new(:CBC) * * === Choosing either encryption or decryption mode * * Encryption and decryption are often very similar operations for * symmetric algorithms, this is reflected by not having to choose * different classes for either operation, both can be done using the * same class. Still, after obtaining a Cipher instance, we need to * tell the instance what it is that we intend to do with it, so we * need to call either * * cipher.encrypt * * or * * cipher.decrypt * * on the Cipher instance. This should be the first call after creating * the instance, otherwise configuration that has already been set could * get lost in the process. * * === Choosing a key * * Symmetric encryption requires a key that is the same for the encrypting * and for the decrypting party and after initial key establishment should * be kept as private information. There are a lot of ways to create * insecure keys, the most notable is to simply take a password as the key * without processing the password further. A simple and secure way to * create a key for a particular Cipher is * * cipher = OpenSSL::AES256.new(:CFB) * cipher.encrypt * key = cipher.random_key # also sets the generated key on the Cipher * * If you absolutely need to use passwords as encryption keys, you * should use Password-Based Key Derivation Function 2 (PBKDF2) by * generating the key with the help of the functionality provided by * OpenSSL::PKCS5.pbkdf2_hmac_sha1 or OpenSSL::PKCS5.pbkdf2_hmac. * * Although there is Cipher#pkcs5_keyivgen, its use is deprecated and * it should only be used in legacy applications because it does not use * the newer PKCS#5 v2 algorithms. * * === Choosing an IV * * The cipher modes CBC, CFB, OFB and CTR all need an "initialization * vector", or short, IV. ECB mode is the only mode that does not require * an IV, but there is almost no legitimate use case for this mode * because of the fact that it does not sufficiently hide plaintext * patterns. Therefore * * <b>You should never use ECB mode unless you are absolutely sure that * you absolutely need it</b> * * Because of this, you will end up with a mode that explicitly requires * an IV in any case. Note that for backwards compatibility reasons, * setting an IV is not explicitly mandated by the Cipher API. If not * set, OpenSSL itself defaults to an all-zeroes IV ("\\0", not the * character). Although the IV can be seen as public information, i.e. * it may be transmitted in public once generated, it should still stay * unpredictable to prevent certain kinds of attacks. Therefore, ideally * * <b>Always create a secure random IV for every encryption of your * Cipher</b> * * A new, random IV should be created for every encryption of data. Think * of the IV as a nonce (number used once) - it's public but random and * unpredictable. A secure random IV can be created as follows * * cipher = ... * cipher.encrypt * key = cipher.random_key * iv = cipher.random_iv # also sets the generated IV on the Cipher * * Although the key is generally a random value, too, it is a bad choice * as an IV. There are elaborate ways how an attacker can take advantage * of such an IV. As a general rule of thumb, exposing the key directly * or indirectly should be avoided at all cost and exceptions only be * made with good reason. * * === Calling Cipher#final * * ECB (which should not be used) and CBC are both block-based modes. * This means that unlike for the other streaming-based modes, they * operate on fixed-size blocks of data, and therefore they require a * "finalization" step to produce or correctly decrypt the last block of * data by appropriately handling some form of padding. Therefore it is * essential to add the output of OpenSSL::Cipher#final to your * encryption/decryption buffer or you will end up with decryption errors * or truncated data. * * Although this is not really necessary for streaming-mode ciphers, it is * still recommended to apply the same pattern of adding the output of * Cipher#final there as well - it also enables you to switch between * modes more easily in the future. * * === Encrypting and decrypting some data * * data = "Very, very confidential data" * * cipher = OpenSSL::Cipher::AES.new(128, :CBC) * cipher.encrypt * key = cipher.random_key * iv = cipher.random_iv * * encrypted = cipher.update(data) + cipher.final * ... * decipher = OpenSSL::Cipher::AES.new(128, :CBC) * decipher.decrypt * decipher.key = key * decipher.iv = iv * * plain = decipher.update(encrypted) + decipher.final * * puts data == plain #=> true * * === Authenticated Encryption and Associated Data (AEAD) * * If the OpenSSL version used supports it, an Authenticated Encryption * mode (such as GCM or CCM) should always be preferred over any * unauthenticated mode. Currently, OpenSSL supports AE only in combination * with Associated Data (AEAD) where additional associated data is included * in the encryption process to compute a tag at the end of the encryption. * This tag will also be used in the decryption process and by verifying * its validity, the authenticity of a given ciphertext is established. * * This is superior to unauthenticated modes in that it allows to detect * if somebody effectively changed the ciphertext after it had been * encrypted. This prevents malicious modifications of the ciphertext that * could otherwise be exploited to modify ciphertexts in ways beneficial to * potential attackers. * * If no associated data is needed for encryption and later decryption, * the OpenSSL library still requires a value to be set - "" may be used in * case none is available. An example using the GCM (Galois Counter Mode): * * cipher = OpenSSL::Cipher::AES.new(128, :GCM) * cipher.encrypt * key = cipher.random_key * iv = cipher.random_iv * cipher.auth_data = "" * * encrypted = cipher.update(data) + cipher.final * tag = cipher.auth_tag * * decipher = OpenSSL::Cipher::AES.new(128, :GCM) * decipher.decrypt * decipher.key = key * decipher.iv = iv * decipher.auth_tag = tag * decipher.auth_data = "" * * plain = decipher.update(encrypted) + decipher.final * * puts data == plain #=> true */ cCipher = rb_define_class_under(mOSSL, "Cipher", rb_cObject); eCipherError = rb_define_class_under(cCipher, "CipherError", eOSSLError); rb_define_alloc_func(cCipher, ossl_cipher_alloc); rb_define_copy_func(cCipher, ossl_cipher_copy); rb_define_module_function(cCipher, "ciphers", ossl_s_ciphers, 0); rb_define_method(cCipher, "initialize", ossl_cipher_initialize, 1); rb_define_method(cCipher, "reset", ossl_cipher_reset, 0); rb_define_method(cCipher, "encrypt", ossl_cipher_encrypt, -1); rb_define_method(cCipher, "decrypt", ossl_cipher_decrypt, -1); rb_define_method(cCipher, "pkcs5_keyivgen", ossl_cipher_pkcs5_keyivgen, -1); rb_define_method(cCipher, "update", ossl_cipher_update, -1); rb_define_method(cCipher, "final", ossl_cipher_final, 0); rb_define_method(cCipher, "name", ossl_cipher_name, 0); rb_define_method(cCipher, "key=", ossl_cipher_set_key, 1); rb_define_method(cCipher, "auth_data=", ossl_cipher_set_auth_data, 1); rb_define_method(cCipher, "auth_tag=", ossl_cipher_set_auth_tag, 1); rb_define_method(cCipher, "auth_tag", ossl_cipher_get_auth_tag, -1); rb_define_method(cCipher, "authenticated?", ossl_cipher_is_authenticated, 0); rb_define_method(cCipher, "key_len=", ossl_cipher_set_key_length, 1); rb_define_method(cCipher, "key_len", ossl_cipher_key_length, 0); rb_define_method(cCipher, "iv=", ossl_cipher_set_iv, 1); rb_define_method(cCipher, "iv_len", ossl_cipher_iv_length, 0); rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0); rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1); }
/* * INIT */ void Init_ossl_digest(void) { rb_require("digest"); #if 0 mOSSL = rb_define_module("OpenSSL"); eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError); #endif /* Document-class: OpenSSL::Digest * * OpenSSL::Digest allows you to compute message digests (sometimes * interchangeably called "hashes") of arbitrary data that are * cryptographically secure, i.e. a Digest implements a secure one-way * function. * * One-way functions offer some useful properties. E.g. given two * distinct inputs the probability that both yield the same output * is highly unlikely. Combined with the fact that every message digest * algorithm has a fixed-length output of just a few bytes, digests are * often used to create unique identifiers for arbitrary data. A common * example is the creation of a unique id for binary documents that are * stored in a database. * * Another useful characteristic of one-way functions (and thus the name) * is that given a digest there is no indication about the original * data that produced it, i.e. the only way to identify the original input * is to "brute-force" through every possible combination of inputs. * * These characteristics make one-way functions also ideal companions * for public key signature algorithms: instead of signing an entire * document, first a hash of the document is produced with a considerably * faster message digest algorithm and only the few bytes of its output * need to be signed using the slower public key algorithm. To validate * the integrity of a signed document, it suffices to re-compute the hash * and verify that it is equal to that in the signature. * * Among the supported message digest algorithms are: * * SHA, SHA1, SHA224, SHA256, SHA384 and SHA512 * * MD2, MD4, MDC2 and MD5 * * RIPEMD160 * * DSS, DSS1 (Pseudo algorithms to be used for DSA signatures. DSS is * equal to SHA and DSS1 is equal to SHA1) * * For each of these algorithms, there is a sub-class of Digest that * can be instantiated as simply as e.g. * * digest = OpenSSL::Digest::SHA1.new * * === Mapping between Digest class and sn/ln * * The sn (short names) and ln (long names) are defined in * <openssl/object.h> and <openssl/obj_mac.h>. They are textual * representations of ASN.1 OBJECT IDENTIFIERs. Each supported digest * algorithm has an OBJECT IDENTIFIER associated to it and those again * have short/long names assigned to them. * E.g. the OBJECT IDENTIFIER for SHA-1 is 1.3.14.3.2.26 and its * sn is "SHA1" and its ln is "sha1". * ==== MD2 * * sn: MD2 * * ln: md2 * ==== MD4 * * sn: MD4 * * ln: md4 * ==== MD5 * * sn: MD5 * * ln: md5 * ==== SHA * * sn: SHA * * ln: SHA * ==== SHA-1 * * sn: SHA1 * * ln: sha1 * ==== SHA-224 * * sn: SHA224 * * ln: sha224 * ==== SHA-256 * * sn: SHA256 * * ln: sha256 * ==== SHA-384 * * sn: SHA384 * * ln: sha384 * ==== SHA-512 * * sn: SHA512 * * ln: sha512 * * "Breaking" a message digest algorithm means defying its one-way * function characteristics, i.e. producing a collision or finding a way * to get to the original data by means that are more efficient than * brute-forcing etc. Most of the supported digest algorithms can be * considered broken in this sense, even the very popular MD5 and SHA1 * algorithms. Should security be your highest concern, then you should * probably rely on SHA224, SHA256, SHA384 or SHA512. * * === Hashing a file * * data = File.read('document') * sha256 = OpenSSL::Digest::SHA256.new * digest = sha256.digest(data) * * === Hashing several pieces of data at once * * data1 = File.read('file1') * data2 = File.read('file2') * data3 = File.read('file3') * sha256 = OpenSSL::Digest::SHA256.new * sha256 << data1 * sha256 << data2 * sha256 << data3 * digest = sha256.digest * * === Reuse a Digest instance * * data1 = File.read('file1') * sha256 = OpenSSL::Digest::SHA256.new * digest1 = sha256.digest(data1) * * data2 = File.read('file2') * sha256.reset * digest2 = sha256.digest(data2) * */ cDigest = rb_define_class_under(mOSSL, "Digest", rb_path2class("Digest::Class")); /* Document-class: OpenSSL::Digest::DigestError * * Generic Exception class that is raised if an error occurs during a * Digest operation. */ eDigestError = rb_define_class_under(cDigest, "DigestError", eOSSLError); rb_define_alloc_func(cDigest, ossl_digest_alloc); rb_define_method(cDigest, "initialize", ossl_digest_initialize, -1); rb_define_copy_func(cDigest, ossl_digest_copy); rb_define_method(cDigest, "reset", ossl_digest_reset, 0); rb_define_method(cDigest, "update", ossl_digest_update, 1); rb_define_alias(cDigest, "<<", "update"); rb_define_private_method(cDigest, "finish", ossl_digest_finish, -1); rb_define_method(cDigest, "digest_length", ossl_digest_size, 0); rb_define_method(cDigest, "block_length", ossl_digest_block_length, 0); rb_define_method(cDigest, "name", ossl_digest_name, 0); }