Sign SHA512-HMAC with private key in java - javascript

I want to build a function that sign a SHA512 HMAC with a Private key with a password to open that file. I have done that with Javascript but I'm not able to do it in JAVA. here is my code in Javascript:-
const fs = require('fs')
const crypto = require('crypto');
const getSignatureByInput = (input, crt) => {
let privatePem = fs.readFileSync(crt);
let key = privatePem.toString('ascii');
let sign = crypto.createSign('RSA-SHA512');
sign.write(input)
let signature = sign.sign({ key, passphrase: 'Password' }, 'hex')
return signature;
}
// Usage
let hamc = crypto.createHmac("sha512", '12345678-73a8-414c-9832-fcd4b2d9b362').update(
JSON.stringify({
"body": {
"Id": "123"
}
})
).digest("hex");
console.log(hamc)
let signatureSignedByPrivateKey = getSignatureByInput(hamc,'./private.key');
console.log(signatureSignedByPrivateKey)
and the below is the example of my private key:-
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIHKTAbBgoqhkiG9w0BDAEDMA0ECATHx+tZ0+/NAgFMBIIHCPbvt4YTQkSTuo4f
ktF/iP1gzY9hYQjg5i3Lj8Qj2DOYK7PY6RXNGJQWaq0s06GhQbGhKc7pXaUBvCbD
N2T7VsBtP8ng+xw8WNX5ynzxbcSUBNrjOPRzZPL8YdfJmBl2tVt6jz4hbCIYldZx
nrMb0kdnIRQ0BR8fizQIZDoUxe4nZqevU6506Aj6G8tJ3Aq4prhSho8/wXSNY5KR
NYkqmqB/FjkjgFJekcslFBddro75SqathPB9etWJIEV9ZB98r2bH/ZGnHjj/Kw/4
3HnBhOfKX/gT36VlqUKrsIfmHNjMRSo5d4OaB7ZHCwofQ3CLVYA2pfqE1zx/w0ZE
pwEaMNnxxScjyk3utSyoupahCCIfnM+Ka89kxr0jL10gqi1nCoHTX5+2e1SeTAsR
8b2dj7hllR0AF+zez1zaOrcJXBfbps1pnW4HB7O+QylEjMm8k//yLnc+fmomylfq
hGe8MrNT6hbb6zEU1VB+6p0pyCysgEGAheCRqS27zrr5fzi18/dd1onSC0aCBRxy
69C8296TTx16GqpogvVz18fb5myLlT5cMptQhvfOmeDrv8M7jw+zfrgLyqPjJD37
NIX+3ggSkg6Pt2hYe3NPvgRxwZen+YiZWeri7v1CjaHlr6Lvl55qS/L8uSpg7fxl
kdJXRfm7knNlG9NeT+S68OpHFSzn/DzpimrXttkXsWJOD9Q27XKTCHDyAwDsig8w
lu0Pypqja4HlN9UErgWaIqOQ5gSPIHSmNXwTHSwNqbdkZb4u8gllD/9zqRvvrHV2
IHavf7UELrARvlIInpVTnFy82TkFg4UH48LiCS4s3hfgJUQTGAcbjCgNsuo/RpcT
gCTqu3eaVXCpWTmvuQM8eIR8rgf7y6mUsA5c5Oo+GJ/YIydp/HkK2iJZMr59VWtB
96i0kdxNoHQIZ94efg8YbK5iqIGPLV8a7+wYu3/EBf6TteKbv72jTt9KWnxqIY9F
gNQsWXhKRb2E/i3yz/KjbS9G9rpnkU7+Xr6etR0kf7RMavSz1cP8kfMdbhzCnoe3
XyVuQo0LSit8Z0olyaRIW10L7Jg85MLzpD//CBmcCUpSu1Mtufv0KHnPX5hEcZWb
DVkKELZQfWW5W1jNbj6KIQIzl1Zgs+Gb9SmzI4s5SqEmeQluvgeEMb7HvgRpF/wE
Bwdx9mZUTGY3iX/wlWpdKk+SabfkjH0gZHkEVfwAujeDNvwXl1w+M4EYm7n1cCZM
lDEK3JvOy1vkbgmtsrmxJpzw7KvfcKIwsIK2OY0JVSyb6nm0QkG59Etxd8kztdsy
9GGHsJ3iEuHrcAeWEdO0JOjnvZJkHWtmJXaruzeAPI/qB9E3nFKd1ALfmA4ueCZ1
B7lldSEzRJzwFKa2Q6TUNnsdF3ApgMBkJYuf2grHK9r8bmjPkvZBZ8JRy0cnqAML
fZapjsWUhWa46lmE7ctMmi69YY/gzu2mJNNsaAZRMWF1LO3lVu4/6mzy/whhoS3g
5C5/ia9C9wVxsn8yQORwV0Dj2aBy9QgRldKlxfd8n990wIe+zzYFfv5BTAocvX3n
9OoROEkf62mUw198Hl3LPPnOEOEEO3biYp+/IzalOwY34hEfIwXYQRyaxmNQq0IK
cgO5rtq7GSjG5o13BYAwvQuAkYgJkjuOOKfkfv3R/3JNEdUPoCym1/mlrDj/l96K
IeFgc1wCk/t2pI8kChiYphhL9BNlDb3I32YQjLKg3MnHw/7epcW1gCzFuYnX+wqm
UWVdZH7ryW7a+79IPDbPPqoslkieuJp4Ad7SU+jUb7qeEFbo4GOOMJQhBMVXgaIS
OOg/B6jSgKxx7EbfW68uAh0+7KOGQyCQ4DWgQ9s7jas73tEcOm48NY6+XfV7OqUp
uDZDFoyMmYpI6RiYeyHwFQfdvbtunqKIoLm/yZZm6vJ6xC5krG9uGX8UhnUPbcy0
hYE2Y8KHxjq8NatfTPvr5+fTFD1naw9p03x72rUrdwK6Zg4QXeD0iu1/THXSB2kM
1TFFp2FqQ+lobQYtRwX+QTKZ7Aaw55OZl9481khCpGCAm9xFogsHuMY1b57jK0zf
JLRi/qoQRWTDCmwfxOhmbG9RhJBhX7XxpJ+t4+Splat/9Lw/CJHe37JHO1TmHPXr
IOSbwnCybydr7S/4mRYOJOm8l2BMdPb7IJUX43xI2gnf3NDPidHxz6aiO1XniSWu
/lEsOsmTv7jKjJnObwIAPEzJBkhp9g5Y3gkENkkEIFK/OD8tyTS7b1wsqOU8d4HD
XYd6+WWZhnTG9hixaIqK3PytVAZusB1GAd/ZzukC8U208zN9ud5LRQFIicdXhBFX
amtrYkTn+gCXRax0eDHVi3FohpySKqC22wyLe1C1VC3HvZ+HhZMDt3Hyt1ZeFWHr
XfJTekUHHwFnpKVang==
-----END ENCRYPTED PRIVATE KEY-----
Appreciate your support!
Thanks in advance...

I found a way to solve this thanks #pra-a for answering a question posted earlier Link here.
I will share my solution below.
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.*;
import java.security.spec.*;
public class Main {
public static final String PRIVATE_KEY="./private.der";
public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
// write your code here
//get the private key
File file = new File(PRIVATE_KEY);
FileInputStream fis = new FileInputStream(file);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int) file.length()];
dis.readFully(keyBytes);
dis.close();
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
RSAPrivateKey privKey = (RSAPrivateKey) kf.generatePrivate(spec);
Mac sha512Hmac;
String result = "";
final String key = "'12345678-73a8-414c-9832-fcd4b2d9b362'";
String signature = "";
String body = "{\n" +
" \"body\": {\n" +
" \"Id\": \"123\"\n" +
" }\n" +
"}";
try {
final String HMAC_SHA512 = "HmacSHA512";
final byte[] byteKey = key.getBytes(StandardCharsets.UTF_8);
sha512Hmac = Mac.getInstance(HMAC_SHA512);
SecretKeySpec keySpec = new SecretKeySpec(byteKey, HMAC_SHA512);
sha512Hmac.init(keySpec);
byte[] macData = sha512Hmac.doFinal(body.getBytes(StandardCharsets.UTF_8));
// Can either base64 encode or put it right into hex
//result = Base64.getEncoder().encodeToString(macData);
result = bytesToHex(macData);
signature = sign(result, privKey);
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
// Put any cleanup here
System.out.println("Done");
}
}
private static final char[] HEX_ARRAY = "0123456789abcdef".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}
public static PrivateKey readPrivateKeyII(String filename) throws Exception{
InputStream in = new FileInputStream(filename);
byte[] privateKeydata = new byte[in.available()];
in.read(privateKeydata);
in.close();
KeyFactory privateKeyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec encodedKeySpec = new PKCS8EncodedKeySpec(privateKeydata);
PrivateKey privateKey = privateKeyFactory.generatePrivate(encodedKeySpec);
return privateKey;
}
public static String sign(String plainText, PrivateKey privateKey) throws Exception {
Signature privateSignature = Signature.getInstance("SHA512withRSA");
privateSignature.initSign(privateKey);
privateSignature.update(plainText.getBytes(StandardCharsets.UTF_8));
byte[] signature = privateSignature.sign();
return bytesToHex(signature);
}
}

Related

AES/GCM/NoPadding encryption in JAVA & decryption in JavaScript

I am using AES/GCM/NoPadding 128 bit. I want to encrypt in Java & decrypt it in Javascript.
When I encrypt in JS & try to decrypt in Java I get the error as Tag mismatch!null
When I encrypt in Java & try to decrypt in JS I get the error as
internal/crypto/cipher.js:164
const ret = this._handle.final();
^
Error: Unsupported state or unable to authenticate data
at Decipheriv.final (internal/crypto/cipher.js:164:28)
at decrypt (/tmp/HoErdq6TQ2.js:51:58)
What am I missing in my JS
Please suggest fixes in JS code, Java code can't be changed as it is in use on production
Java code:
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Arrays;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import java.util.logging.Logger;
import java.util.Base64;
public class HelloWorld {
private final static Logger LOGGER = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
public static void main(String []args) {
String masterKey = "2f12cb0f1d2e3d12345f1af2b123dce4";
String encrypted = aesEncryptStringV2("Hello, World!", masterKey);
System.out.println(encrypted);
String decrypted = aesDecryptStringV2(encrypted, masterKey);
System.out.println(decrypted);
}
private static final String ALGORITHM = "AES/GCM/NoPadding";
private static final int GCM_IV_LENGTH = 12;
private static final int GCM_TAG_LENGTH = 16;
private static SecretKeySpec setKeyV2(final String myKey) {
try {
byte[] newKey = myKey.getBytes(StandardCharsets.UTF_8);
MessageDigest sha = MessageDigest.getInstance("SHA-512");
newKey = sha.digest(newKey);
newKey = Arrays.copyOf(newKey, 16);
return new SecretKeySpec(newKey, "AES");
} catch (Exception e) {
System.out.println("Error in setKeyV2: ");
System.out.println(e.getMessage());
}
return null;
}
public static synchronized String aesEncryptStringV2(
final String strToEncrypt, final String secret) {
try {
SecretKeySpec newSecretKey = setKeyV2(secret);
Cipher cipher = Cipher.getInstance(ALGORITHM);
GCMParameterSpec gcmParameterSpec = new
GCMParameterSpec(GCM_TAG_LENGTH * 8,
new byte[GCM_IV_LENGTH]);
cipher.init(Cipher.ENCRYPT_MODE, newSecretKey, gcmParameterSpec);
return Base64.getEncoder()
.encodeToString(cipher.doFinal(strToEncrypt.getBytes(StandardCharsets.UTF_8
)));
} catch (Exception e) {
System.out.println("Error in aesEncryptStringV2: ");
System.out.println(e.getMessage());
}
return null;
}
public static synchronized String aesDecryptStringV2(
final String strToDecrypt, final String secret) {
try {
SecretKeySpec newSecretKey = setKeyV2(secret);
Cipher cipher = Cipher.getInstance(ALGORITHM);
GCMParameterSpec gcmParameterSpec = new
GCMParameterSpec(GCM_TAG_LENGTH * 8,
new byte[GCM_IV_LENGTH]);
cipher.init(Cipher.DECRYPT_MODE, newSecretKey, gcmParameterSpec);
return new
String(cipher.doFinal(Base64.getDecoder().decode(strToDecrypt)));
} catch (Exception e) {
System.out.println("Error in aesDecryptStringV2: ");
System.out.println(e.getMessage());
}
return null;
}
}
Javascript Code:
const crypto = require('crypto');
const cryptoConfig = {
cipherAlgorithm: 'aes-128-gcm',
masterKey: '2f12cb0f1d2e3d12345f1af2b123dce4',
ivLength: 12,
tagLength: 16,
digest: 'sha512'
}
const generateKey = () => {
var h = crypto.createHash(cryptoConfig.digest);
h.update(cryptoConfig.masterKey, 'utf8');
var k = h.digest().slice(0, 16);
return k;
};
function encrypt(content) {
const iv = crypto.randomBytes(cryptoConfig.ivLength);
const key = generateKey();
const cipher = crypto.createCipheriv(cryptoConfig.cipherAlgorithm, key, iv, {authTagLength: cryptoConfig.tagLength});
const encrypted = Buffer.concat([cipher.update(content, 'utf8'), cipher.final()]);
const tag = cipher.getAuthTag();
return Buffer.concat([iv, encrypted, tag]).toString('base64');
}
const decrypt = (encdata, masterkey) => {
const bData = Buffer.from(encdata, 'base64');
const iv = bData.slice(0, 12);
const tag = bData.slice(bData.length - 16, bData.length);
const text = bData.slice(12, bData.length - 16);
const key = generateKey(masterkey);
const decipher = crypto.createDecipheriv('aes-128-gcm', key, iv);
decipher.setAuthTag(tag);
const decrypted =
decipher.update(text, 'binary', 'utf8') + decipher.final('utf8');
return decrypted;
};
const encryptedData = encrypt('hello world');
console.log('encrypt data -> ', encryptedData);
const decryptedData = decrypt(encryptedData);
console.log('decryptedData -> ', decryptedData);
So the Java code doesn't attach IV/nonce to the output. It uses a buffer of 0's of specified length.
Updated JS decryption code:
const decrypt = (encdata, masterkey) => {
const bData = Buffer.from(encdata, 'base64');
const iv = Buffer.alloc(12);
const tag = bData.slice(bData.length - 16, bData.length);
const text = bData.slice(0, bData.length - 16);
const key = generateKey(masterkey);
const decipher = crypto.createDecipheriv('aes-128-gcm', key, iv);
decipher.setAuthTag(tag);
const decrypted =
decipher.update(text, 'binary', 'utf8') + decipher.final('utf8');
return decrypted;
};
Serious security warning: Do NOT use the above code in production as it is UNSECURE. You should consider to change your production code as the encryption in AES GCM mode gets total insecure when using a nonce more than one time with the same key (the Java code is using a static IV/nonce)
Credits - Michael Fehr's comment

Java sign and Javascript verify a signature failed

I am trying to use Java to sign a message on the server side, while verify the signature on the client side, but failed! My steps are as follows:
Generate RSA key pair:
openssl genrsa -out privatekey.pem 2048
openssl pkcs8 -topk8 -inform PEM -outform DER -in privatekey.pem -out private_key.der -nocrypt
openssl rsa -in privatekey.pem -pubout -outform DER -out pubic_key.der
Thus I got pubic_key.der and private_key.der two files.
Using java to load these two files and generate signature.
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import org.apache.commons.codec.binary.Base64;
import com.nimbusds.jose.jwk.*;
public class SignatureTest {
public static KeyPair generateSignKeyPair() throws Exception {
byte[] privBytes = Files.readAllBytes(Paths.get("testFiles/private_key.der"));
byte[] pubBytes = Files.readAllBytes(Paths.get("testFiles/public_key.der"));
// private key
KeySpec keySpec = new PKCS8EncodedKeySpec(privBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
//public key
X509EncodedKeySpec X509publicKey = new X509EncodedKeySpec(pubBytes);
PublicKey publicKey = keyFactory.generatePublic(X509publicKey);
return new KeyPair(publicKey, privateKey);
}
public static byte[] generateSignature(PrivateKey signPrivateKey, byte[] data) throws Exception {
Signature dsa = Signature.getInstance("SHA256withRSA");
dsa.initSign(signPrivateKey);
dsa.update(data);
return dsa.sign();
}
public static boolean verifySignature(PublicKey publicKey, byte[] data, byte[] sig) throws Exception {
Signature dsa = Signature.getInstance("SHA256withRSA");
dsa.initVerify(publicKey);
dsa.update(data);
return dsa.verify(sig);
}
private static String getPEMPrivateKeyFromDER(PrivateKey privateKey) {
Base64 base64 = new Base64();
String begin = "-----BEGIN PRIVATE KEY-----";
String end = "-----END PRIVATE KEY-----";
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey.getEncoded());
String key = new String(base64.encode(pkcs8EncodedKeySpec.getEncoded()));
return begin + "\n" + key + "\n" + end;
}
private static String getPEMPublicKeyFromDER(PublicKey publicKey) {
Base64 base64 = new Base64();
String begin = "-----BEGIN PUBLIC KEY-----";
String end = "-----END PUBLIC KEY-----";
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(publicKey.getEncoded());
String key = new String(base64.encode(pkcs8EncodedKeySpec.getEncoded()));
return begin + "\n" + key + "\n" + end;
}
public static void main(String[] args) {
Base64 base64 = new Base64();
try{
KeyPair keyPair = generateSignKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
// print private key
String privKey = getPEMPrivateKeyFromDER(privateKey);
System.out.println("privKey:\n " + privKey);
// print public key
String pubKey = getPEMPublicKeyFromDER(publicKey);
System.out.println("pubKey:\n " + pubKey);
System.out.println("---------------Convert to JWK-----------------");
RSAKey jwk = new RSAKey.Builder((RSAPublicKey) publicKey).privateKey(privateKey).build();
System.out.println("jwk:\n" + jwk.toPublicJWK());
String data = new String(base64.encode("hello".getBytes()));
// sign "hello"
byte[] sig = generateSignature(keyPair.getPrivate(), "hello".getBytes());
System.out.println("signature base64: " + new String(Base64.encodeBase64(sig)));
// start verify
boolean result = verifySignature(publicKey, "hello".getBytes(), sig);
System.out.println("Verification: " + result);
}catch (Exception e){
e.printStackTrace();
}
}
}
The output of the public key, private key, signature and jwk are as follows:
public key:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0pGjaaEsFCYj3sjfYzTarJPgYgSGtuwMeCMgfzAEFy0va+R83tyRNy7asYtGFB8mpwaED9OvzVJ3JvJKCE81c6Q6yWoZ+xQEzMtvQ3FibH/MH+gBSkgRYczP+dsT9j3n+F6sIRz9qdHfzHCyDPZ0tSf/wmmsX54eayMuH1p417bHv9yysDgXYxWKWiOoYOP6ynYSqMLEIxirkgUYlhsXVTD4RlZOAVBCUIbN2YE41UnQDExEnw6s8u1KHDeiNc15G1zZmm4SX/BNOWEeGjEVB4VJAwTUynaAcGgcBuNxzadpklLqFNYyIbu3WkK8L1Im3vVAuttMYIFF7sWiWLiFDQIDAQAB
-----END PUBLIC KEY-----
private key:
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDSkaNpoSwUJiPeyN9jNNqsk+BiBIa27Ax4IyB/MAQXLS9r5Hze3JE3Ltqxi0YUHyanBoQP06/NUncm8koITzVzpDrJahn7FATMy29DcWJsf8wf6AFKSBFhzM/52xP2Pef4XqwhHP2p0d/McLIM9nS1J//Caaxfnh5rIy4fWnjXtse/3LKwOBdjFYpaI6hg4/rKdhKowsQjGKuSBRiWGxdVMPhGVk4BUEJQhs3ZgTjVSdAMTESfDqzy7UocN6I1zXkbXNmabhJf8E05YR4aMRUHhUkDBNTKdoBwaBwG43HNp2mSUuoU1jIhu7daQrwvUibe9UC620xggUXuxaJYuIUNAgMBAAECggEBAMuzFflucDzBtLulaO0IyW5f05YeuM+mRF3H5X0Ez0A4dwKR0/aoO1a93dQZXl7Cz9qOZB0HdK9U0m17wACP166aNkB4gs+wSwBu4KDGxCcf7jEDeJQKab5JqvwTYhk5Q/myZCPYbs/kdvLIJoaBuN8y5amGHrmVNeoA63JrTDGoH7EVSPuJSDLzYd6Wtj5agAR7t4YRvWgqGsYRwhekXONOkMcoPh+o4WGocfLvI39XTzSTiItX+LfcWIKNL7KhPfjALfmCSzhCBEI0DqjMG4UFusfhGun5RM3Ii+ADfPwR1RkuqfVRvvdCh+B9C2RvflIXbJ8g6VfYDCnSmFyPXsUCgYEA8ju5im9oS+8z4C341IUdWpLthJyKGdBd/fvfTlRQFOroz5fKM8nK52BMf8Z0am641UY7gmNaEVID+z4KSIEIvgK19ymZmIUmMHR9nyFUDG7U05GeR9ocp+E12C5mo6KVkmfydMP0o+JeVcRxIksY5O7KcD1GgajJ2oHuOpJODlMCgYEA3ok5pvfCuZ3BpAblHAtKheCtydqt1vqYdPt1/IwzscJSpBkPNV08LQVjHBduSbZ0CqnSP0m+RkJysl7lJbsUejDZvDLpVTuHbI+/lVKVNsDcjbqFCaQ/YNbCS3/RQR8aHyAOjGvFUT0TyiGCyA0RUtOPQ0lN3jKSlvmB4KIk8x8CgYEA1frmcyDpDDMZK07RAcM5Y/po8P1rjVQgw61M3R/jwialVEStLUR0BiJuUW1ZB3AZvOUWyp7DQIun0rhCUzwRIfC5F8Za1X3Bd4pgMkM5wOXjAaYgIS7Oo4pxiy+qIaEM6dEDQByeLmtYlAE9Q2L9cbZzg+TNNNqKvYiLjpgRddsCgYBk5yvw/V6Z82IeEdJIyQXddmbWpAU2+SGvyWVSQfAepdH6/jHbLI9gipTJ5AXp/oTXYPEoKTPRf8eqAUU9unoqfYP8xcjvELLzEqr39h4aWZCn4u731DW4nygyO56SPJwHiO2P1j39/AfBGzjFpMc6GxtWkyJvoda+BhxR0rOWWQKBgQCXKepBOKEcE+tBpptYNBI3fWZp21W0WggTNcsBTvLHT1few5voRxmVlzoP2h3VB30v9i7JyGlP76nZFN+PEQeTUStmRk5kyi0UMx001+qgAjc2uEYUPxf62luQiJdozaQ+tXQ7KTKiQixqfUC4jQszUIlwFLDZgS7gZ7ynzOIGBQ==
-----END PRIVATE KEY-----
signature:
signature base64: sor4eqf2iBiqJnhMogu2GSx0JlT804l9J4thEkZ6stPZLari3sFa6w1/kxtwR+ogHq+LJM2g25eygTPr6RqndOiVjWnB7l0btnPV+wN4AWzofBSi+vAXL+BA+ANm8QF14JG0yW2acF+Wyn+xZjMid6tCc1IVw/3EOdVGWVATVYigM6HCVxdXE9HLBuj0VK7suWgseAEfxrn5hbzaJT+OxZ4Ozx3YwwyUjeDy62cnirswOMb49bZ7eLEreffCZLnah1URrerXTikFyDSFslZjg4X19q4MArZ+xqm8ON+tLC4NoQw7ST9f7KcYznbw58oEgpvE2mxdiEbsTqWwJ+/BOQ==
jwk (JSON Web Key):
{"kty":"RSA","e":"AQAB","n":"0pGjaaEsFCYj3sjfYzTarJPgYgSGtuwMeCMgfzAEFy0va-R83tyRNy7asYtGFB8mpwaED9OvzVJ3JvJKCE81c6Q6yWoZ-xQEzMtvQ3FibH_MH-gBSkgRYczP-dsT9j3n-F6sIRz9qdHfzHCyDPZ0tSf_wmmsX54eayMuH1p417bHv9yysDgXYxWKWiOoYOP6ynYSqMLEIxirkgUYlhsXVTD4RlZOAVBCUIbN2YE41UnQDExEnw6s8u1KHDeiNc15G1zZmm4SX_BNOWEeGjEVB4VJAwTUynaAcGgcBuNxzadpklLqFNYyIbu3WkK8L1Im3vVAuttMYIFF7sWiWLiFDQ"}
In java, the verification is true!!!
In the client side, I use Webcrypto to verify:
// npm install #trust/webcrypto --save
const crypto = require('#trust/webcrypto');
// Utility function
function str2ab(str) {
var arrBuff = new ArrayBuffer(str.length);
var bytes = new Uint8Array(arrBuff);
for (var iii = 0; iii < str.length; iii++) {
bytes[iii] = str.charCodeAt(iii);
}
return bytes;
}
// The publicKeyB64 is in the form of jwk that output in the step 2
var publicKeyB64 = {"kty":"RSA","e":"AQAB","n":"0pGjaaEsFCYj3sjfYzTarJPgYgSGtuwMeCMgfzAEFy0va-R83tyRNy7asYtGFB8mpwaED9OvzVJ3JvJKCE81c6Q6yWoZ-xQEzMtvQ3FibH_MH-gBSkgRYczP-dsT9j3n-F6sIRz9qdHfzHCyDPZ0tSf_wmmsX54eayMuH1p417bHv9yysDgXYxWKWiOoYOP6ynYSqMLEIxirkgUYlhsXVTD4RlZOAVBCUIbN2YE41UnQDExEnw6s8u1KHDeiNc15G1zZmm4SX_BNOWEeGjEVB4VJAwTUynaAcGgcBuNxzadpklLqFNYyIbu3WkK8L1Im3vVAuttMYIFF7sWiWLiFDQ"};
// the Base64 output of "hello"
var dataB64 = "aGVsbG8=";
// The signature output from step 2
var signatureB64 = "sor4eqf2iBiqJnhMogu2GSx0JlT804l9J4thEkZ6stPZLari3sFa6w1/kxtwR+ogHq+LJM2g25eygTPr6RqndOiVjWnB7l0btnPV+wN4AWzofBSi+vAXL+BA+ANm8QF14JG0yW2acF+Wyn+xZjMid6tCc1IVw/3EOdVGWVATVYigM6HCVxdXE9HLBuj0VK7suWgseAEfxrn5hbzaJT+OxZ4Ozx3YwwyUjeDy62cnirswOMb49bZ7eLEreffCZLnah1URrerXTikFyDSFslZjg4X19q4MArZ+xqm8ON+tLC4NoQw7ST9f7KcYznbw58oEgpvE2mxdiEbsTqWwJ+/BOQ==";
var signatureAlgorithm = {name: 'RSASSA-PKCS1-v1_5', modulusLength: 2048, publicExponent: new Uint8Array([0x01, 0x00, 0x01]), hash: {name: 'SHA-256'}};
var data = str2ab(Buffer.from(dataB64, 'base64').toString());
var signature = str2ab(Buffer.from(signatureB64, 'base64').toString());
crypto.subtle.importKey("jwk", publicKeyB64, signatureAlgorithm, false, ["verify"]).then(function(pubkey){
console.log("pubkey: " + pubkey);
return crypto.subtle.verify(signatureAlgorithm, pubkey, signature, data);
}).then( function (valid) {
console.log("Signature valid: ----- " + valid + " -----");
}).catch(function(err) {
console.log("Verification failed: \n" + err );
});
The result shows:
Signature valid: ----- false -----
I am wondering I made mistake in any step and could anyone help with this issue? Thanks a lot.

Java encryption to javascript decryption AES, CryptoJS, CTR

I am having encryption and decryption code already in place.
But now i am just going to use java encryption for encrypting the text.
And going to decrypt it in JavaScript using CryptoJS.
#Service
public class EncryptionServiceImpl extends EncryptionService {
protected static final int BLOCK_SIZE_BYTES = 16;
protected static final int BLOCK_SIZE_BITS = 128;
protected SecureRandom secureRandom;
protected int keySizeByte;
#Value("${encryption.key}")
private String keyString ;
public EncryptionServiceImpl() {
byte[] key = keyString.getBytes();
//create secret key spec instance
secretKeySpec = new SecretKeySpec(key, "AES");
try {
cipher = javax.crypto.Cipher.getInstance("AES/CTR/NoPadding");
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
}
//create secure random number generator instance
secureRandom = new SecureRandom();
}
public String encrypt(String data) {
byte[] dataByte = new byte[0];
try {
dataByte = data.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
}
//create iv
SecureRandom randomSecureRandom;
IvParameterSpec ivParams = null;
byte[] iv = new byte[0];
try {
randomSecureRandom = SecureRandom.getInstance("SHA1PRNG");
iv = new byte[cipher.getBlockSize()];
randomSecureRandom.nextBytes(iv);
ivParams = new IvParameterSpec(iv);
} catch (NoSuchAlgorithmException e) {
}
try {
cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, secretKeySpec, ivParams);
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
throw e;
}
//return concatenation of iv + encrypted data
byte[] encByteArr;
try {
encByteArr = ArrayUtils.addAll(iv, cipher.doFinal(dataByte));
} catch (IllegalBlockSizeException | BadPaddingException e) {
throw e;
}
return Base64.encodeBase64URLSafeString(encByteArr);
}
public String decrypt(String encryptedData) {
byte[] decodedValue = Base64.decodeBase64(encryptedData);
byte[] iv = new byte[BLOCK_SIZE_BYTES];
System.arraycopy(data, 0, iv, 0, BLOCK_SIZE_BYTES);
try {
cipher.init(javax.crypto.Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(iv));
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
}
//return decrypted value
byte[] decryptedByteArray;
try {
decryptedByteArray = cipher.doFinal(data, BLOCK_SIZE_BYTES, data.length - BLOCK_SIZE_BYTES);
} catch (IllegalBlockSizeException | BadPaddingException e) {
}
try {
return new String(decryptedByteArray,"UTF-8");
} catch (UnsupportedEncodingException e) {
}
return new String(decryptedByteArray);
}
}
I want to do the exact decryption in JS that what i did in java.
I am new to JS.
i am trying below things to convert it in js.
I think looking at the code, i need to get rid of IV from encrypted text. but IV generated with SecureRandom. Unable to figure out how to get the rid of IV in JS.
import CryptoJS from 'crypto-js';
/* eslint-disable no-restricted-globals */
function decryption(val) {
const encrypted = CryptoJS.enc.Base64.parse(val);
const key = CryptoJS.enc.Base64.parse("<my encryption key used in java code>");
const iv = CryptoJS.enc.Base64.parse(val);
const valueDec = CryptoJS.enc.Utf8.stringify(CryptoJS.AES.decrypt(
{ ciphertext: encrypted },
key,
{ mode: CryptoJS.mode.CTR, padding: CryptoJS.pad.NoPadding, iv: iv, }));
return valueDec;
}

how to decrypt in nodejs which is encrypted using JAVA

im trying to convert java lambda into javascript lamda. want to convert these encrypt and decrypt method which is written in java to node js or javascript.
I have tried to implement using crpto in node
keys are like this
private static String CIPHER_NAME = "AES/CBC/PKCS5PADDING";
private static int CIPHER_KEY_LEN = 16; //128 bits
encrypt method
private String encrypt(String key, String iv, String data) {
try {
if (key.length() <CIPHER_KEY_LEN) {
int numPad = CIPHER_KEY_LEN - key.length();
for(int i = 0; i < numPad; i++){
key += "0"; //0 pad to len 16 bytes
}
} else if (key.length() >CIPHER_KEY_LEN) {
key = key.substring(0, CIPHER_KEY_LEN); //truncate to 16 bytes
}
IvParameterSpec initVector = new IvParameterSpec(iv.getBytes("ISO-8859-1"));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("ISO-8859-1"), "AES");
Cipher cipher = Cipher.getInstance(CIPHER_NAME);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, initVector);
byte[] encryptedData = cipher.doFinal((data.getBytes()));
String base64_EncryptedData = Base64.getEncoder().encodeToString(encryptedData);
String base64_IV = Base64.getEncoder().encodeToString(iv.getBytes("ISO-8859-1"));
return base64_EncryptedData + ":" + base64_IV;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
decrypt method
private String decrypt(String key, String data) {
try {
if (key.length() < CIPHER_KEY_LEN) {
int numPad = CIPHER_KEY_LEN - key.length();
for(int i = 0; i < numPad; i++){
key += "0"; //0 pad to len 16 bytes
}
} else if (key.length() > CIPHER_KEY_LEN) {
key = key.substring(0, CIPHER_KEY_LEN); //truncate to 16 bytes
}
String[] parts = data.split(":");
IvParameterSpec iv = new IvParameterSpec(Base64.getDecoder().decode(parts[1]));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("ISO-8859-1"), "AES");
Cipher cipher = Cipher.getInstance(CIPHER_NAME);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] decodedEncryptedData = Base64.getDecoder().decode(parts[0]);
byte[] original = cipher.doFinal(decodedEncryptedData);
return new String(original);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
I have used
this is the solution i made but seems it not working cause i encrypted this using a java code and using node's javascript code to decrypt it.
function decrypt (messagebase64, keyBase64, ivBase64) {
var key = Buffer.from(keyBase64, 'base64');
var iv = Buffer.from(ivBase64, 'base64');
var decipher = crypto.createDecipheriv(getAlgorithm(keyBase64), key, iv);
decipher.setAutoPadding(false);
decipher.update(messagebase64, 'base64');
return decipher.final();
}
find the alogorithm i use this and adding padding if the key is not long enough but this give error that saying length is not enough.
function getAlgorithm(keyBase64) {
if(keyBase64.length<CIPHER_KEY_LEN){
var padding = CIPHER_KEY_LEN-keyBase64.length;
for(var i=0;i<padding;i++){
keyBase64+="0";
}
}else if(keyBase64.length>CIPHER_KEY_LEN){
keyBase64 =keyBase64.substring(0, CIPHER_KEY_LEN)
}
var key = Buffer.from(keyBase64, 'base64');
switch (key.length) {
case 16:
return 'aes-128-cbc';
case 32:
return 'aes-256-cbc';
}
throw new Error('Invalid key length: ' + key.length);
}
after struggling for a while i have implemented encrypted method and decrypt method which will be identical to java.
decrypt method
function decrypt (messagebase64, keyBase64, ivBase64) {
if(keyBase64.length<CIPHER_KEY_LEN){
var padding = CIPHER_KEY_LEN-keyBase64.length;
for(var i=0;i<padding;i++){
keyBase64+="0";
}
}else if(keyBase64.length>CIPHER_KEY_LEN){
keyBase64 =keyBase64.substring(0, CIPHER_KEY_LEN)
}
var key = Buffer.from(keyBase64, 'latin1');
var iv = Buffer.from(ivBase64, 'base64');
var encryptdata = new Buffer(messagebase64, 'base64');
var decipher = crypto.createDecipheriv('aes-128-cbc', key, iv),
decoded = decipher.update(encryptdata, 'base64', 'utf8');
decoded += decipher.final('utf8');
return decoded
}
encrypt method
function encrypt(plainText, keyBase64, ivBase64) {
if(keyBase64.length<CIPHER_KEY_LEN){
var padding = CIPHER_KEY_LEN-keyBase64.length;
for(var i=0;i<padding;i++){
keyBase64+="0";
}
}else if(keyBase64.length>CIPHER_KEY_LEN){
keyBase64 =keyBase64.substring(0, CIPHER_KEY_LEN)
}
var key = Buffer.from(keyBase64, 'latin1');
var iv = Buffer.from(ivBase64,'latin1');
var encoded_base64_iv= iv.toString('base64');
var cipher2 = crypto.createCipheriv('aes-128-cbc', key, iv);
cipher2.write(plainText);
cipher2.end();
var cipher_text = cipher2.read();
var encodedString = cipher_text.toString('base64');
var final_encrypted_data = encodedString+":"+encoded_base64_iv;
return final_encrypted_data.toString();
};

MCrypt class use simcard serial number as SecretKey

How can I read the Simcard serial number and use the first 16 numbers
as a SecretKey
........
private String SecretKey = "0123456789abcdef";**//Read the Simcard serial number and use the first 16 numbers as a SecretKey**
public MCrypt()
{
ivspec = new IvParameterSpec(iv.getBytes());
keyspec = new SecretKeySpec(SecretKey.getBytes(), "AES");
................
what I'm doing wrong ??
public class MCrypt {
static char[] HEX_CHARS = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
private String deviceid = telephonyManager.getSimSerialNumber();
//private String deviceid = "894310210159403811111456457657845786485458";
private String serial = new String (deviceid.substring(0, 16));
private String iv = ""+serial;//Dummy iv (CHANGE IT!) 8943102101594038
private static IvParameterSpec ivspec;
private static SecretKeySpec keyspec;
private static Cipher cipher;
private static Context context;
private String SecretKey = "0123456789abcdef";//Dummy secretKey (CHANGE IT!)
O.k. now I see your problem.
Activity inherit's from Context - so when you are calling getSystemService in your class MCrypt , you are really wanting to call super.getSystemService.
If you want to have a Context available in another class (like MCrypt), you can pass it in as an argument to a method of that class (the constructor, which you already have), and keep a reference to it, etc.
Add Context argument to your constructor in MCrypt:
public class MCrypt {
Context mContext;
TelephonyManager mtelemamanger;
public MCrypt (Context context)//this is a constructor
{
mContext = context;
mtelemamanger = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
...
Add the below permission into your Androidmanifest.xml file.
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
Then use this:
TelephonyManager telemamanger = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
String deviceid = telemamanger.getSimSerialNumber();
the getSimSerialNumber() function returns a string which contains provider info etc. If you want to get the pure sim serial number you have to get the last 14 digits.
String SecretKey = deviceid.substring(Math.max(0, deviceid.length() - 14));
Thats my Worked Code
/**
* Created by Studio on 02/06/2017.
*/
import android.content.Context;
import android.telephony.TelephonyManager;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class MCrypt {
TelephonyManager mtelemamanger;
private static char[] HEX_CHARS = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
private static IvParameterSpec ivspec;
private static SecretKeySpec keyspec;
private static Cipher cipher;
MCrypt(Context con)
{
mtelemamanger = (TelephonyManager) con.getSystemService(Context.TELEPHONY_SERVICE);
String deviceid = mtelemamanger.getSimSerialNumber();
String iv = deviceid.substring(0, 16);
ivspec = new IvParameterSpec(iv.getBytes());
String secretKey = "0123456789abcdef";
keyspec = new SecretKeySpec(secretKey.getBytes(), "AES");
try {
cipher = Cipher.getInstance("AES/CBC/NoPadding");
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public byte[] encrypt(String text) throws Exception
{
if(text == null || text.length() == 0)
throw new Exception("Empty string");
byte[] encrypted;
try {
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
encrypted = cipher.doFinal(padString(text).getBytes());
} catch (Exception e)
{
throw new Exception("[encrypt] " + e.getMessage());
}
return encrypted;
}
static byte[] decrypt(String code) throws Exception
{
if(code == null || code.length() == 0)
throw new Exception("Empty string");
byte[] decrypted = null;
try {
cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
decrypted = cipher.doFinal(hexToBytes(code));
//Remove trailing zeroes
if( decrypted.length > 0)
{
int trim = 0;
for( int i = decrypted.length - 1; i >= 0; i-- ) if( decrypted[i] == 0 ) trim++;
if( trim > 0 )
{
byte[] newArray = new byte[decrypted.length - trim];
System.arraycopy(decrypted, 0, newArray, 0, decrypted.length - trim);
decrypted = newArray;
}
}
} catch (Exception e)
{
throw new Exception("[decrypt] " + e.getMessage());
}
return decrypted;
}
public static String bytesToHex(byte[] buf)
{
char[] chars = new char[2 * buf.length];
for (int i = 0; i < buf.length; ++i)
{
chars[2 * i] = HEX_CHARS[(buf[i] & 0xF0) >>> 4];
chars[2 * i + 1] = HEX_CHARS[buf[i] & 0x0F];
}
return new String(chars);
}
private static byte[] hexToBytes(String str) {
if (str==null) {
return null;
} else if (str.length() < 2) {
return null;
} else {
int len = str.length() / 2;
byte[] buffer = new byte[len];
for (int i=0; i<len; i++) {
buffer[i] = (byte) Integer.parseInt(str.substring(i*2,i*2+2),16);
}
return buffer;
}
}
private static String padString(String source)
{
char paddingChar = 0;
int size = 16;
int x = source.length() % size;
int padLength = size - x;
for (int i = 0; i < padLength; i++)
{
source += paddingChar;
}
return source;
}
}

Categories