Private Key sign data in Java to PHP - java

I have to write PHP program to do the same function with the java sign function as follow
public static String sign(byte[] data, String privateKey) throws Exception {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(data);
byte[] hashData = messageDigest.digest();
StringBuffer hexString = new StringBuffer();
byte[] keyBytes = Base64Utils.decode(privateKey.getBytes());
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Signature signature = Signature.getInstance("NONEWithRSA");
signature.initSign(privateK);
signature.update(hashData);
byte[] sign = signature.sign();
return Base64.getEncoder().encodeToString(sign);
}
I have done some research on google and try to write the PHP code as follow
public function sign($data, $privateKeyString){
$privateKey = openssl_pkey_get_private($privateKeyString);
$hashData = hash("sha256",$data);
openssl_sign($hashData, $signature, $privateKey);
openssl_free_key($privateKey);
return base64_encode($signature);
}
I try to pass the same key with the data let's say "Hello" to both function and testing
the hash data are map but the outcome signature are different
Is there anyone can spot what cause the return base64 signature are different between the java and php?

public function sign($data, $privateKeyString){
$privateKey = openssl_pkey_get_private($privateKeyString);
$hashData = openssl_digest("sha256",$data);
openssl_private_encrypt($hashData, $signature, $privateKey);
openssl_free_key($privateKey);
return base64_encode($signature);
}
Finally fixing the problem by using openssl_digest "sha256" instead of passing sha256 hash value into the for private key encrytion, due to the hashing need to be convert into the hex string instead of the original value.

Related

convert Encryption Algo from C# to Java

public static string Encrypt(string KeyToEncrypt)
{
byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(KeyToEncrypt);
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(_Pwd, _Salt);
//Calling another private method for Encryption
byte[] encryptedData = Encrypt(clearBytes, pdb.GetBytes(32), pdb.GetBytes(16));
return Convert.ToBase64String(encryptedData);
}
private static byte[] Encrypt(byte[] candelaData, byte[] Key, byte[] IV)
{
MemoryStream ms = new MemoryStream();
CryptoStream cs = null;
Rijndael alg = Rijndael.Create();
alg.Key = Key;
alg.IV = IV;
cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(candelaData, 0, candelaData.Length);
cs.FlushFinalBlock();
return ms.ToArray();
}
I want to convert the following algo in java, I have searched for the libraries and couldn't get anything. Help Please. ?
Darab , your best bet in Java has to be Bouncy Castle. You have API's for crypt in salting as well as the AES Rijndael as i read from the code.
For the Rejndael part you can refer : http://www.itcsolutions.eu/2011/08/24/how-to-encrypt-decrypt-files-in-java-with-aes-in-cbc-mode-using-bouncy-castle-api-and-netbeans-or-eclipse/. This gives you a fair idea of the AES part of the code and this question here Rfc2898DeriveBytes in java gives you a great idea of salting and Rfc2898 as well.

Javascript Equivalent of Java AES+SecretKeySpec Decryption

Below is my java code which I am trying to move to NodeJS.
public static String decryptDataWithKey(String keyString, String base64String) throws Exception {
//Algorithm
String AES_ALGORITHM = "AES";
//Key from keystring
MessageDigest digester = MessageDigest.getInstance("MD5");
digester.update(keyString.getBytes());
byte[] password = digester.digest();
Key key = new SecretKeySpec(password, AES_ALGORITHM); // what is the equivalent of this line in javascript ?
//Create decipher
Cipher c = Cipher.getInstance(AES_ALGORITHM);
c.init(Cipher.DECRYPT_MODE, key);
//Get bytes of enc data
byte[] decodedValue = new BASE64Decoder().decodeBuffer(base64String);
// Do decrypt
byte[] decValue = c.doFinal(decodedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
}
I ended up writing below method, but getting exception - Bad Decrypt
function decryptDataWithKey(keyString, base64String){
//Algorithm
let algorithm = 'aes-128-ecb';
//Key from keystring
let key = crypto.createHash('md5').update(keyString).digest();
//Create decipher
let decipher = crypto.createDecipher(algorithm,key);
//Get bytes of enc data
let cipher = new Buffer(base64String, 'base64');
// Do decrypt
let decrypted = decipher.update(cipher, 'base64', 'utf-8');
decrypted += decipher.final('utf-8'); // throwing exception : digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
return decrypted;
}
Please guide me what I am missing here. I am trying to avoid the jar dependency in my nodejs project. I believe this should be achievable using crypto.
Or Should I go for crypto-js ?

Public Key Unknown Encoding

I have this public key:
MIGJAoGBAKv4OKlpY2oq9QZPMzAjbQfiqDqTnisSvdLP+mTswZJdbtk1J+4+qAySJuZjSQljzcUu0ANg+QG0VsvoU72zu5pErZKWubfe9HB/tq69bhP60qgP6/W2VebWlqUNGtsMedxuVaFBL3SoqU7e5RELIsuArCJJIgz86BQDX0x63VpXAgMBAAE=
I am trying to use it to decode this:
Zm/qR/FrkzawabBZYk7WfQJNMVZoZrwWTvfQwIhPMzAuqEO+y+sb/x9+TZwTbqmu45/GV4yhKv0bbDL8F6rif7RJap7iQUFQBDEIAraY42IGZ8pB6A0Q0RSnJWW+tLTLJg5cTrgZQ8sLoO+U03T6DE1wy73FU5h6XhXxZERo0tQ=
In which I know the unencrypted value is this:
2ABB43E83F7EC33D0D33F64BA5782E42
I have been trying several different things including Bouncy Castle (Java implementation) but I am unable to get the public key to work, mostly ending in invalid encoding errors.
This is my current implementation:
byte[] keyBytes = Base64.decodeBase64(PUB_KEY);
try {
AlgorithmIdentifier rsaIdent = new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption);
SubjectPublicKeyInfo kInfo = new SubjectPublicKeyInfo(rsaIdent, keyBytes);
ASN1Primitive primKey = kInfo.parsePublicKey();
byte[] encoded = primKey.getEncoded();
byte[] sessionBytes = Base64.decodeBase64("Zm/qR/FrkzawabBZYk7WfQJNMVZoZrwWTvfQwIhPMzAuqEO+y+sb/x9+TZwTbqmu45/GV4yhKv0bbDL8F6rif7RJap7iQUFQBDEIAraY42IGZ8pB6A0Q0RSnJWW+tLTLJg5cTrgZQ8sLoO+U03T6DE1wy73FU5h6XhXxZERo0tQ=");
Security.addProvider(new BouncyCastleProvider());
X509EncodedKeySpec spec = new X509EncodedKeySpec(encoded);
KeyFactory factory = KeyFactory.getInstance(spec.getFormat());
Cipher cipher = Cipher.getInstance("RSA", "BC");
cipher.init(Cipher.DECRYPT_MODE, factory.generatePublic(spec));
// ----- THIS IS WHERE IT BREAKS -----
byte[] decrypted = cipher.doFinal(sessionBytes);
String tada = new String(decrypted, StandardCharsets.UTF_8);
} catch (Exception e) { ... }
When I get to generate the public key from the factory I get
java.lang.IllegalArgumentException: unknown object in getInstance: org.bouncycastle.asn1.ASN1Integer
I have tried several other things but all result in the same error above.
Is there something wrong with my public key? What is the correct way to do this?
First of all, your key is PKCS#1 encoded. It's not a SubjectPublicKeyInfo structure required by Java. You can see how to decode it here.
Second, you cannot decrypt with a public key, you need a private key for that.

Getting different RSA encryption result in different language?

I am trying to encypt some data using RSA public key and signing with SHA-512 algo. But response recevied is differnet in different plat
form.
In C#:
RSACryptoServiceProvider crypto = new RSACryptoServiceProvider();
crypto.ImportCspBlob(Convert.FromBase64String(publickey));
crypto.exportParameters(false); // and got the public key modulus and exp
byte[] response = crypto.SignData(data, "SHA512");
In Java:
// got modulus and exp for public key from c#
byte[] modulo = {.....};
byte[] exp = {1,0,1};
BigInteger modulus = new BigInteger(1, modulo);
BigInteger pubExp = new BigInteger(1, exp);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPublicKeySpec priKeySpec = new RSAPublicKeySpec(modulus, pubExp);
RSAPublicKey Key = (RSAPublicKey)keyFactory.generatePublic(priKeySpec);
// Calculate Hash
MessageDigest sha1 = MessageDigest.getInstance("SHA-512");
byte[] digest = sha1.digest(data);
// Encrypt digest
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, Key);
byte[] response = cipher.doFinal(digest);
but both response are not matching.C# generate correct one but java not generating the same byte[]
Any missing part in java code.
private static final String algorithm = "AES/CBC/NOPadding";
if we convert type 中國傳統的 languages then we get null value when we encryt.To overcome this problem we use below thing.
private static final String algorithm = "AES/CBC/PKCS5Padding";
if we do diifferent type languages like 中國傳統的 converion can be encryted.

java.security.InvalidKeyException: invalid key format on generating RSA public key

Background:
I have created an applet to extract public key of a certificate extracted from a smart card.
This public key is then stored in database.
The private key of certificate is used to sign data and the public key is then used to verify the signature.
Code for extracting public key from certificate:
private byte[] getPublicKey(KeyStore paramKeyStore)
throws GeneralSecurityException {
Enumeration localEnumeration = paramKeyStore.aliases();
if (localEnumeration.hasMoreElements()) {
String element = (String) localEnumeration.nextElement();
Certificate[] arrayOfCertificate =
paramKeyStore.getCertificateChain(element);
byte[] publicKeyByteArray =
arrayOfCertificate[0].getPublicKey().getEncoded();
return publicKeyByteArray;
}
throw new KeyStoreException("The keystore is empty!");
}
This publicKeyByteArray is then storeed in database as BLOB after converting to string using bytes2String method:
private static String bytes2String(byte[] bytes) {
StringBuilder string = new StringBuilder();
for (byte b : bytes) {
String hexString = Integer.toHexString(0x00FF & b);
string.append(hexString.length() == 1 ? "0" + hexString : hexString);
}
return string.toString();
}
The content of the BLOB(key) saved in database is:
30820122300d06092a864886f70d01010105000382010f003082010a02820101009bd307e4fc38adae43b93ba1152a4d6dbf82689336bb4e3af5160d16bf1599fe070f7acbfefd93e866e52043de1620bd57d9a3f244fb4e6ef758d70d19e0be86e1b12595af748fbc00aad9009bd61120d3348079b00af8462de46e254f6d2b092cbc85c7f6194c6c37f8955ef7b9b8937a7e9999541dbbea8c1b2349c712565482dbd573cd9b7ec56a59e7683b4c246620cf0d8148ed38da937f1e4e930eb05d5b4c6054712928fa59870763468c07e71265525e1e40839b51c833579f5742d3c8e0588766e3ed6deef1593b10baad0a2abea34734de1505d37710e1cfaa4225b562b96a6a4e87fecb1d627d4c61916e543eba87054ee9212e8183125cdb49750203010001
After reading the stored public key byte[] from database, I try to convert it back to Public Key using following code:
Cipher rsa;
rsa = Cipher.getInstance("RSA");
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(pkey.getBytes());
PublicKey pk = keyFactory.generatePublic(publicKeySpec);
rsa.init(Cipher.DECRYPT_MODE, pk);
byte[] cipherDecrypt = rsa.doFinal(encryptedText.getBytes());
but it gives following error:
Caused by: java.security.InvalidKeyException: invalid key format
at sun.security.x509.X509Key.decode(X509Key.java:387)
at sun.security.x509.X509Key.decode(X509Key.java:403)
at sun.security.rsa.RSAPublicKeyImpl.<init>(RSAPublicKeyImpl.java:83)
at sun.security.rsa.RSAKeyFactory.generatePublic(RSAKeyFactory.java:298)
at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:201)
Please suggest the reason and resolution for this issue.
You must have an error in the way you read the key back from the database. The following code works just fine for me:
String key = "3082012230..."; // full key omitted for brevity
byte[] derPublicKey = DatatypeConverter.parseHexBinary(key);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(derPublicKey);
keyFactory.generatePublic(publicKeySpec);
I would guess, based on the use of pkey.getBytes(), that you've simply tried to get the bytes from the string rather than hex-decoding it.

Categories