I am trying to sign a byte stream which does not change with a private key that does not change either, using the SHAwithECDSA. This should produce the same result, no matter how often you run the code. However, I experience some randomness which I can't explain as the resulting output changes with every run.
Here is what I do (minimal example):
public byte[] sign() {
Signature ecdsa = Signature.getInstance("SHA256withECDSA", "SunEC");
// This is a hexadecimal byte sequence I need to sign
String dataToBeSigned = "808112B43A3A381D1797BBBBBB973B99" +
"9737B93397AA2917B1B0B737B734B1B0" +
"B616B2BC3497A1AB43A3A381D1797BBB" +
"BBB973B999737B933979918181897981" +
"A17BC36B63239B4B396B6B7B93291B2B" +
"1B239B096B9B430991A9B22062349443" +
"1025687474703A2F2F7777772E77332E" +
"6F72672F54522F63616E6F6E6963616C" +
"2D6578692F4852D0E8E8E0745E5EEEEE" +
"EE5CEE665CDEE4CE5E646060625E6068" +
"5EF0DAD8CADCC646E6D0C2646A6C841A" +
"36BC07A00CB7DCAD662F3088A60A3D6A" +
"99431F81C122C2E9F1678EF531E95523" +
"70";
String hexPrivKey = "B9134963F51C4414738435057F97BBF1" +
"010CABCB8DBDE9C5D48138396AA94B9D";
byte[] privKey = DatatypeConverter.parseHexBinary(hexPrivKey);
ecdsa.initSign(getPrivateKey(privKey));
ecdsa.update(dataToBeSigned);
byte[] signature = ecdsa.sign();
System.out.println("Signature: " + DatatypeConverter.printHexBinary(signature));
}
public ECPrivateKey getPrivateKey(byte[] privateKeyBytes) {
try {
AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC");
parameters.init(new ECGenParameterSpec("secp256r1"));
ECParameterSpec ecParameterSpec = parameters.getParameterSpec(ECParameterSpec.class);
ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(new BigInteger(privateKeyBytes), ecParameterSpec);
ECPrivateKey privateKey = (ECPrivateKey) KeyFactory.getInstance("EC").generatePrivate(ecPrivateKeySpec);
return privateKey;
} catch (NoSuchAlgorithmException | InvalidKeySpecException | InvalidParameterSpecException e) {
System.out.println(e.getClass().getSimpleName() + " occurred when trying to get private key from raw bytes", e);
return null;
}
}
Do you have any hint why this would not result in the same signature output every time I run this code? A similar question was raised here, but no real answer has been found yet.
Another question related to that: I see that there is another initSign method provided by the Signature class: initSign(PrivateKey privateKey, SecureRandom random) Why would I wanna insert a random source/seed when creating a signature? How is the receiving side supposed to verify that signature then if the random seed is not known?
Thanks for any valuable input! Marc