Reputation: 103
I'm working with Bouncy Castle Library, and can't find the way to sign a raw message without hashing/padding it first. I'm not sure what parameters to pass as alg
.
When signing a digest with PKCS v1.5 padding, I was using: "SHA1WithRSA" , "SHA256WithRSA", etc. (According to the digest type).
signature = Signature.getInstance(alg, JCEProvider.CRYPTO_PROVIDER_NAME);
Upvotes: 3
Views: 2652
Reputation: 1
// ECDSA Digital Signature Verification in Java
Signature signature = Signature.getInstance("NONEwithECDSA");
Upvotes: 0
Reputation: 93948
Raw signing is nothing more than modular exponentiation. Now there seem to be two options, but basically only one will remain. I'll explain below.
First of all, you'd think that using a Signature
with "NoneWithRSA"
should work. The algorithm does exist, but unfortunately it still pads; it just strips the ASN.1 structure indicating the hash function and value. So that one is not available.
Although signing is not the same as encryption, both operations in the end rely on modular exponentiation. So it is fortunately possible to use a Cipher
instance to create the functionality you need:
Security.addProvider(new BouncyCastleProvider());
Cipher rsa = Cipher.getInstance("RSA/ECB/NoPadding", BouncyCastleProvider.PROVIDER_NAME);
rsa.init(Cipher.DECRYPT_MODE, kp.getPrivate());
byte[] signatureUsingCipher = rsa.doFinal("owlstead"
.getBytes(StandardCharsets.UTF_8));
System.out.println(Hex.toHexString(signatureUsingCipher));
Now one thing to notice here is that Bouncy Castle does perform a somewhat different operation than the SunJCE provider of Oracle. Instead of just removing the padding, it also forgets to put the ciphertext through the I2OSP algorithm (see the PKCS#1 standard), which properly encodes to the output size of the modulus. So you can have a smaller ciphertext than 128 bytes for specific key / plaintext combinations. This is very easy to see by encrypting the value 0, where the output will be zero bytes.
Finally note that specifying Cipher.ENCRYPT
mode or Cipher.DECRYPT
mode doesn't make a difference; both simply perform modular exponentiation. However, Cipher.DECRYPT is more likely to expect a private key, which is why I used it in above code.
You can generate a key pair for testing above code like this:
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
KeyPair kp = kpg.generateKeyPair();
Warning: signature generation without secure padding is insecure; it may result in existential forgery attacks. You can only use this as building block for to create a secure scheme.
Upvotes: 1
Reputation: 327
Signature signature = Signature.getInstance("NONEwithRSA","BC");
See http://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Signature.
Upvotes: 0