sorry to ask a particular question, but I need to generate in java code a 'signature' like the following code line in ruby:
signature = OpenSSL::PKey::RSA.new(File.read("PUBLIC_PEM_PATH")).public_encrypt('SECRET_KEY')
I have the .pem key file and the SECRET_KEY that's is something like: F6qxlwQTYWRM3gRfgftryKJHKYZiGXdoy5lDm4
How can I do this ?
Thanks!
UPDATE 1 I tried this :
File pubKeyFile = new File(keyFileName);
DataInputStream inputStream;
byte[] signature = null;
try {
inputStream = new DataInputStream(new FileInputStream(pubKeyFile));
byte[] pubKeyBytes = new byte[(int)pubKeyFile.length()];
inputStream.readFully(pubKeyBytes);
inputStream.close();
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(pubKeyBytes);
RSAPublicKey pubKey = (RSAPublicKey) keyFactory.generatePublic(pubSpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
signature = cipher.doFinal(secretKey.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
return signature;
And got this error:
java.security.spec.InvalidKeySpecException: java.lang.RuntimeException: error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag
UPDATE2 I managed to load a public key from a .pem file. But now, Im getting an error from the cipher.
public static byte[] getSignature(String keyFileName, byte[] secretKey){
byte[] signature = null;
try {
PublicKey pubKey = readKeyFromFile(keyFileName);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
signature = cipher.doFinal(secretKey);
} catch (Exception e) {
e.printStackTrace();
}
return signature;
}
private static PublicKey readKeyFromFile(String keyFileName) throws IOException {
InputStream in = new FileInputStream(keyFileName);
DataInputStream din = new DataInputStream(in);
try {
BigInteger m = BigInteger.valueOf(din.readLong());
BigInteger e = BigInteger.valueOf(din.readLong());
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e);
KeyFactory fact = KeyFactory.getInstance("RSA");
RSAPublicKey pubKey = (RSAPublicKey) fact.generatePublic(keySpec);
return pubKey;
} catch (Exception e) {
throw new RuntimeException("Spurious serialisation error", e);
} finally {
din.close();
}
}
The error log:
javax.crypto.IllegalBlockSizeException: input must be under 8 bytes
Any thoughts??
So finally, after hours of research I came with a solution and finally could get read my public key from .pem file and generate an instance of this key. Hence, I managed to encrypt the data.
But I had to copy and paste the key content without any special character like '\n' and make a publicKeyString
with it
----------BEGIN RSA PUBLIC KEY---------
key content
----------END RSA PUBLIC KEY---------
static public PublicKey publicKey(String publicKeyString) {
try {
byte[] decodedPublicKey = Base64.decode(publicKeyString, 0);
ASN1InputStream in = new ASN1InputStream(decodedPublicKey);
ASN1Primitive obj = in.readObject();
RSAPublicKeyStructure keyStruct = RSAPublicKeyStructure.getInstance(obj);
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(keyStruct.getModulus(), keyStruct.getPublicExponent());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(keySpec);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
I failed even when I tried to use PEMReader from bouncy castle. All the problems have something to do with keys generated in Ruby version prior 1.9.3 as described with details here.
Anyway, thanks a lot for the attention disposed.