Golang's RSA signature doesn't match Java's

95 views Asked by At

I am trying to create a RSA signature using the PKCS #1v15 standard. The data is first hashed using MD5, and the signature' algorithm is SHA256. But for some reason, both outputs are different and the server is throwing an error for the Golang code. Any advice would be appreciated.

Java code:

For context:

RSA_ALGORITHM_SIGN = "SHA256WithRSA";

CHARSET = "UTF-8";

private static String getSign(String data, RSAPrivateKey privateKey) {
    try {
        String encodeStr = DigestUtils.md5Hex(data);
        System.out.println(encodeStr);
        Signature signature = Signature.getInstance(RSA_ALGORITHM_SIGN);
        signature.initSign(privateKey);
        signature.update(encodeStr.getBytes(CHARSET));
        byte[] sign = signature.sign();
        System.out.println(sign.length);
        return Base64.encodeBase64URLSafeString(sign);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

Golang code:

func GetSignature(data []byte, pk *rsa.PrivateKey) (string, error) {
    m := md5.New()
    _, err := m.Write(data)
    if err != nil {
        return "", err
    }
    encoded := hex.EncodeToString(m.Sum(nil))
    fmt.Println(encoded)
    signature, err := rsa.SignPKCS1v15(rand.Reader, pk, crypto.SHA256, []byte(encoded))
    if err != nil {
        return "", err
    }
    return base64.URLEncoding.EncodeToString(signature), nil
}

I was hoping for the server I am using to not throw an error. However, no matter how I change the Golang code, I am getting signature errors.

2

There are 2 answers

0
Tselmuun On BEST ANSWER

So, I missed something in the Java method.

In the Java code, the work process is MD5 -> HEX -> SHA256 -> Signature. In my earlier Golang code, I implemented MD5 -> HEX -> Signature.

Finally managed to fix it. Thank you to all those, who shared their collective input. Really helped me steer in the right direction.

2
VHS On

You are using rsa.SignPKCS1v15 (PKCS #1v15 standard) in your GoLang code but SHA256WithRSA scheme in Java. The former requires explicit padding scheme while the latter uses implicit padding. In your GoLang code, you are not doing explicit padding which results in inconsistent signature generation between your Java and Go codes. Do explict padding in your Golang code as shown below:

// Create the PKCS #1v15 padding according to the key size
padding := pkcs1v15Padding(pk.Size(), crypto.MD5)

// Concatenate padding and hashed data
paddedData := append(padding, []byte(encoded)...)

signature, err := rsa.SignPKCS1v15(rand.Reader, pk, crypto.MD5, paddedData)