I am trying to encrypt a string "1" using key = "secret_key" and text "11869021012". Earlier I had written this in nodejs. now I want to port this to python. but here surprisingly both are giving different outputs.
var crypto = require('crypto');
function getBytes (str) {
let bytes = [], char;
str = encodeURI(str);
while (str.length) {
char = str.slice(0, 1);
str = str.slice(1);
if ('%' !== char) {
bytes.push(char.charCodeAt(0));
} else {
char = str.slice(0, 2);
str = str.slice(2);
bytes.push(parseInt(char, 16));
}
}
return bytes;
};
function getIV (str, bytes){
iv = getBytes(str);
if(!bytes) bytes = 16;
for(let i=iv.length;i<bytes;i++) {
iv.push(0);
}
return Buffer.from(iv);
};
function getKey (pwd){
pwd = Buffer.from(getBytes(pwd), 'utf-8');
let hash = crypto.createHash('sha256');
pwd = hash.update(pwd).digest();
return pwd;
};
function createCipherIV (algorithm, input_key, iv_input, text){
let iv = getIV(iv_input);
let key = getKey(input_key);
let cipher = crypto.createCipheriv(algorithm, key, iv);
let encrypted = cipher.update(text)
encrypted += cipher.final('base64');
return encrypted;
}
output = createCipherIV('aes256', 'secret_key', '11869021012', '1')
console.log(output)
This produces the output:
s6LMaE/YRT6y8vr2SehLKw==
python code:
# AES 256 encryption/decryption using pycrypto library
import base64
import hashlib
from Crypto.Cipher import AES
from Crypto import Random
BLOCK_SIZE = 16
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]
password = "secret_key"
def encrypt(raw, password):
private_key = hashlib.sha256(bytearray(password, "utf-8")).digest()
raw = pad(raw)
iv = b'11869021012\x00\x00\x00\x00\x00'
cleartext = bytearray(raw, 'utf-8')
cipher = AES.new(private_key, AES.MODE_CBC, iv)
return base64.b64encode(iv + cipher.encrypt(cleartext))
# First let us encrypt secret message
encrypted = encrypt("1", password)
print(encrypted)
This produces the output:
MTE4NjkwMjEwMTIAAAAAALOizGhP2EU+svL69knoSys=
I have used aes256 algorithm here for encrypting message.
Clearly they are very close, but node seems to be padding the output with some extra bytes. Any ideas how I can get the two to interoperate?
First, in a secure crypto system, you should expect the output to be different every time you encrypt, even using the same code. That fact that yours doesn't indicates it's an insecure cipher. Typically this is done by adding a random IV.
Your IV is "11869021012", which is horrible (because it's not random, and not even 16 bytes), but it does seem you're using it the same way in both, so that's fine.
Your password is the SHA-256 of a string, which is a horrible way to create a key, but still, you seem to be doing it the same way in both cases, so that's fine.
Your problem is that the Python code emits the IV followed by the cipher text. Your JS code does not emit the IV; it only emits the cipher text. So you probably meant this in the Python:
return base64.b64encode(cipher.encrypt(cleartext))
Or you need to rework the JavaScript to glue together the IV and the cipher text before Base64 encoding.
Related
I have an implementation of password based encryption in Java. It formerly used PBEWithMD5AndDES and was later changed to use PBEWithHmacSHA256AndAES_256. The significant code looks like this:
//String cipherAlgorithm = "PBEWithMD5AndDES";
String cipherAlgorithm = "PBEWithHmacSHA256AndAES_256";
PBEKeySpec pbeKeySpec = new PBEKeySpec(passPhrase, salt, iterationCount);
SecretKey secretKey = SecretKeyFactory.getInstance(cipherAlgorithm).generateSecret(pbeKeySpec);
AlgorithmParameterSpec paramSpec = iv == null ?
new PBEParameterSpec(data.salt, iterationCount) :
new PBEParameterSpec(data.salt, iterationCount, new IvParameterSpec(iv));
cipher = Cipher.getInstance(cipherAlgorithm);
if (encrypt) {
cipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec);
} else {
cipher.init(Cipher.DECRYPT_MODE, secretKey, paramSpec);
}
...
byte[] enc = cipher.doFinal(utf8);
I have also an implementation with openSSL (and with Windows crypt functions) for the old algorithm. Now I try to extend this to the new algorithm.
The old code using the openSSL implementation looks like this:
unsigned char iv[8];
unsigned char key[8];
memset(iv, '\0', sizeof(iv));
memset(key, '\0', sizeof(key));
int rc = EVP_BytesToKey(EVP_des_cbc(), EVP_md5(),
salt,
apasswd, alen, iterationCount,
key, iv);
if (rc != sizeof(key))
throw ...
EVP_CIPHER_CTX *ectx;
ectx = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(ectx);
if (!EVP_CipherInit_ex(ectx, EVP_des_cbc(), NULL, key, iv, encrypt ? 1 : 0))
throw ...
if (!EVP_CipherUpdate(ectx, ebuf, &ebuflen, (unsigned char *)abuf, abuflen))
throw ...
if (ebuflen > (int)abufsize)
throw ...
...
if (!EVP_CipherFinal_ex(ectx, ebuf, &ebuflen))
throw ...
...
EVP_CIPHER_CTX_free(ectx);
I was not successful to get this working. I tried already the following:
Replace EVP_des_cbc() with EVP_aes_256_cbc() and EVP_md5() : EVP_sha256()
Use PKCS5_PBKDF2_HMAC instead of EVP_BytesToKey (with iv and key sizes adapted to 16 and32)
PKCS5_PBKDF2_HMAC(apasswd, alen, salt, sizeof(salt),
iterationCount, EVP_sha256(),
sizeof(key), key);
But the decryption of data encrypted with the Java implementation fails (EVP_CipherFinal_ex returns an error, so the key seems wrong).
Unfortunately I did not find any information about how PBEWithHmacSHA256AndAES_256 is implemented in Java.
Could anyone point me to more information about this or has anyone successfully implemented similar things (with openSSL or Windows API) and have some hints about this?
I finally got it working, so I can answer the question myself now.
For openSSL, the key can be generated from the passphrase with:
int rc = PKCS5_PBKDF2_HMAC((const char *)passPhrase, pLen, salt,
sizeof(salt), iterationCount, EVP_sha256(),
sizeof(key), key);
For Windows, the key can be generated with:
NTSTATUS status;
BYTE key[32];
BCRYPT_ALG_HANDLE handle;
status = BCryptOpenAlgorithmProvider(&handle,
BCRYPT_SHA256_ALGORITHM, NULL,
BCRYPT_ALG_HANDLE_HMAC_FLAG);
status = BCryptDeriveKeyPBKDF2(handle, (BYTE*)passPhrase, sizeof(passPhrase),
salt, sizeof(salt), iterationCount, key, 32, 0);
I have implemented Secure Web hook features for my Spring Boot application(Java).
For that I have created "Subscription" with below JSON.
String subscriptionMessageTemplate = "{\"changeType\": \"created,updated\",\"notificationUrl\": \"%s/notify/messages\",\"lifecycleNotificationUrl\":\"%s/notify/messages/lifeCycle\", \"resource\": \"/teams/{id}/channels/19:{id}#thread.skype/messages\", \"clientState\": \"secretClientValue\",\"includeResourceData\": true,\"encryptionCertificate\": \"%s\",\"expirationDateTime\":\"%s\",\"encryptionCertificateId\": \"1\"}";
I have used ngrok for public IP:
When I am sending message from the team, I am getting below response.
{
"value": [
{
"subscriptionId": "76222963-cc7b-42d2-882d-8aaa69cb2ba3",
"changeType": "created",
// Other properties typical in a resource change notification
"resource": "teams('d29828b8-c04d-4e2a-b2f6-07da6982f0f0')/channels('19:f127a8c55ad949d1a238464d22f0f99e#thread.skype')/messages('1565045424600')/replies('1565047490246')",
"resourceData": {
"id": "1565293727947",
"#odata.type": "#Microsoft.Graph.ChatMessage",
"#odata.id": "teams('88cbc8fc-164b-44f0-b6a6-b59b4a1559d3')/channels('19:8d9da062ec7647d4bb1976126e788b47#thread.tacv2')/messages('1565293727947')/replies('1565293727947')"
},
"encryptedContent": {
"data": "{encrypted data that produces a full resource}",
"dataSignature": "<HMAC-SHA256 hash>",
"dataKey": "{encrypted symmetric key from Microsoft Graph}",
"encryptionCertificateId": "MySelfSignedCert/DDC9651A-D7BC-4D74-86BC-A8923584B0AB",
"encryptionCertificateThumbprint": "07293748CC064953A3052FB978C735FB89E61C3D"
}
}
],
"validationTokens": [
"eyJ0eXAiOiJKV1QiLCJhbGciOiJSU..."
]
}
Now I want to decrypt data, Can any one help me to how to decrypt data in Java?
For certificate generation, I have used my custom method:
strong text.
private void generateSelfSignedX509Certificate(KeyPair keyPair) throws Exception {
// yesterday
Date validityBeginDate = new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000);
// in 2 years
Date validityEndDate = new Date(System.currentTimeMillis() + 2 * 365 * 24 * 60 * 60 * 1000);
// GENERATE THE X509 CERTIFICATE
X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
X500Principal dnName = new X500Principal("CN=John Doe");
certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
certGen.setSubjectDN(dnName);
certGen.setIssuerDN(dnName); // use the same
certGen.setNotBefore(validityBeginDate);
certGen.setNotAfter(validityEndDate);
certGen.setPublicKey(keyPair.getPublic());
certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
this.certificate = certGen.generate(keyPair.getPrivate(), "BC");
}
I had to struggle my way with it in Python 3.6, so for the sake of future python-readers, here is my skeleton of working code that do the above (using pycryptodome==3.9.7):
import json
import hashlib, hmac
from base64 import b64decode, b64encode
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Util.Padding import unpad
from Crypto.PublicKey import RSA
from Crypto.Cipher import AES
...
...
encrypted_symmetric_key: bytes = b64decode(encrypted_symmetric_key.encode())
encrypted_payload = b64decode(encrypted_payload.encode())
rsa_key = RSA.import_key(private_key, passphrase=private_key_passphrase)
cipher = PKCS1_OAEP.new(rsa_key)
# if length of encrypted_symmetric_key is > 128 we will get ciphertext with incorrect length, to avoid that lets split and decrypt in chunks
default_length = 128
length = len(encrypted_symmetric_key)
if length < default_length:
decrypt_byte = cipher.decrypt(encrypted_symmetric_key)
else:
offset = 0
res = []
while length - offset > 0:
if length - offset > default_length:
res.append(cipher.decrypt(encrypted_symmetric_key[offset:offset + default_length]))
else:
res.append(cipher.decrypt(encrypted_symmetric_key[offset:]))
offset += default_length
decrypt_byte = b''.join(res)
decrypted_symmetric_key = decrypt_byte
hash_state_machine = hmac.new(decrypted_symmetric_key, msg=encrypted_payload, digestmod=hashlib.sha256)
raw_signature = hash_state_machine.digest()
actual_signature_bytes: bytes = b64encode(raw_signature)
actual_signature: str = actual_signature_bytes.decode()
if actual_signature != expected_data_signature:
raise Exception("data hash is not as expected")
iv = decrypted_symmetric_key[:16]
cipher2 = AES.new(decrypted_symmetric_key, AES.MODE_CBC, iv=iv)
message_str = unpad(cipher2.decrypt(encrypted_payload), block_size=16).decode()
message_dict = json.loads(message_str)
I updated the documentation to include Java samples. I'll also include the samples here for reference but future readers should refer to the documentation which is where the samples will be kept up to date.
Keep in mind these samples operate under the assumption that you have a local Java Key Store (JKS) that the certificate is pulled from.
Decrypt the AES key:
String storename = ""; //name/path of the jks store
String storepass = ""; //password used to open the jks store
String alias = ""; //alias of the certificate when store in the jks store, should be passed as encryptionCertificateId when subscribing and retrieved from the notification
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(storename), storepass.toCharArray());
Key asymmetricKey = ks.getKey(alias, storepass.toCharArray());
byte[] encryptedSymetricKey = Base64.decodeBase64("<value from dataKey property>");
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");
cipher.init(Cipher.DECRYPT_MODE, asymmetricKey);
byte[] decryptedSymmetricKey = cipher.doFinal(encryptedSymetricKey);
Verify the data signature
byte[] decryptedSymmetricKey = "<the aes key decrypted in the previous step>";
byte[] decodedEncryptedData = Base64.decodeBase64("data property from encryptedContent object");
Mac mac = Mac.getInstance("HMACSHA256");
SecretKey skey = new SecretKeySpec(decryptedSymmetricKey, "HMACSHA256");
mac.init(skey);
byte[] hashedData = mac.doFinal(decodedEncryptedData);
String encodedHashedData = new String(Base64.encodeBase64(hashedData));
if (comparisonSignature.equals(encodedHashedData);)
{
// Continue with decryption of the encryptedPayload.
}
else
{
// Do not attempt to decrypt encryptedPayload. Assume notification payload has been tampered with and investigate.
}
Decrypt the data content
SecretKey skey = new SecretKeySpec(decryptedSymmetricKey, "AES");
IvParameterSpec ivspec = new IvParameterSpec(Arrays.copyOf(decryptedSymmetricKey, 16));
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, skey, ivspec);
String decryptedResourceData = new String(cipher.doFinal(Base64.decodeBase64(encryptedData)));
optimized the previous answer a bit excluding the hash validations
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import serialization
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from config.config import Config
import base64
import json
config = Config('config.yaml')
notification_response = json.loads(msg)
base64encodedKey = notification_response['value'][0]['encryptedContent']['dataKey']
asymetricPrivateKey = bytes(config.subscription.PRIVATE_KEY,encoding='utf-8')
decodedKey = base64.b64decode(base64encodedKey)
private_key = serialization.load_pem_private_key(
asymetricPrivateKey,
password=None,
backend=default_backend()
)
decryptedSymetricKey = private_key.decrypt(
decodedKey,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA1(),
label=None
)
)
encrypted_payload = base64.b64decode(notification_response['value'][0]['encryptedContent']['data'].encode())
iv = decryptedSymetricKey[:16]
cipher2 = AES.new(decryptedSymetricKey, AES.MODE_CBC, iv=iv)
message_str = unpad(cipher2.decrypt(encrypted_payload), block_size=16).decode()
message_dict = json.loads(message_str)
On web, I'm using CryptoJS for decrypto JS:
CryptoJS.AES.decrypt(inputBase64, key).toString(CryptoJS.enc.Utf8);
Example:
input: "tzfwnxVwE/qNoaWRRfqLp11ZyhB4UtKO+0/Lvv5B7eE="
key: "20190225165436_15230006321670000_15510884759030000"
On flutter I can't find any library to decrypt with a key of any length.
I know "For AES, NIST selected three members of the Rijndael family, each with a block size of 128 bits, but three different key lengths: 128, 192 and 256 bits.
"
But I don't know how to convert any length key to 128 bit format?
import 'dart:convert';
import 'dart:math';
import 'dart:typed_data';
import 'package:crypto/crypto.dart';
import 'package:tuple/tuple.dart';
import 'package:encrypt/encrypt.dart' as encrypt;
String encryptAESCryptoJS(String plainText, String passphrase) {
try {
final salt = genRandomWithNonZero(8);
var keyndIV = deriveKeyAndIV(passphrase, salt);
final key = encrypt.Key(keyndIV.item1);
final iv = encrypt.IV(keyndIV.item2);
final encrypter = encrypt.Encrypter(
encrypt.AES(key, mode: encrypt.AESMode.cbc, padding: "PKCS7"));
final encrypted = encrypter.encrypt(plainText, iv: iv);
Uint8List encryptedBytesWithSalt = Uint8List.fromList(
createUint8ListFromString("Salted__") + salt + encrypted.bytes);
return base64.encode(encryptedBytesWithSalt);
} catch (error) {
throw error;
}
}
String decryptAESCryptoJS(String encrypted, String passphrase) {
try {
Uint8List encryptedBytesWithSalt = base64.decode(encrypted);
Uint8List encryptedBytes =
encryptedBytesWithSalt.sublist(16, encryptedBytesWithSalt.length);
final salt = encryptedBytesWithSalt.sublist(8, 16);
var keyndIV = deriveKeyAndIV(passphrase, salt);
final key = encrypt.Key(keyndIV.item1);
final iv = encrypt.IV(keyndIV.item2);
final encrypter = encrypt.Encrypter(
encrypt.AES(key, mode: encrypt.AESMode.cbc, padding: "PKCS7"));
final decrypted =
encrypter.decrypt64(base64.encode(encryptedBytes), iv: iv);
return decrypted;
} catch (error) {
throw error;
}
}
Tuple2<Uint8List, Uint8List> deriveKeyAndIV(String passphrase, Uint8List salt) {
var password = createUint8ListFromString(passphrase);
Uint8List concatenatedHashes = Uint8List(0);
Uint8List currentHash = Uint8List(0);
bool enoughBytesForKey = false;
Uint8List preHash = Uint8List(0);
while (!enoughBytesForKey) {
int preHashLength = currentHash.length + password.length + salt.length;
if (currentHash.length > 0)
preHash = Uint8List.fromList(
currentHash + password + salt);
else
preHash = Uint8List.fromList(
password + salt);
currentHash = md5.convert(preHash).bytes;
concatenatedHashes = Uint8List.fromList(concatenatedHashes + currentHash);
if (concatenatedHashes.length >= 48) enoughBytesForKey = true;
}
var keyBtyes = concatenatedHashes.sublist(0, 32);
var ivBtyes = concatenatedHashes.sublist(32, 48);
return new Tuple2(keyBtyes, ivBtyes);
}
Uint8List createUint8ListFromString(String s) {
var ret = new Uint8List(s.length);
for (var i = 0; i < s.length; i++) {
ret[i] = s.codeUnitAt(i);
}
return ret;
}
Uint8List genRandomWithNonZero(int seedLength) {
final random = Random.secure();
const int randomMax = 245;
final Uint8List uint8list = Uint8List(seedLength);
for (int i=0; i < seedLength; i++) {
uint8list[i] = random.nextInt(randomMax)+1;
}
return uint8list;
}
Usage
import 'package:app/utils/cryptojs_aes_encryption_helper.dart';
String plainText = 'PlainText is Me';
var encrypted = encryptAESCryptoJS(plainText, "password");
var decrypted = decryptAESCryptoJS(encrypted, "password");
When you pass CryptoJS a string as the key it treats it as a passphrase and generates the key from it using a key derivation function - in this case PBKDF2. It generates a 256 bit key and a 128 bit initialization vector (IV). It then uses those for the encryption/decryption. You also need to find out what chaining method CryptoJS uses (probably cipher block chaining (CBC)) and what padding method it uses (to make sure that the plain text is a round number of 128 bit blocks - probably PKCS#7).
CryptoJS has this "works out of the box" mode, but it isn't particularly clear what it's doing under the hood - you'd need to read the source code or scour the documentation.
When trying to inter-operate between two systems/languages it's best if you remain in charge of things, rather than letting one end make arbitrary decisions. That way you can make sure that you have the settings the same at each end.
So, you might choose to:
Use PBKDF2 to generate a 128 bit key and 128 bit IV from the string
passphrase - with, say, 9999 rounds
Use PKCS#7 padding
Use AES in CBC mode
The pointycastle package supports all the above in Dart. It looks like CryptoJS supports all of those too.
Start with a passphrase and make sure you can generate the same key and IV in JS and Dart. Then move onto creating the ciphers.
Remember, too, never to encrypt two messages with the same key/IV pair. Use a message sequence number, for example, to slightly change the IV for each message.
Sample encrypt using nodejs script:
var key = CryptoJS.PBKDF2("123456", "123456", {
keySize: 256 / 32
});
var iv = CryptoJS.PBKDF2("123456", "123456", {
keySize: 128 / 32
});
var encrypted = CryptoJS.AES.encrypt('my message', key, { iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}).toString();
decript using dart
import 'package:encrypt/encrypt.dart' as aes;
import 'package:crypto/crypto.dart';
import 'package:hex/hex.dart';
import 'package:password_hash/pbkdf2.dart';
void main(List<String> arguments) {
String encrypted = 'HbsmGAigiIWmU3MNZAf8+w==';
final generator = PBKDF2(hashAlgorithm: sha1);
final key = aes.Key.fromBase16(HEX.encode(generator.generateKey("123456", "123456", 1, 32)));
final iv = aes.IV.fromBase16(HEX.encode(generator.generateKey("123456", "123456", 1, 16)));
final encrypter = aes.Encrypter(aes.AES(key, mode: aes.AESMode.cbc, padding: 'PKCS7'));
final decrypted = encrypter.decrypt64(encrypted, iv:iv);
print(decrypted);
}
I am attempting to use DES to encrypt / decrypt. However, the decrypt is not working. I keep getting the error: Cannot read property 'charCodeAt' of null
The decryption is from http://www.tero.co.uk/des/
I am using this to encode:
var decodedKey = decodeBase64(key);
var em = urlEncode(encrypt(decodedKey, value));
and then I am attempting to use this function to decrypt:
var emD = urlDecode(decrypt(decodedKey, em))
with
function encrypt(key, message) {
var ciphertext = des(key, message, 1, 0, null, 1);
var encodedCiphertext = encodeBase64(ciphertext);
return encodedCiphertext;
}
function decrypt(key,message) {
var ciphertext = des(key, message, 0, 1, null,1);
var plainText = decodeBase64(ciphertext);
return plainText;
};
With:
urlEncode(encrypt(decodedKey, value));
you first encrypt then url-encode. When you need to decrypt, you need to first url-decode then decrypt - something like:
decrypt(decodedKey, urlDecode(em));
as opposed to decrypt then url-decode as you try with this statement:
urlDecode(decrypt(decodedKey, em));
Also, please note that DES is considered insecure and should be avoided. Use a secure cipher like AES.
I want to generate a 256bit password for my AES encryption. When I check the password after the encryption it is different from my initial password. What am I doing wrong? Or is there some security mechanism I am not aware of?
My code:
password=Generate_key();
var encrypted = CryptoJS.AES.encrypt("Message", password);
//Those two should be the same
document.write(password+"<br>");
document.write(encrypted.key);
function Generate_key() {
var key = "";
var hex = "0123456789abcdef";
for (i = 0; i < 64; i++) {
key += hex.charAt(Math.floor(Math.random() * 16));
//Initially this was charAt(chance.integer({min: 0, max: 15}));
}
return key;
}
The output is i.e.
0b05308c9a00f07044416bad7a51bacd282fc5c0c999551a4ff15c302b268b20
4df875993770411044fb35953166ee7833c32ca0741e9fec091dfa10138039e8
Is this normal or am I doing something wrong here?
Thanks for help!
Encryption is done with a key, which is a set of binary bits, not a password, which implies a human-readable string.
To go from a password to a key, one can use a Password Based Key Derivation Function, such as PBKDF2. Crypto-JS already has a PBKDF2 function built-in, i.e.
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/pbkdf2.js"></script>
<script>
var salt = CryptoJS.lib.WordArray.random(128/8);
var key128Bits = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 128/32 });
var key256Bits = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 256/32 });
var key512Bits = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 512/32 });
var key512Bits1000Iterations = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 512/32, iterations: 1000 });
</script>
In general, use as high an iteration count as you can get away with.
Salt should be a random value, as in the example above; you'll need, of course, to store that value along with the iteration count in order to get the same key given the same passphrase.
I found the solution. You can define your own key using
var encrypted = CryptoJS.AES.encrypt("Message", key, { iv: iv });
So my source code is:
key=CryptoJS.enc.Hex.parse(Generate_key());
iv=CryptoJS.enc.Hex.parse(Generate_key());
var encrypted = CryptoJS.AES.encrypt("Message", key, { iv: iv });