I am trying to generate signature using ECDSA with secp256r1 curve (P256) and SHA256 algorithm for message hash. Also i am using Bouncy Castle libraries. Code below,
public class MyTest {
/**
* @param args
*/
public static void main(String[] args) {
new MyTest().getSign();
}
void getSign() {
// Get the instance of the Key Generator with "EC" algorithm
try {
KeyPairGenerator g = KeyPairGenerator.getInstance("EC");
ECGenParameterSpec kpgparams = new ECGenParameterSpec("secp256r1");
g.initialize(kpgparams);
KeyPair pair = g.generateKeyPair();
// Instance of signature class with SHA256withECDSA algorithm
Signature ecdsaSign = Signature.getInstance("SHA256withECDSA");
ecdsaSign.initSign(pair.getPrivate());
System.out.println("Private Keys is::" + pair.getPrivate());
System.out.println("Public Keys is::" + pair.getPublic());
String msg = "text ecdsa with sha256";//getSHA256(msg)
ecdsaSign.update((msg + pair.getPrivate().toString())
.getBytes("UTF-8"));
byte[] signature = ecdsaSign.sign();
System.out.println("Signature is::"
+ new BigInteger(1, signature).toString(16));
// Validation
ecdsaSign.initVerify(pair.getPublic());
ecdsaSign.update(signature);
if (ecdsaSign.verify(signature))
System.out.println("valid");
else
System.out.println("invalid!!!!");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
Here key pairs are generated using KeyPair , but for my requirement I will be having a static privateKey and public key. Also, validation of signature is always returning false.
Need help, how can I have static private key and on validation part.
Jackpot - nothing in your title is a problem!
First, you probably aren't actually using BouncyCastle. Sun/Oracle Java 7 and 8 now includes an EC provider (earlier versions did not) and the one-arg form of getInstance
uses the first available provider, which is normally SunEC unless you or someone has altered the provider list.
TO VERIFY A SIGNATURE: pass the same data to the verifying Signature.update()
as you passed to the signing Signature.update()
. Exactly the same, byte for byte. Pass the signature value only to Signature.verify()
. Putting PrivateKey.toString()
in the data is silly; this value is specific to the running Java process, so you'll have to send it to the receiving process (if different, as it normally should be) where it is useless and a waste of space.
TO USE A STATIC KEY: do just that. Create a keypair and store it someplace, then read it in and use it. The easiest secure (password protected) store is a Java KeyStore (JKS) file, but that requires a certificate chain (perhaps a dummy one) which is a nuisance to code yourself; fortunately the keytool
utility with -genkeypair
generates a keypair with a dummy selfsigned certificate, and for -keyalg ec -keysize 256
it uses the (very popular) secp256r1 curve. Also specify -alias name
of your choice, -keystore filename
, any names you like for the dummy cert, and passwords. To use a keypair from a JKS file:
use java.security.KeyStore.getInstance("JKS")
to create a store object and pass .load(InputStream,char[])
a FileInputStream
on the file, and the password.
use .getKey(String alias,char[] password)
and cast to get the PrivateKey. Use for signing.
use .getCertificateChain(String alias)[0].getPublicKey()
to get the PublicKey from the first (only) cert. Use for verifying.