I'm trying to implement reCaptcha Secure Tokens in nodejs.
Looked at the examples made in Java and in .NET and created this version for node:
exports.getSecureToken = function() {
var algorithm = 'aes-128-ecb';
var tokenObj = { session_id: 'ab0069ec-3c2c-436c-868b-43c7a10db229'/*uuid.v4()*/, ts_ms: 1446560931992/*(new Date()).getTime()*/ };
var text = JSON.stringify(tokenObj);
var shaHash = new Buffer(crypto.createHash('sha1').update('6LeyNOTTVALIDH2RLNaivqrrpm2zh56Y3uHqOjFO'/*config.reCAPTCHASecret*/).digest('hex'), 'hex');
var key = shaHash.slice(0, 16);
var cipher = crypto.createCipher(algorithm, key, key);
var encryptedToken = cipher.update(text, 'utf8', 'base64') + cipher.final('base64');
var result = encryptedToken.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
return result;
};
Problem is that in .NET I get a token that works (using the right key not included in the post), but in node I get a different token for the same input, and it doesn't works:
.NET - LhPTUELia5vc0X6aDGDtqpsbmB7oqm6vUnzk5BL2auactYXRU5TEUzML8gZ_JubXG07rvJxk1Sb5_a-wqVUGEf_UuO1gGi-WO83yJHOxnjI
node - EGr7drd1JEylwzLGakZ6dpPRSf2nFdpzHOrJlLZlyHYmVRj5obAw7WjPt4W5l0vsywNEqCQ-2_d7qIZOMiOedianfBrQPOBaOmmq44IOB8Q
I got to see that key and input are the same (in .NET and node) right at the moment before encryption, so the problem must(?) be the cipher, any clues?
.NET code for reference:
public static void Main(string[] args)
{
//Your code goes here
Console.WriteLine(EncryptJsonToken(GetJsonToken()));
}
public static string GetJsonToken()
{
//Example: {"session_id": e6e9c56e-a7da-43b8-89fa-8e668cc0b86f,"ts_ms":1421774317718}
string jsonRequest = "{" + string.Format("\"session_id\": {0},\"ts_ms\":{1}", "ab0069ec-3c2c-436c-868b-43c7a10db229", 1446560931992) + "}";
return jsonRequest;
}
public static byte[] getKey()
{
string secretKey = "6LeyNOTTVALIDH2RLNaivqrrpm2zh56Y3uHqOjFO";
SHA1 sha = SHA1.Create();
byte[] dataToHash = Encoding.UTF8.GetBytes(secretKey);
byte[] shaHash = sha.ComputeHash(dataToHash);
byte[] first16OfHash = new byte[16];
Array.Copy(shaHash, first16OfHash, 16);
return first16OfHash;
}
public static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
byte[] encrypted;
// Create an AesManaged object
// with the specified key and IV.
using (AesManaged aesAlg = new AesManaged())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
aesAlg.Padding = PaddingMode.PKCS7;
aesAlg.Mode = CipherMode.ECB;
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
public static string EncryptJsonToken(string jsonToken)
{
byte[] encrypted = EncryptStringToBytes_Aes(jsonToken, getKey(), getKey());
//Base64 encode the encrypted data
//Also applys the URL variant of base64 encoding, unfortunately the HttpServerUtility.UrlTokenEncode(encrypted) seems to truncate the last value from the string so we can't use it?
return Convert.ToBase64String(encrypted, Base64FormattingOptions.None).Replace("=", String.Empty).Replace('+', '-').Replace('/', '_');
}
To debug in .NET: DEMO
You have two problems:
You're using JSON.stringify() to produce a valid JSON string, but the GetJsonToken() method in the C# code doesn't produce a valid JSON string. There are " missing for the UUID and there is a space between the session_id key and its value for some reason. You have to reflect those differences in JavaScript:
var uuidToken = "ab0069ec-3c2c-436c-868b-43c7a10db229";
var time = 1446560931992;
var text = "{\"session_id\": "+uuidToken+",\"ts_ms\":"+time+"}";
There is no such function crypto.createCipher(algorithm, key, key). There is however crypto.createCipheriv(algorithm, key, iv). createCipher(algorithm, password) can be used if one has a password instead of a key which you don't have. Since there is no IV for ECB mode, you can pass in an empty (binary) string as the IV.
Full code:
var crypto = require("crypto");
var algorithm = 'aes-128-ecb';
var uuidToken = "ab0069ec-3c2c-436c-868b-43c7a10db229";
var time = 1446560931992;
var text = "{\"session_id\": "+uuidToken+",\"ts_ms\":"+time+"}";
console.log("Token: " + text);
var shaHash = crypto.createHash('sha1').update('6LeyNOTTVALIDH2RLNaivqrrpm2zh56Y3uHqOjFO').digest();
var key = shaHash.slice(0, 16);
var cipher = crypto.createCipheriv(algorithm, key, "");
var encryptedToken = cipher.update(text, 'utf8', 'base64') + cipher.final('base64');
var result = encryptedToken.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
console.log("result: " + result);
console.log("expected: LhPTUELia5vc0X6aDGDtqpsbmB7oqm6vUnzk5BL2auactYXRU5TEUzML8gZ_JubXG07rvJxk1Sb5_a-wqVUGEf_UuO1gGi-WO83yJHOxnjI");
Output:
Token: {"session_id": ab0069ec-3c2c-436c-868b-43c7a10db229,"ts_ms":1446560931992}
result: LhPTUELia5vc0X6aDGDtqpsbmB7oqm6vUnzk5BL2auactYXRU5TEUzML8gZ_JubXG07rvJxk1Sb5_a-wqVUGEf_UuO1gGi-WO83yJHOxnjI
expected: LhPTUELia5vc0X6aDGDtqpsbmB7oqm6vUnzk5BL2auactYXRU5TEUzML8gZ_JubXG07rvJxk1Sb5_a-wqVUGEf_UuO1gGi-WO83yJHOxnjI
Related
I am trying to decrypt a PDF file using node js,PDF file encrypted by third party using C# .
I am having a hard time because I keep getting this error:
D:\IMP\DevOps Implementation\New folder (2)> node index1.js
internal/crypto/cipher.js:172
const ret = this[kHandle].final();
^
Error: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
at Decipheriv.final (internal/crypto/cipher.js:172:29)
at Object.AESCrypt.decrypt (D:\IMP\DevOps Implementation\New folder (2)\index1.js:12:18)
at D:\IMP\DevOps Implementation\New folder (2)\index1.js:57:24
at FSReqCallback.readFileAfterClose [as oncomplete] (internal/fs/read_file_context.js:63:3) {
library: 'digital envelope routines',
function: 'EVP_DecryptFinal_ex',
reason: 'bad decrypt',
code: 'ERR_OSSL_EVP_BAD_DECRYPT'
}
we are using below code for encryption(C#)
private void FileEncrypt(string inputFile, string outputfile, string password)
{
byte[] salt = GenerateSalt();
byte[] passwords = Encoding.UTF8.GetBytes(password);
RijndaelManaged AES = new RijndaelManaged();
AES.KeySize = 256;
AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwords, salt, 50000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CBC;
AES.Padding = PaddingMode.Zeros;
using (FileStream fsCrypt = new FileStream(inputFile + ".aes", FileMode.Create))
{
fsCrypt.Write(salt, 0, salt.Length);
using (CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateEncryptor(), CryptoStreamMode.Write))
{
using (FileStream fsIn = new FileStream(inputFile, FileMode.Open))
{
byte[] buffer = new byte[1048576];
int read;
while ((read = fsIn.Read(buffer, 0, buffer.Length)) > 0)
{
cs.Write(buffer, 0, read);
}
}
}
}
}
we are using below code for decryption(Node js)
AESCrypt.encrypt = function(cryptkey, iv, cleardata) {
var encipher = crypto.createCipheriv('aes-256-cbc', cryptkey, iv);
return Buffer.concat([
encipher.update(cleardata),
encipher.final()
]);
}
function decrypted(){
var enc;
fs.readFile('./resource/test.pdf', function (err,data) {
if (err) {
return console.log(err);
}
var bufferenc = new Buffer.from(data);
var dec = AESCrypt.decrypt(cryptkey,iv, bufferenc);
console.log(dec);
// var buffer = new Buffer.from(dec);
fs.writeFileSync('./resource/decrypted.pdf',dec);
});
}
Unable to decrypt a pdf file Using 'aes-256-cbc' algorithm in node js
You can try this code to decrypt the pdf data, it's working for me with the C# code:
const fs = require('fs');
const crypto = require("crypto");
function FileDecrypt(inputFile, outputfile, password)
{
// Read the entire file into the buffer.
let buffer = fs.readFileSync(inputFile);
// Read the first eight bytes as a salt.
let salt = buffer.slice(0,8);
let cipherText = buffer.slice(8);
// use key derivation function to get key and iv.
let derivedBytes = crypto.pbkdf2Sync(password, salt, 50000, 48, "sha1");
let key = derivedBytes.slice(0, 32);
let iv = derivedBytes.slice(32);
let cipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
// Switch off auto padding in this context
cipher.setAutoPadding(false);
let decryptedData = Buffer.concat([cipher.update(cipherText), cipher.final()]);
fs.writeFileSync(outputfile, decryptedData);
}
FileDecrypt("encrypted.pdf", "node-decrypted.pdf", "password");
I am encrypting a text in NODEJS and trying decrypt in Java but getting error.
my nodejs code:
var crypto = require('crypto')
, key = 'mykey#91'
, plaintext = 'SS18617710213463'
, cipher = crypto.createCipher('aes-128-ecb', key)
, decipher = crypto.createDecipher('aes-128-ecb', key);
var encryptedPassword = cipher.update(plaintext, 'utf8', 'base64');
encryptedPassword += cipher.final('base64')
var decryptedPassword = decipher.update(encryptedPassword, 'base64', 'utf8');
decryptedPassword += decipher.final('utf8');
console.log('original :', plaintext);
console.log('encrypted :', encryptedPassword);
console.log('decrypted :', decryptedPassword);
but when I am trying to decrypt it, it always throws an error.
public static String decrypt(String encryptedText) {
try {
final String key = "mykey#91";
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] cipherText = Base64.getDecoder().decode(encryptedText.getBytes("UTF8"));
String decryptedString = new String(cipher.doFinal(cipherText),"UTF8");
return decryptedString;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
The error I am getting as below:
java.security.InvalidKeyException: Invalid AES key length: 8 bytes
The reason you are getting Invalid AES key length: 8 bytes invalid AES is related to length of your key and text. You need to make sure that its length in bits is a power of two. If you want to use a String as your encryption key, check its length in bytes and multiply by 8 to find the length in bits. Also most String implementation will require 2 bytes for every character (Java 64bit). Detailed information here: How to solve InvalidKeyException
In this case, the mentioned error will disappear just using a padded or longer key, for example:
static String PLAIN_TEXT = "SS18617710213463";
static String ENCRYPTION_KEY = "mykey#91mykey#91";
However there is another important thing to consider. The Java Implementation has to match the exact algorithms provided by node.js. This is not as easy as it sounds (at least based on my experience). In your case, I would suggest you to use node-forge on node.js side which is easier to match Java implementations:
var forge = require('node-forge');
var plaintext = 'SS18617710213463';
var key = 'mykey#91mykey#91';
var iv = 'AODVNUASDNVVAOVF';
console.log('Plain Text: ' + plaintext);
var cipher = forge.cipher.createCipher('AES-CBC', key);
cipher.start({iv: iv});
cipher.update(forge.util.createBuffer(plaintext));
cipher.finish();
var encrypted = cipher.output;
var encodedB64 = forge.util.encode64(encrypted.data);
console.log("Encoded: " + encodedB64);
var decodedB64 = forge.util.decode64(encodedB64);
encrypted.data = decodedB64;
var decipher = forge.cipher.createDecipher('AES-CBC', key);
decipher.start({iv: iv});
decipher.update(encrypted);
var result = decipher.finish();
console.log("Decoded: " + decipher.output.data);
Running the code above, the output should be:
Plain Text: SS18617710213463
Encoded: HCzZD7uc13fqfM6odWcXf/mdR4aNJfkMDhEbnU+asjE=
Decoded: SS18617710213463
And the compatible Java code that will work on the same way looks like the code below:
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Main {
static String PLAIN_TEXT = "SS18617710213463";
static String ENCRYPTION_KEY = "mykey#91mykey#91";
static String INITIALIZATIO_VECTOR = "AODVNUASDNVVAOVF";
public static void main(String [] args) {
try {
System.out.println("Plain text: " + PLAIN_TEXT);
byte[] encryptedMsg = encrypt(PLAIN_TEXT, ENCRYPTION_KEY);
String base64Encrypted = Base64.getEncoder().encodeToString(encryptedMsg);
System.out.println("Encrypted: "+ base64Encrypted);
byte[] base64Decrypted = Base64.getDecoder().decode(base64Encrypted);
String decryptedMsg = decrypt(base64Decrypted, ENCRYPTION_KEY);
System.out.println("Decrypted: " + decryptedMsg);
} catch (Exception e) {
e.printStackTrace();
}
}
public static byte[] encrypt(String plainText, String encryptionKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/pkcs5padding", "SunJCE");
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(INITIALIZATIO_VECTOR.getBytes("UTF-8")));
return cipher.doFinal(plainText.getBytes("UTF-8"));
}
public static String decrypt(byte[] cipherText, String encryptionKey) throws Exception{
Cipher cipher = Cipher.getInstance("AES/CBC/pkcs5padding", "SunJCE");
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
cipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(INITIALIZATIO_VECTOR.getBytes("UTF-8")));
return new String(cipher.doFinal(cipherText),"UTF-8");
}
}
Which produces:
Plain text: SS18617710213463
Encrypted: HCzZD7uc13fqfM6odWcXf/mdR4aNJfkMDhEbnU+asjE=
Decrypted: SS18617710213463
So, I have a content which needs to be decrypted with private key and padding AES/ECB/PKCS5Padding.
I tried many libraries, and many examples, but none of them works. Now, this is the one where I managed to finish to the last steps, but im not sure if there is another library that can do this for me.
var absolutePath = path.resolve('./private.txt');
var privateKey = fs.readFileSync(absolutePath, "utf8");
var buffer = new Buffer(toDecrypt, "base64");
var decrypted = crypto.privateDecrypt(privateKey, buffer);
return decrypted.toString("utf8");
This one throws me error:
0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag
The second example, slighlty different than the first one, but uses padding (thats what I need, I just wanted to try without it to see if it works):
var stringKey = 'BEGIN RSA PRIVATE KEY-----....';
var cipherText = 'ENCRYPTEDTEXT';
// we compute the sha256 of the key
var hash = crypto.createHash("sha256");
hash.update(stringKey, "utf8");
var sha256key = hash.digest();
var keyBuffer = new Buffer(sha256key);
var cipherBuffer = new Buffer(cipherText, 'hex');
var aesDec = crypto.createDecipheriv("aes-256-ecb", keyBuffer, ''); // always use createDecipheriv when the key is passed as raw bytes
var output = aesDec.update(cipherBuffer, 'binary', 'binary');
var final = aesDec.final();
return output + final;
It crashes on the line var final = aesDec.final() and throws error:
digital envelope routines:EVP_DecryptFinal_ex:wrong final block length
Does anybody has knowledge or expirience on how to do this?
We had similar issue.
We receieved encrypted base 64 string from api and needed to decrypt aes key, and then, with decrypted aes key, we needed to decrypt the payload.
What we have done:
var bytes = new Buffer(input, 'base64'); this is the encrypted data from server
var aes = bytes.slice(offset, offset + AES_SIZE); slice byte array to get aes
`var aesString = aes.toString('binary');` convert it to binary string
Use forge library:
var forge = require('node-forge');
var pki = require('node-forge').pki;
// Grab private key from file
var absolutePath = path.resolve('../private-key.txt');
var privateKey = fs.readFileSync(absolutePath, "utf8");
// Generate private key object
var private_key = pki.privateKeyFromPem(privateKey);
var result;
// Decrypt aes key with private key
try {
result = private_key.decrypt(api.apiSecret, 'RSA-OAEP', {
md: forge.md.sha1.create(),
mgf1: {
md: forge.md.sha1.create()
}
});
} catch (err) {
console.error(err.message);
return;
}
// Build byte array from aes key
var base = new Buffer(result, 'binary');
// Generate initialization vector
var iv = forge.random.getBytesSync(api.content.length);
// Create decipher object with AES/ECB/PKCS5 padding
var decipher = forge.cipher.createDecipher('AES-ECB', forge.util.createBuffer(base));
decipher.start({ iv: iv });
// Add content for decrypting
decipher.update(forge.util.createBuffer(api.content));
var result = decipher.finish();
// Get json data from decipher object
var data = decipher.output.data;
I bought an SSL certificate b/c arvixe does not support self-signed ones. I have a private key in a .pem file which I'd like to use to RSA sign bank transaction parameters. So far, I have not found a way it can be done.
certificate.PrivateKey throws a Keyset not found exception. Using bouncy castle to import the private key (.pem) file works fine, right up to the point where I need to convert to RSACryptoServiceProvider. At that point, DotNetUtilities.ToRSA throws a File Not Found exception. There must be a better way to do this!!!
Here is the relevant snippet from my code:
public string SignRsa(string stringToSign)
{
var encoder = new ASCIIEncoding();
var binData = encoder.GetBytes(stringToSign);
byte[] binSignature;
if (Request.Url.OriginalString.IndexOf("localhost", StringComparison.Ordinal) < 0)
{
var store = new X509Store(StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var certificates = store.Certificates;
var signed = string.Empty;
X509Certificate2 ipCert = certificates.Find(X509FindType.FindBySubjectName, "www.ingyenpiac.com", false).OfType<X509Certificate2>().First();
RSACryptoServiceProvider rsaCsp;
if (ipCert != null)
{
AsymmetricCipherKeyPair keyPair;
using (var reader = System.IO.File.OpenText(Server.MapPath("~/App_Data/private_key.pem"))) // file containing RSA PKCS1 private key
keyPair = (AsymmetricCipherKeyPair)new PemReader(reader).ReadObject();
PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private);
byte[] serializedPrivateBytes = privateKeyInfo.ToAsn1Object().GetDerEncoded();
string serializedPrivate = Convert.ToBase64String(serializedPrivateBytes);
SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public);
byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();
string serializedPublic = Convert.ToBase64String(serializedPublicBytes);
RsaPrivateCrtKeyParameters privateKey = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(serializedPrivate));
RsaKeyParameters publicKey = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(serializedPublic));
var kpp = keyPair.Private as RsaPrivateCrtKeyParameters;
var ppk = DotNetUtilities.ToRSA(kpp); // <==== File not found exception!!!! WTF???
RSACryptoServiceProvider tempRcsp = (RSACryptoServiceProvider)ppk;
RSACryptoServiceProvider rcsp = new RSACryptoServiceProvider(new CspParameters(1, "Microsoft Strong Cryptographic Provider", new Guid().ToString(), new CryptoKeySecurity(), null));
rcsp.ImportCspBlob(tempRcsp.ExportCspBlob(true));
ipCert.PrivateKey = rcsp;
if (ipCert.Verify())
{
rsaCsp = (RSACryptoServiceProvider)ipCert.PrivateKey;
}
else
throw new ApplicationException("Certificate failed to verify.");
}
else
throw new ApplicationException("SignRsa: No certifciate found");
using (var sha = new SHA1CryptoServiceProvider())
{
binSignature = rsaCsp.SignData(binData, sha);
}
if (rsaCsp.VerifyData(binData, new SHA1CryptoServiceProvider(), binSignature))
signed = BitConverter.ToString(binSignature).Replace("-", string.Empty);
store.Close();
return signed;
}
return null;
}
I sure hope someone can help me with this!
With .NET 4.6 this code can get simplified a bit:
public string SignRsa(string stringToSign)
{
var signed = string.Empty;
using (var ipCert = new X509Certificate2(Server.MapPath("~/App_Data/pfxFile.pfx"), "password"))
using (var RSA = ipCert.GetRSAPrivateKey())
{
// Note, if the cert was not RSA, or had no private key, RSA
// will be null. But you didn't check it, so I won't.
var binData = System.Text.Encoding.ASCII.GetBytes(stringToSign);
byte[] binSignature = RSA.SignData(binData, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
// Not sure why you want to re-verify the signature, but OK:
if (RSA.VerifyData(binData, binSignature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1))
signed = BitConverter.ToString(binSignature).Replace("-", string.Empty);
return signed;
}
}
Wow! I really overcomplicated things. No need for bouncy castle, or to do contortions. The answer was quite simple, shown below:
public string SignRsa(string stringToSign)
{
ASCIIEncoding encoder;
var signed = string.Empty;
var ipCert = new X509Certificate2(Server.MapPath("~/App_Data/pfxFile.pfx"), "password");
var RSA = (RSACryptoServiceProvider)ipCert.PrivateKey;
encoder = new ASCIIEncoding();
var binData = encoder.GetBytes(stringToSign);
byte[] binSignature;
using (var sha1 = new SHA1CryptoServiceProvider())
binSignature = RSA.SignData(binData, sha1);
if (RSA.VerifyData(binData, new SHA1CryptoServiceProvider(), binSignature))
signed = BitConverter.ToString(binSignature).Replace("-", string.Empty);
return signed;
}
node js code:
function AES_encrypt(){
var bKey = new Buffer('24Qn9974h50D9DNi', 'utf-8');
var bInput = new Buffer(‘test’, 'utf-8');
console.log(bKey.length);
var cipher = crypto.createCipher('AES-128-ECB',bKey);
//cipher.setAutoPadding(auto_padding=false);
var crypted = cipher.update(bInput,null,'base64');
crypted+=cipher.final('base64');
console.log(crypted);
return crypted;
}
get Result:57b6b7oulw7eO5h7efZ9/w==
java code:
main java:
String data = AES.encryptToBase64("test","24Qn9974h50D9DNi");
AES java:
public static String encryptToBase64(String data, String key){
try {
byte[] valueByte = encrypt(data.getBytes("utf-8"), key.getBytes("utf-8");
return new String(Base64.encode(valueByte));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("encrypt fail!", e);
}
}
public static byte[] encrypt(byte[] data, byte[] key) {
if(key.length!=16){
throw new RuntimeException("Invalid AES key length (must be 16 bytes)");
}
try {
SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec seckey = new SecretKeySpec(enCodeFormat,"AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, seckey);// 初始化
byte[] result = cipher.doFinal(data);
return result; // 加密
} catch (Exception e){
throw new RuntimeException("encrypt fail!", e);
}
}
get Result:wA1JU6VxMaVl8Ck8pBrX8A==
Use crypto.createCipheriv to solve the issue,
http://nodejs.org/api/crypto.html#crypto_crypto_createcipheriv_algorithm_key_iv
You need to pad the string "test" to 16 bytes. I believe Java uses PKCS padding by default (but there are other padding schemes, too).
String data = AES.encryptToBase64("test","24Qn9974h50D9DNi");