@@ -777,44 +777,69 @@ ossl_pkey_compare(VALUE self, VALUE other)
777
777
}
778
778
779
779
/*
780
- * call-seq:
781
- * pkey.sign(digest, data) -> String
780
+ * call-seq:
781
+ * pkey.sign(digest, data [, options] ) -> string
782
782
*
783
- * To sign the String _data_, _digest_, an instance of OpenSSL::Digest, must
784
- * be provided. The return value is again a String containing the signature.
785
- * A PKeyError is raised should errors occur.
786
- * Any previous state of the Digest instance is irrelevant to the signature
787
- * outcome, the digest instance is reset to its initial state during the
788
- * operation.
783
+ * Hashes and signs the +data+ using a message digest algorithm +digest+ and
784
+ * a private key +pkey+.
789
785
*
790
- * == Example
791
- * data = 'Sign me!'
792
- * digest = OpenSSL::Digest.new('SHA256')
793
- * pkey = OpenSSL::PKey::RSA.new(2048)
794
- * signature = pkey.sign(digest, data)
786
+ * See #verify for the verification operation.
787
+ *
788
+ * See also the man page EVP_DigestSign(3).
789
+ *
790
+ * +digest+::
791
+ * A String that represents the message digest algorithm name, or +nil+
792
+ * if the PKey type requires no digest algorithm.
793
+ * For backwards compatibility, this can be an instance of OpenSSL::Digest.
794
+ * Its state will not affect the signature.
795
+ * +data+::
796
+ * A String. The data to be hashed and signed.
797
+ * +options+::
798
+ * A Hash that contains algorithm specific control operations to \OpenSSL.
799
+ * See OpenSSL's man page EVP_PKEY_CTX_ctrl_str(3) for details.
800
+ * +options+ parameter was added in version 2.3.
801
+ *
802
+ * Example:
803
+ * data = "Sign me!"
804
+ * pkey = OpenSSL::PKey.generate_key("RSA", rsa_keygen_bits: 2048)
805
+ * signopts = { rsa_padding_mode: "pss" }
806
+ * signature = pkey.sign("SHA256", data, signopts)
807
+ *
808
+ * # Creates a copy of the RSA key pkey, but without the private components
809
+ * pub_key = pkey.public_key
810
+ * puts pub_key.verify("SHA256", signature, data, signopts) # => true
795
811
*/
796
812
static VALUE
797
- ossl_pkey_sign (VALUE self , VALUE digest , VALUE data )
813
+ ossl_pkey_sign (int argc , VALUE * argv , VALUE self )
798
814
{
799
815
EVP_PKEY * pkey ;
816
+ VALUE digest , data , options , sig ;
800
817
const EVP_MD * md = NULL ;
801
818
EVP_MD_CTX * ctx ;
819
+ EVP_PKEY_CTX * pctx ;
802
820
size_t siglen ;
803
821
int state ;
804
- VALUE sig ;
805
822
806
823
pkey = GetPrivPKeyPtr (self );
824
+ rb_scan_args (argc , argv , "21" , & digest , & data , & options );
807
825
if (!NIL_P (digest ))
808
826
md = ossl_evp_get_digestbyname (digest );
809
827
StringValue (data );
810
828
811
829
ctx = EVP_MD_CTX_new ();
812
830
if (!ctx )
813
831
ossl_raise (ePKeyError , "EVP_MD_CTX_new" );
814
- if (EVP_DigestSignInit (ctx , NULL , md , /* engine */ NULL , pkey ) < 1 ) {
832
+ if (EVP_DigestSignInit (ctx , & pctx , md , /* engine */ NULL , pkey ) < 1 ) {
815
833
EVP_MD_CTX_free (ctx );
816
834
ossl_raise (ePKeyError , "EVP_DigestSignInit" );
817
835
}
836
+ if (!NIL_P (options )) {
837
+ pkey_ctx_apply_options (pctx , options , & state );
838
+ if (state ) {
839
+ EVP_MD_CTX_free (ctx );
840
+ rb_jump_tag (state );
841
+ }
842
+ }
818
843
#if OPENSSL_VERSION_NUMBER >= 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER )
819
844
if (EVP_DigestSign (ctx , NULL , & siglen , (unsigned char * )RSTRING_PTR (data ),
820
845
RSTRING_LEN (data )) < 1 ) {
@@ -866,35 +891,40 @@ ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
866
891
}
867
892
868
893
/*
869
- * call-seq:
870
- * pkey.verify(digest, signature, data) -> String
894
+ * call-seq:
895
+ * pkey.verify(digest, signature, data [, options] ) -> true or false
871
896
*
872
- * To verify the String _signature_, _digest_, an instance of
873
- * OpenSSL::Digest, must be provided to re-compute the message digest of the
874
- * original _data_, also a String. The return value is +true+ if the
875
- * signature is valid, +false+ otherwise. A PKeyError is raised should errors
876
- * occur.
877
- * Any previous state of the Digest instance is irrelevant to the validation
878
- * outcome, the digest instance is reset to its initial state during the
879
- * operation.
897
+ * Verifies the +signature+ for the +data+ using a message digest algorithm
898
+ * +digest+ and a public key +pkey+.
880
899
*
881
- * == Example
882
- * data = 'Sign me!'
883
- * digest = OpenSSL::Digest.new('SHA256')
884
- * pkey = OpenSSL::PKey::RSA.new(2048)
885
- * signature = pkey.sign(digest, data)
886
- * pub_key = pkey.public_key
887
- * puts pub_key.verify(digest, signature, data) # => true
900
+ * Returns +true+ if the signature is successfully verified, +false+ otherwise.
901
+ * The caller must check the return value.
902
+ *
903
+ * See #sign for the signing operation and an example.
904
+ *
905
+ * See also the man page EVP_DigestVerify(3).
906
+ *
907
+ * +digest+::
908
+ * See #sign.
909
+ * +signature+::
910
+ * A String containing the signature to be verified.
911
+ * +data+::
912
+ * See #sign.
913
+ * +options+::
914
+ * See #sign. +options+ parameter was added in version 2.3.
888
915
*/
889
916
static VALUE
890
- ossl_pkey_verify (VALUE self , VALUE digest , VALUE sig , VALUE data )
917
+ ossl_pkey_verify (int argc , VALUE * argv , VALUE self )
891
918
{
892
919
EVP_PKEY * pkey ;
920
+ VALUE digest , sig , data , options ;
893
921
const EVP_MD * md = NULL ;
894
922
EVP_MD_CTX * ctx ;
895
- int ret ;
923
+ EVP_PKEY_CTX * pctx ;
924
+ int state , ret ;
896
925
897
926
GetPKey (self , pkey );
927
+ rb_scan_args (argc , argv , "31" , & digest , & sig , & data , & options );
898
928
ossl_pkey_check_public_key (pkey );
899
929
if (!NIL_P (digest ))
900
930
md = ossl_evp_get_digestbyname (digest );
@@ -904,10 +934,17 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
904
934
ctx = EVP_MD_CTX_new ();
905
935
if (!ctx )
906
936
ossl_raise (ePKeyError , "EVP_MD_CTX_new" );
907
- if (EVP_DigestVerifyInit (ctx , NULL , md , /* engine */ NULL , pkey ) < 1 ) {
937
+ if (EVP_DigestVerifyInit (ctx , & pctx , md , /* engine */ NULL , pkey ) < 1 ) {
908
938
EVP_MD_CTX_free (ctx );
909
939
ossl_raise (ePKeyError , "EVP_DigestVerifyInit" );
910
940
}
941
+ if (!NIL_P (options )) {
942
+ pkey_ctx_apply_options (pctx , options , & state );
943
+ if (state ) {
944
+ EVP_MD_CTX_free (ctx );
945
+ rb_jump_tag (state );
946
+ }
947
+ }
911
948
#if OPENSSL_VERSION_NUMBER >= 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER )
912
949
ret = EVP_DigestVerify (ctx , (unsigned char * )RSTRING_PTR (sig ),
913
950
RSTRING_LEN (sig ), (unsigned char * )RSTRING_PTR (data ),
@@ -1081,8 +1118,8 @@ Init_ossl_pkey(void)
1081
1118
rb_define_method (cPKey , "public_to_pem" , ossl_pkey_public_to_pem , 0 );
1082
1119
rb_define_method (cPKey , "compare?" , ossl_pkey_compare , 1 );
1083
1120
1084
- rb_define_method (cPKey , "sign" , ossl_pkey_sign , 2 );
1085
- rb_define_method (cPKey , "verify" , ossl_pkey_verify , 3 );
1121
+ rb_define_method (cPKey , "sign" , ossl_pkey_sign , -1 );
1122
+ rb_define_method (cPKey , "verify" , ossl_pkey_verify , -1 );
1086
1123
rb_define_method (cPKey , "derive" , ossl_pkey_derive , -1 );
1087
1124
1088
1125
id_private_q = rb_intern ("private?" );
0 commit comments