如何使JAVA验证OpenSSL RSA / PSS签名

时间:2018-02-15 08:44:57

标签: openssl ssl-certificate rsa bouncycastle sign

我正在使用C RPC客户端。我需要使用OpenSSL来签署mime数据,并将公钥和签名发送到服务器。 Java将尝试使用公钥验证签名。

问题是,JAVA无法验证OpenSSL生成的签名,但可以验证JAVA生成的签名。知道如何修复我的客户端代码吗?

客户端代码:

#define LENGTH 256
FILE *fp=fopen("ssl.key");
unsigned int uDigestLen = 32;
EVP_PKEY *privkey;
privkey = EVP_PKEY_new();
PEM_read_PrivateKey( fp, &privkey, NULL, NULL);

pRsaKey = EVP_PKEY_get1_RSA(privkey);

if(RSA_check_key(pRsaKey)) {
    printf("RSA key is valid.\n");
}

EVP_MD_CTX_init(&md_ctx);
EVP_DigestInit(&md_ctx, EVP_sha256());
EVP_DigestUpdate(&md_ctx, (const void*) szMessage, strlen(szMessage));
EVP_DigestFinal(&md_ctx, pDigest, &uDigestLen);
EVP_MD_CTX_cleanup(&md_ctx);

// also tried RSA_padding_add_PKCS1_PSS but no luck
status = RSA_padding_add_PKCS1_PSS_mgf1(pRsaKey, EM, pDigest, EVP_sha256(), EVP_sha256(), 20 /* fixed salt length! (tried -2 w/o success)*/);
if (!status)
{
    printf("RSA_padding_add_PKCS1_PSS failed with error %s\n", ERR_error_string(ERR_get_error(), NULL));
}

status = RSA_private_encrypt(LENGTH, EM, pSignature, pRsaKey, RSA_PKCS1_PADDING);
if (status == -1)
{
    printf("RSA_private_encrypt failed with error %s\n", ERR_error_string(ERR_get_error(), NULL));
}

// I send base64 encoded string as well as public key to server, java failed to verify.
cout << "hashedChars: " << base64_encode(pSignature, LENGTH);  

JAVA代码:

Signature publicSignature = Signature.getInstance("SHA256withRSA/PSS", "BC");
publicSignature.initVerify(publicKey);
publicSignature.update(text.getBytes(StandardCharsets.UTF_8));

// always fail!!
byte[] signatureBytes = Base64.getDecoder().decode("base64 encoded  from c client");
System.out.println("verified result:" + publicSignature.verify(signatureBytes));

1 个答案:

答案 0 :(得分:2)

我想在这里要解决两件事:

  1. 将MGF1设置为明确使用SHA-256;
  2. 设置盐的大小,OpenSSL使用最大的盐大小。
  3. 有关旧讨论的更多信息,请参阅here