I know AES 256 CBC with buffer to give different encrypt but its length 66. here is my code
const crypto = require('crypto');
const ENCRYPTION_KEY = 'Must256bytes(32characters)secret';
const IV_LENGTH = 16;
function encrypt(text) {
let iv = crypto.randomBytes(IV_LENGTH);
let cipher = crypto.createCipheriv('aes-256-cbc', new Buffer(ENCRYPTION_KEY), iv);
let encrypted = cipher.update(text.toString());
encrypted = Buffer.concat([encrypted, cipher.final()]);
return iv.toString('hex') + 'XX' + encrypted.toString('hex');
}
function decrypt(text) {
let textParts = text.split('XX');
let iv = new Buffer(textParts.shift(), 'hex');
let encryptedText = new Buffer(textParts.join('XX'), 'hex');
let decipher = crypto.createDecipheriv('aes-256-cbc', new Buffer(ENCRYPTION_KEY), iv);
let decrypted = decipher.update(encryptedText);
try{
decrypted = Buffer.concat([decrypted, decipher.final()]);
return decrypted.toString();
}catch(Err){
return 'NULL';
}
}
Problem is encryption data length is 66 even for text is 1
So is there any encryption and decryption method should give different encryption data at every time with less than 10 characters for text is 1(according to my example)
Thank you
Maarten covers most of the major points that I wanted to make, so this is just some elaboration and an example of it in Node.
The changes from your code are:
As Maarten notes, it is quite dangerous for CTR mode to duplicate a Key+Nonce pair. If someone does that, they can learn the XOR of the two original messages. With that, they have a good chance of decrypting both messages. For example, if you duplicated your key+nonce on two messages and the attacker used that to discover that their XOR was 3 and knew that the encrypted text was a capital letter, they would know that the two messages had to be one of these:
[('A', 'B'), ('D', 'G'), ('E', 'F'), ('H', 'K'), ('I', 'J'), ('L', 'O'),
('M', 'N'), ('P', 'S'), ('Q', 'R'), ('T', 'W'), ('U', 'V')]
This kind of information is devastating for structured data like human language or computer protocols. It can very quickly be used to decrypt the whole message. Key+nonce reuse is how WEP was broken. (When you do this by hand, it's basically identical to solving a cryptogram puzzle you'd find in the newspaper.) It is less powerful the more random the encrypted data is, and the less context it provides.
With a random 5-byte nonce, there is a 50% likelihood of a collision after about 1.3M encryptions. With a random 8-byte nonce, there is a 50% likelihood of a collision after about 5.3B encryptions. sqrt(pi/2 * 2^bits)
In cryptographic terms, this is a completely broken. It may or may not be sufficient for your purposes. To do it correctly (which I do not do below), as Maarten notes, you should keep track of your counter and increment it for every encryption rather than using a random one. After 2^40 encryptions (~1T), you change your key.
Assuming that leaking information about two messages per million is acceptable, this is how you would implement that.
const crypto = require('crypto');
const ENCRYPTION_KEY = 'Must256bytes(32characters)secret';
const SALT = 'somethingrandom';
const IV_LENGTH = 16;
const NONCE_LENGTH = 5; // Gives us 8-character Base64 output. The higher this number, the better
function encrypt(key, text) {
let nonce = crypto.randomBytes(NONCE_LENGTH);
let iv = Buffer.alloc(IV_LENGTH)
nonce.copy(iv)
let cipher = crypto.createCipheriv('aes-256-ctr', key, iv);
let encrypted = cipher.update(text.toString());
message = Buffer.concat([nonce, encrypted, cipher.final()]);
return message.toString('base64')
}
function decrypt(key, text) {
let message = Buffer.from(text, 'base64')
let iv = Buffer.alloc(IV_LENGTH)
message.copy(iv, 0, 0, NONCE_LENGTH)
let encryptedText = message.slice(NONCE_LENGTH)
let decipher = crypto.createDecipheriv('aes-256-ctr', key, iv);
let decrypted = decipher.update(encryptedText);
try{
decrypted = Buffer.concat([decrypted, decipher.final()]);
return decrypted.toString();
}catch(Err){
return 'NULL';
}
}
// You could do this one time and record the result. Or you could just
// generate a random 32-byte key and record that. But you should never
// pass an ASCII string to the encryption function.
let key = crypto.pbkdf2Sync(ENCRYPTION_KEY, SALT, 10000, 32, 'sha512')
let encrypted = encrypt(key, "X")
console.log(encrypted + " : " + encrypted.length)
let decrypted = decrypt(key, encrypted)
console.log(decrypted)