@@ -440,8 +440,8 @@ public RubyString public_to_pem(ThreadContext context) {
440440 public IRubyObject syssign (IRubyObject data ) {
441441 final Ruby runtime = getRuntime ();
442442
443- DSAPrivateKey privateKey ;
444- if (( privateKey = this . privateKey ) == null ) {
443+ DSAPrivateKey privateKey = this . privateKey ;
444+ if (privateKey == null ) {
445445 throw newDSAError (runtime , "Private DSA key needed!" );
446446 }
447447
@@ -454,13 +454,55 @@ public IRubyObject syssign(IRubyObject data) {
454454 }
455455 }
456456
457+ // In OpenSSL, sign_raw/verify_raw are base-class PKey methods that use EVP_PKEY_sign /
458+ // EVP_PKEY_verify (low-level, no-hashing operations).
459+ // When the digest argument is non-nil, EVP_PKEY_CTX_set_signature_md is called, but for DSA
460+ // this only affects input-length validation inside OpenSSL - does not hash the data.
461+ //
462+ // In JCA, "NONEwithDSA" is the direct equivalent: it accepts already-hashed bytes and signs
463+ // them without any further digest step.
464+ // The digest argument therefore does not influence the JCA algorithm and is intentionally unused.
465+ @ JRubyMethod (name = "sign_raw" )
466+ public IRubyObject sign_raw (ThreadContext context , IRubyObject digest , IRubyObject data ) {
467+ DSAPrivateKey privateKey = this .privateKey ;
468+ if (privateKey == null ) {
469+ throw newDSAError (context .runtime , "Private DSA key needed!" );
470+ }
471+ try {
472+ ByteList sign = sign ("NONEwithDSA" , privateKey , data .convertToString ().getByteList ());
473+ return RubyString .newString (context .runtime , sign );
474+ }
475+ catch (GeneralSecurityException ex ) {
476+ throw newDSAError (context .runtime , ex .getMessage ());
477+ }
478+ }
479+
480+ @ JRubyMethod (name = "verify_raw" )
481+ public IRubyObject verify_raw (IRubyObject digest , IRubyObject sign , IRubyObject data ) {
482+ final Ruby runtime = getRuntime ();
483+ ByteList sigBytes = convertToString (runtime , sign , "OpenSSL::PKey::PKeyError" , "invalid signature" ).getByteList ();
484+ ByteList dataBytes = convertToString (runtime , data , "OpenSSL::PKey::PKeyError" , "invalid data" ).getByteList ();
485+ try {
486+ return runtime .newBoolean (verify ("NONEwithDSA" , getPublicKey (), dataBytes , sigBytes ));
487+ }
488+ catch (NoSuchAlgorithmException e ) {
489+ throw newPKeyError (runtime , e .getMessage ());
490+ }
491+ catch (SignatureException e ) {
492+ throw newPKeyError (runtime , "invalid signature" );
493+ }
494+ catch (InvalidKeyException e ) {
495+ throw newPKeyError (runtime , "invalid key" );
496+ }
497+ }
498+
457499 @ JRubyMethod // ossl_dsa_verify
458500 public IRubyObject sysverify (IRubyObject data , IRubyObject sign ) {
459501 final Ruby runtime = getRuntime ();
460502 ByteList sigBytes = convertToString (runtime , sign , "OpenSSL::PKey::DSAError" , "invalid signature" ).getByteList ();
461503 ByteList dataBytes = convertToString (runtime , data , "OpenSSL::PKey::DSAError" , "invalid data" ).getByteList ();
462504 try {
463- return runtime .newBoolean ( verify ("NONEwithDSA" , getPublicKey (), dataBytes , sigBytes ) );
505+ return runtime .newBoolean (verify ("NONEwithDSA" , getPublicKey (), dataBytes , sigBytes ));
464506 }
465507 catch (NoSuchAlgorithmException e ) {
466508 throw newDSAError (runtime , e .getMessage ());
0 commit comments