I need to write a java code which signs a binary data using a private key given by a customer. Here is what I did:
- I have written the following method to read the private key the private.key file:
private static PrivateKey readPrivateKey(String filename) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException
{
File file = new File(filename);
FileInputStream in = new FileInputStream(file);
byte[] keyBytes = new byte[ new Long(file.length()).intValue() ];
in.read(keyBytes);
in.close();
String strPrivateKey = new String(keyBytes, "UTF-8").replaceAll("(-+BEGIN PRIVATE KEY-+\\r?\\n|-+END PRIVATE KEY-+\\r?\\n?)", "");
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(strPrivateKey));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePrivate(keySpec);
}
- I have written the following method to read the public key from the public.key file
private static PublicKey readPublicKey(String filename) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException
{
File file = new File(filename);
FileInputStream in = new FileInputStream(file);
byte[] keyBytes = new byte[ new Long(file.length()).intValue() ];
in.read(keyBytes); in.close();
String strPublicKey = new String(keyBytes, "UTF-8").replaceAll("(-+BEGIN PUBLIC KEY-+\\r?\\n|-+END PUBLIC KEY-+\\r?\\n?)", "");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(DatatypeConverter.parseBase64Binary(strPublicKey));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(keySpec);
}
- I have written the following “main” test application which signs the binary data, and verifies it signature.
public static void main(String[] args) throws Exception
{
PrivateKey privateKey = readPrivateKey("private.key");
PublicKey publicKey = readPublicKey("public.key");
byte[] data = readBytesfromFile("InputData.bin");
Signature sig = Signature.getInstance("NONEwithRSA");
sig.initSign(privateKey); sig.update(data);
byte[] signatureBytes = sig.sign();
sig.initVerify(publicKey);
sig.update(data);
System.out.println(sig.verify(signatureBytes));
}
The problem is that the verification fails, and the sig.verify(signatureBytes) method returns false. I have no idea why. Here is some more input:
- I have signed the same data using OpenSSL utility with the same private.key file, and successfully verified it using my java code.
- This makes me think that my private key file is OK. And the public key file matches the private key.
- This also proves that I read the public key file correctly in java
- Is there something wrong with the way I read the private key file in java?
- Is there something wrong with the way I sign the binary data?
- I have also tried to generate my own key pair using KeyPairGenerator, and everything works fine.
Any help will be highly appreciated.
Thanks, Guy Hudara