Normally both PSS
and PKCS1v15
can be used for RSA signatures padding.
And for java the code is also simple, but it just can't tell the padding strategy used.
My code:
Signature signature = Signature.getInstance("SHA1WithRSA");
signature.initSign(privateKey);
signature.update(plainBytes);
byte[] signBytes = signature.sign();
May I explicitly define PSS
with MGF1
as the padding strategy using SunJCE as provider?
PSS
is not present in the supported algorithms list of SunJCE. However SHA256withRSA/PSS
is implemented in android.
I suggest to use BouncyCastle
Security.addProvider(new BouncyCastleProvider());
Signature sig = Signature.getInstance("SHA1withRSA/PSS");
sig.initSign(privateKey);
sig.update(data);
byte[] signature = sig.sign();
UPDATED
The default maskGenAlgorithm
in PKCS#1 v2.1 is MGF1.
RSASSA-PSS-params ::= SEQUENCE {
hashAlgorithm [0] OAEP-PSSDigestAlgorithms DEFAULT sha1,
maskGenAlgorithm [1] PKCS1MGFAlgorithms DEFAULT mgf1SHA1,
saltLength [2] INTEGER DEFAULT 20,
trailerField [3] INTEGER DEFAULT 1
}
I assume BouncyCastle is using it. You can define your own PSS parameters. For example (see PSSParameterSpec)
sig.setParameter(PSSParameterSpec.DEFAULT);
Inspired by the answer, just to add a snippet that shows how to set all the params manually, and of course BouncyCastle
has to be used:
Signature signature = Signature.getInstance("SHA256WithRSA/PSS", "BC"); //second param "BC" is not really required
MGF1ParameterSpec mgf1ParameterSpec = new MGF1ParameterSpec("SHA-256");
PSSParameterSpec pssParameterSpec = new PSSParameterSpec("SHA-256", "MGF1", mgf1ParameterSpec , 20, 1);
signature.setParameter(pssParameterSpec);
signature.initSign(privateKey);
signature.update(plainBytes);
byte[] signBytes = signature.sign();
thanks @xuanzhui
Here is how I successfully verified my (hex encoded) signature:
public static boolean verify(String plainText, String signature, PublicKey publicKey) throws Exception {
Signature publicSignature = Signature.getInstance("SHA512withRSA/PSS");
publicSignature.setParameter(new PSSParameterSpec("SHA-512", "MGF1", MGF1ParameterSpec.SHA512 , 64, 1));
publicSignature.initVerify(publicKey);
publicSignature.update(plainText.getBytes(UTF_8));
return publicSignature.verify(hexToBytes(signature));
}
Note despite the documentation suggesting otherwise (getSaltLength()
- "returns the salt length in bits") salt length seems to be in bytes!
Also I think "SHA512withRSA/PSS" is only supported from Android 23+