@@ -1022,6 +1022,145 @@ ossl_pkey_derive(int argc, VALUE *argv, VALUE self)
1022
1022
return str ;
1023
1023
}
1024
1024
1025
+ /*
1026
+ * call-seq:
1027
+ * pkey.encrypt(data [, options]) -> string
1028
+ *
1029
+ * Performs a public key encryption operation using +pkey+.
1030
+ *
1031
+ * See #decrypt for the reverse operation.
1032
+ *
1033
+ * Added in version 2.3. See also the man page EVP_PKEY_encrypt(3).
1034
+ *
1035
+ * +data+::
1036
+ * A String to be encrypted.
1037
+ * +options+::
1038
+ * A Hash that contains algorithm specific control operations to \OpenSSL.
1039
+ * See OpenSSL's man page EVP_PKEY_CTX_ctrl_str(3) for details.
1040
+ *
1041
+ * Example:
1042
+ * pkey = OpenSSL::PKey.generate_key("RSA", rsa_keygen_bits: 2048)
1043
+ * data = "secret data"
1044
+ * encrypted = pkey.encrypt(data, rsa_padding_mode: "oaep")
1045
+ * decrypted = pkey.decrypt(data, rsa_padding_mode: "oaep")
1046
+ * p decrypted #=> "secret data"
1047
+ */
1048
+ static VALUE
1049
+ ossl_pkey_encrypt (int argc , VALUE * argv , VALUE self )
1050
+ {
1051
+ EVP_PKEY * pkey ;
1052
+ EVP_PKEY_CTX * ctx ;
1053
+ VALUE data , options , str ;
1054
+ size_t outlen ;
1055
+ int state ;
1056
+
1057
+ GetPKey (self , pkey );
1058
+ rb_scan_args (argc , argv , "11" , & data , & options );
1059
+ StringValue (data );
1060
+
1061
+ ctx = EVP_PKEY_CTX_new (pkey , /* engine */ NULL );
1062
+ if (!ctx )
1063
+ ossl_raise (ePKeyError , "EVP_PKEY_CTX_new" );
1064
+ if (EVP_PKEY_encrypt_init (ctx ) <= 0 ) {
1065
+ EVP_PKEY_CTX_free (ctx );
1066
+ ossl_raise (ePKeyError , "EVP_PKEY_encrypt_init" );
1067
+ }
1068
+ if (!NIL_P (options )) {
1069
+ pkey_ctx_apply_options (ctx , options , & state );
1070
+ if (state ) {
1071
+ EVP_PKEY_CTX_free (ctx );
1072
+ rb_jump_tag (state );
1073
+ }
1074
+ }
1075
+ if (EVP_PKEY_encrypt (ctx , NULL , & outlen ,
1076
+ (unsigned char * )RSTRING_PTR (data ),
1077
+ RSTRING_LEN (data )) <= 0 ) {
1078
+ EVP_PKEY_CTX_free (ctx );
1079
+ ossl_raise (ePKeyError , "EVP_PKEY_encrypt" );
1080
+ }
1081
+ if (outlen > LONG_MAX ) {
1082
+ EVP_PKEY_CTX_free (ctx );
1083
+ rb_raise (ePKeyError , "encrypted data would be too large" );
1084
+ }
1085
+ str = ossl_str_new (NULL , (long )outlen , & state );
1086
+ if (state ) {
1087
+ EVP_PKEY_CTX_free (ctx );
1088
+ rb_jump_tag (state );
1089
+ }
1090
+ if (EVP_PKEY_encrypt (ctx , (unsigned char * )RSTRING_PTR (str ), & outlen ,
1091
+ (unsigned char * )RSTRING_PTR (data ),
1092
+ RSTRING_LEN (data )) <= 0 ) {
1093
+ EVP_PKEY_CTX_free (ctx );
1094
+ ossl_raise (ePKeyError , "EVP_PKEY_encrypt" );
1095
+ }
1096
+ EVP_PKEY_CTX_free (ctx );
1097
+ rb_str_set_len (str , outlen );
1098
+ return str ;
1099
+ }
1100
+
1101
+ /*
1102
+ * call-seq:
1103
+ * pkey.decrypt(data [, options]) -> string
1104
+ *
1105
+ * Performs a public key decryption operation using +pkey+.
1106
+ *
1107
+ * See #encrypt for a description of the parameters and an example.
1108
+ *
1109
+ * Added in version 2.3. See also the man page EVP_PKEY_decrypt(3).
1110
+ */
1111
+ static VALUE
1112
+ ossl_pkey_decrypt (int argc , VALUE * argv , VALUE self )
1113
+ {
1114
+ EVP_PKEY * pkey ;
1115
+ EVP_PKEY_CTX * ctx ;
1116
+ VALUE data , options , str ;
1117
+ size_t outlen ;
1118
+ int state ;
1119
+
1120
+ GetPKey (self , pkey );
1121
+ rb_scan_args (argc , argv , "11" , & data , & options );
1122
+ StringValue (data );
1123
+
1124
+ ctx = EVP_PKEY_CTX_new (pkey , /* engine */ NULL );
1125
+ if (!ctx )
1126
+ ossl_raise (ePKeyError , "EVP_PKEY_CTX_new" );
1127
+ if (EVP_PKEY_decrypt_init (ctx ) <= 0 ) {
1128
+ EVP_PKEY_CTX_free (ctx );
1129
+ ossl_raise (ePKeyError , "EVP_PKEY_decrypt_init" );
1130
+ }
1131
+ if (!NIL_P (options )) {
1132
+ pkey_ctx_apply_options (ctx , options , & state );
1133
+ if (state ) {
1134
+ EVP_PKEY_CTX_free (ctx );
1135
+ rb_jump_tag (state );
1136
+ }
1137
+ }
1138
+ if (EVP_PKEY_decrypt (ctx , NULL , & outlen ,
1139
+ (unsigned char * )RSTRING_PTR (data ),
1140
+ RSTRING_LEN (data )) <= 0 ) {
1141
+ EVP_PKEY_CTX_free (ctx );
1142
+ ossl_raise (ePKeyError , "EVP_PKEY_decrypt" );
1143
+ }
1144
+ if (outlen > LONG_MAX ) {
1145
+ EVP_PKEY_CTX_free (ctx );
1146
+ rb_raise (ePKeyError , "decrypted data would be too large" );
1147
+ }
1148
+ str = ossl_str_new (NULL , (long )outlen , & state );
1149
+ if (state ) {
1150
+ EVP_PKEY_CTX_free (ctx );
1151
+ rb_jump_tag (state );
1152
+ }
1153
+ if (EVP_PKEY_decrypt (ctx , (unsigned char * )RSTRING_PTR (str ), & outlen ,
1154
+ (unsigned char * )RSTRING_PTR (data ),
1155
+ RSTRING_LEN (data )) <= 0 ) {
1156
+ EVP_PKEY_CTX_free (ctx );
1157
+ ossl_raise (ePKeyError , "EVP_PKEY_decrypt" );
1158
+ }
1159
+ EVP_PKEY_CTX_free (ctx );
1160
+ rb_str_set_len (str , outlen );
1161
+ return str ;
1162
+ }
1163
+
1025
1164
/*
1026
1165
* INIT
1027
1166
*/
@@ -1121,6 +1260,8 @@ Init_ossl_pkey(void)
1121
1260
rb_define_method (cPKey , "sign" , ossl_pkey_sign , -1 );
1122
1261
rb_define_method (cPKey , "verify" , ossl_pkey_verify , -1 );
1123
1262
rb_define_method (cPKey , "derive" , ossl_pkey_derive , -1 );
1263
+ rb_define_method (cPKey , "encrypt" , ossl_pkey_encrypt , -1 );
1264
+ rb_define_method (cPKey , "decrypt" , ossl_pkey_decrypt , -1 );
1124
1265
1125
1266
id_private_q = rb_intern ("private?" );
1126
1267
0 commit comments