How to perform Base64 on top of HASH in Java - java

I have the following example in Javascript, I can't seem to find the equivalent in Java for it
var rapyd_signature = CryptoJS.enc.Hex.stringify(CryptoJS.HmacSHA256(data, key));
rapyd_signature = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(rapyd_signature));
What I have (which does not give the same result)
Mac hmacSHA256 = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
hmacSHA256.init(secretKeySpec);
byte[] tobeEncoded = data.getBytes(StandardCharsets.UTF_8);
String rapyd_signature = Base64.getEncoder().encodeToString(tobeEncoded);

You initialized hmacSHA256 … and then you didn’t do anything with it.
You need to actually hash the data, by calling hmacSHA256.doFinal:
Mac hmacSHA256 = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
hmacSHA256.init(secretKeySpec);
byte[] tobeEncoded = data.getBytes(StandardCharsets.UTF_8);
toBeEncoded = hmacSHA256.doFinal(toBeEncoded);
String rapyd_signature = Base64.getEncoder().encodeToString(tobeEncoded);

Related

Encrypt payload using a key and iv by AES/GCM/NoPadding algorithm in node js and decrypt in java

I have encrypt the file using node.js and decrypt in JAVA. Decryption is done in JAVA using "AES/GCM/Nopadding" algorithm and it is third party app hence I cannot see the JAVA code.
I am encrypting the payload in node.js using "aes-128-gcm" algorithm.
for this, I am try mimicking a working java encryption code
I have tried with crypto and node-forge.
iam getting the output but am getting an error "Bad encryption - payload is not encrypted properly" when submitting payload.
pleas help me to find what I did wrong in this code.
working code in java
public void encrypt(#NonNull final byte[] payload, #NonNull final byte[] key) throws GeneralSecurityException
{
SecretKeySpec codingKey = new SecretKeySpec(key, AES);
Cipher cipher = AEC_GCM_THREAD_CIPHER.get();
byte[] iv = new byte[cipher.getBlockSize()];
RANDOM.nextBytes(iv);
cipher.init(Cipher.ENCRYPT_MODE, codingKey, new IvParameterSpec(iv));
final byte[] encryptedPayload = cipher.doFinal(payload);
byte[] encryptMerchantKey = encryptMerchantKey(key);
String payloadFinal = encodeToUrlString(encryptedPayload); // final payload
String ivFinal = encodeToUrlString(iv); // final iv
String keyFinal = encodeToUrlString(encryptMerchantKey); // final key
System.out.println("Payload");
System.out.println(payloadFinal);
System.out.println("iv");
System.out.println(ivFinal);
System.out.println("key");
System.out.println(keyFinal);
}
code iam tried in node js
function encrypt(payload) {
let key = forge.random.getBytesSync(16);
let iv = forge.random.getBytesSync(16);
let cipher = forge.cipher.createCipher("AES-GCM", key);
cipher.start({ iv: iv});
cipher.update(forge.util.createBuffer(payload));
cipher.finish();
let encrypted = forge.util.encode64(cipher.output.getBytes());
let tag = forge.util.encode64(cipher.mode.tag.getBytes());
let iv64 = forge.util.encode64(iv);
let encryptedPayload = encrypted+tag;
//RSA Encryption
encryptedkey = RSAencrypt(forge.util.encode64(key));
return {
"payload" : base64url.fromBase64(encryptedPayload) ,
"iv" : base64url.fromBase64(iv64).length,
"key" : base64url.fromBase64(encryptedkey)
};
}
Rsa description is working fine abling to decrypt the key.
some problem with aes encryption. as see the code, I added auth tag and encrypted data together but no use.
I have complete example of encryption and decryption in angular and java you can take this example as it is and make changes according to you.
Install node-forge with command "npm install node-forge".
encrypt(msg, pass) {
const key = CryptoJS.lib.WordArray.random(8).toString();
const iv = CryptoJS.lib.WordArray.random(8).toString();
// encrypt some bytes using GCM mode
const cipher = forge.cipher.createCipher('AES-GCM', key);
cipher.start({
iv: iv,
additionalData: 'nvn', // optional
tagLength: 128 // optional, defaults to 128 bits
});
cipher.update(forge.util.createBuffer(msg));
cipher.finish();
const encrypted = cipher.output;
const encodedB64 = forge.util.encode64(encrypted.data);
const tag = cipher.mode.tag;
const tagB64 = forge.util.encode64(tag.data);
// outputs encrypted hex
const trasmitmsg = key+iv+tagB64+encodedB64;
return trasmitmsg
}
I have used CryptoJS to generate random string because random of node-forge giving nontransferable strings.
java code to decrypt this trasmitmsg is
public String getDecrypt(String transmsg) throws Exception {
String keyString = transmsg.substring(0, 16);
String ivString = transmsg.substring(16, 32);
String additionalString = transmsg.substring(32, 56);
String cipherString = transmsg.substring(56);
byte[] keyBytes = keyString.getBytes();
SecretKey key = new SecretKeySpec(keyBytes, "AES");
byte[] ivBytes = ivString.getBytes();
byte[] one = Base64.getDecoder().decode(cipherString);
byte[] two = Base64.getDecoder().decode(additionalString);
byte[] cipherText = ArrayUtils.addAll(one, two);
return decrypt(cipherText, key, ivBytes);
}
public static String decrypt(byte[] cipherText, SecretKey key, byte[] IV) throws Exception {
// Get Cipher Instance
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
// Create SecretKeySpec
SecretKeySpec keySpec = new SecretKeySpec(key.getEncoded(), "AES");
// Create GCMParameterSpec
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH , IV);
// Initialize Cipher for DECRYPT_MODE
cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec);
cipher.updateAAD("nvn".getBytes());
byte[] decryptedText = cipher.doFinal(cipherText);
return new String(decryptedText);
}
Cheers!!!
The problem was with forge buffer it need to convert to node buffer
this code is working now. thanks, #Maarten Bodewes for the advice.
function encrypt(payload) {
//initialize forge random buffer
var key = forge.random.getBytesSync(16);
var iv = forge.random.getBytesSync(16);
let cipher = forge.cipher.createCipher("AES-GCM", key);
cipher.start({iv : iv});
cipher.update(forge.util.createBuffer(payload));
cipher.finish();
let encrypted = cipher.output.data;
let tag = cipher.mode.tag.data;
let encryptedLoad = encrypted+tag;
// node buffer and forge buffer differ, so the forge buffer must be converted to node Buffer
iv = Buffer.from(iv, "binary");
encryptedLoad = Buffer.from(encryptedLoad, "binary");
//Calling RSA Encryption
encryptedKey = RSAencrypt(key);
return {
"payload" : base64url(encryptedLoad) ,
"iv" : base64url(iv),
"key" : base64url.fromBase64(encryptedKey)
};
}

PHP PEAR Crypt_CBC implementation in java

I am trying to encrypt a value using the BLOWFISH cipher. The implementation must be in java and having the same result as the php version:
require_once('/usr/share/php/Crypt/CBC.php');
....
$cipher = new Crypt_CBC($key, 'BLOWFISH');
$encryptedPassword = $cipher->encrypt($valueToEncrypt);
echo "ENCODED STRING: " . $encryptedPassword;
$encodedPassword = base64_encode($encryptedPassword);
echo "ENCRYPTED STRING: " . $encodedPassword;
I tried something like this, but I cannot manage to get something even remotely similar:
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "Blowfish");
String IV = "RandomIV";
Cipher cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
init(Cipher.ENCRYPT_MODE, keySpec
, new javax.crypto.spec.IvParameterSpec(IV.getBytes())
);
byte[] encryptedBytes = cipher.doFinal(toEncrypt.getBytes());
String encoded = Base64.getEncoder().encodeToString(encryptedBytes);
Any helping idea is appreciated

emulating PBEWITHMD5ANDDES encryption under .net from JAVA

I am trying to emulate same behaviour of Java in C#. But I am not getting desired result. Key generated by both is different.
JAVA CODE
public static String generateDecryptedKey(String secretKey, String authKey)
{
String strDecryptedKey = "";
byte[] salt = { (byte)0x09, (byte)0xD5, (byte)0xA1, (byte)0xA6, (byte)0xA3, (byte)0xA7, (byte)0xA9, (byte)0xA0 };
int iterationCount = 10;
KeySpec keySpec = new PBEKeySpec(secretKey.toCharArray(), salt, iterationCount);
SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec);
AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);
dcipher = Cipher.getInstance(key.getAlgorithm());
dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
byte[] enc = Base64.decodeBase64(authKey.getBytes());
byte[] utf8 = dcipher.doFinal(enc);
strDecryptedKey = new String(utf8, "UTF-8");
return strDecryptedKey;
}
C# CODE
public static string generateDecryptedKey(string secretKey,string authKey)
{
string strDecryptedKey = string.Empty;
byte[] salt = { (byte)0x09, (byte)0xD5, (byte)0xA1, (byte)0xA6, (byte)0xA3, (byte)0xA7, (byte)0xA9, (byte)0xA0 };
int iterationCount = 10;
PKCSKeyGenerator kp = new PKCSKeyGenerator();
ICryptoTransform crypt = kp.Generate(secretKey, salt, iterationCount, 1);
var bytes = Encoding.UTF8.GetBytes(authKey);
byte[] resultBytes = crypt.TransformFinalBlock(bytes, 0, bytes.Length);
strDecryptedKey = Convert.ToBase64String(resultBytes);
return strDecryptedKey;
}
Result generated by both function upon same input is coming wrong. I am new to cryptography, please someone explain where I am doing wrong. Below is the link for class written by BobJanova that I am using in C# conversion.
https://www.codeproject.com/Articles/16450/Emulating-PBEWithMD-AndDES-Encryption-under-NET
NOTE: I don't want to reveal my SALT value so I had changed to some value. Hope you understand.
You should use
var bytes = Convert.FromBase64String(authKey);
instead of
var bytes = Encoding.UTF8.GetBytes(authKey);
and
strDecryptedKey = Encoding.UTF8.GetString(resultBytes);
instead of
strDecryptedKey = Convert.ToBase64String(resultBytes);
in C#.
Also, authKey.getBytes() in Java might lead to problems down the line. Always specify an encoding like authKey.getBytes("UTF-8").

Java - repetitive hmacSHA1 hashing - how to convert to PHP?

How do you convert the following Java to PHP?
byte[] byteArray1 = key1.getBytes("UTF8");
byte[] byteArray2 = key2.getBytes("UTF8");
byte[] byteArray3 = key3.getBytes("UTF8");
byte[] byteArray4 = key4.getBytes("UTF8");
Mac mac = Mac.getInstance("HmacSHA1");
SecretKeySpec derivedKey = new SecretKeySpec(byteArray1, "HmacSha1");
mac.init(derivedKey); derivedKey = new SecretKeySpec(mac.doFinal(byteArray2), "HmacSha1"); }
mac.init(derivedKey); derivedKey = new SecretKeySpec(mac.doFinal(byteArray3), "HmacSha1");
mac.init(derivedKey); derivedKey = new SecretKeySpec(mac.doFinal(byteArray4), "HmacSha1");
From all the research I've done, it looks like if we'd remove the last two lines, we could neatly convert it to PHP as follows:
hash_hmac("sha1", $key2, $key1, true);
However, how to you convert this type of reiterative hashing to PHP?
Note: I've tried the following unsuccessfully:
$derivedKey = hash_hmac("sha1", $key2, $key1, true);
$derivedKey = hash_hmac("sha1", $key3, $derivedKey, true);
$derivedKey = hash_hmac("sha1", $key4, $derivedKey, true);

HmacSHA256 Encoding in java

I just want to encode a given string to HmacSHA256 according to a private key in java.anyone can provide a simple program....?
SecureRandom sr = new SecureRandom();
byte[] keyBytes = new byte[20];
sr.nextBytes(keyBytes);
SecretKey key = new SecretKeySpec(keyBytes, "HmacSHA1");
Mac m = Mac.getInstance("HmacSHA1");
m.init(key);
m.update(inputData);
byte[] mac = m.doFinal();
Copied from 'http://oreilly.com/catalog/javacrypt/chapter/ch06.html', you'll find all other cryptographic information there.

Categories

Resources