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