'Create compatible Java "RSA" signature using a PKCS#8 encoded private key

I have pkcs8_rsa_private_key file which generate by openssl from a rsa_private_key.pem file.

I need make a signature by the private key in python, make the same signature with below java code.

public static final String SIGN_ALGORITHMS = "SHA1WithRSA";

public static String sign(String content, String privateKey) {
    String charset = "utf-8";
    try {
        PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
                Base64.decode(privateKey));
        KeyFactory keyf = KeyFactory.getInstance("RSA");
        PrivateKey priKey = keyf.generatePrivate(priPKCS8);

        java.security.Signature signature = java.security.Signature
                .getInstance(SIGN_ALGORITHMS);

        signature.initSign(priKey);
        signature.update(content.getBytes(charset));

        byte[] signed = signature.sign();

        return Base64.encode(signed);
    } catch (Exception e) {
        e.printStackTrace();
    }

    return null;
}


Solution 1:[1]

PKCS#8 defines a way to encode and transport secret keys and it is not specific to OpenSSL; PKCS#1 defines a way to use an RSA key (no matter how it was loaded into your application, with PKCS#8 or not) to carry out and verify digital signature on data.

The piece of code you have does three things:

  1. It decodes Base64 into PKCS#8
  2. It decodes PKCS#8 into the actual key in memory (mind you may need to provide a passphrase here)
  3. It performs PKCS#1 v1.5 signature using SHA-1 using said key
  4. It encodes the signature in Base64

The example for PKCS#1 v1.5 signing in the API of PyCrypto does exactly steps #2 and #3.

Solution 2:[2]

from Crypto.Signature import PKCS1_v1_5 as pk
from Crypto.Hash import SHA
class Crypt(object):
    pkcs8_private_key = RSA.importKey(open('pkcs8_rsa_private_key.pem', 'r').read())
    def rsa_sign(cls, des_reqdata):
        """
            @:param reqdata: request reqData
        """
        h = SHA.new(des_reqdata)
        signer = pk.new(cls.pkcs8_private_key)
        signature = signer.sign(h)

        return base64.b64encode(signature)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 SquareRootOfTwentyThree
Solution 2 Youbo Sun