无法在 createCipheriv、Nodejs、Crypto lib 中使用 ScryptSync 密钥

问题描述

我是与编码相关的主题的新手,并且无法将我的 scryptsync 密钥转换为 createCipheriv(集成到 Nodejs 的加密库)可以在 iv 参数中使用的东西。

const algorithm = 'aes-256-gcm';
var text = 'default'
var encrypted = secret;

class Auth
{

SignUp(pass)
{
    console.log(pass);

    var pair = ec.genKeyPair(); 

    text = pair.getPrivate.toString('hex');

    var key = crypto.scryptSync(pass,'baethrowssalt',32);

    console.log(`The key is:${key}`); //this is not a string

    key=key.toString('hex');

    var cipher = crypto.createCipheriv(algorithm,key);  

    var encrypted = cipher.update(text,'hex','hex') + cipher.final('hex');

    fs.writeFileSync(file,encrypted);

    return alert(`Close and reopen your app to integrate your wallet securely`);
}

如上所示,我尝试将 scryptSync 返回值转换为字符串十六进制,以便 createCipheriv 愿意使用它,但出现以下错误

pass is passrig
passrig
The key is:�→A�r;yR�����▲�h�8��f�����v�A�,TypeError [ERR_INVALID_ARG_TYPE]: The "iv" argument must be of type string or an instance of Buffer,TypedArray,or DataView. Received undefined
    at Cipheriv.createCipherWithIV (internal/crypto/cipher.js:120:29)
    at new Cipheriv (internal/crypto/cipher.js:227:22)
    at Object.createCipheriv (crypto.js:117:10)

所以我的问题包含两个部分:如何将 scryptSync 与 createCipheriv 一起使用?为了帮助我理解,您的解决方案背后的原因是什么?

解决方法

我创建了一个示例,该示例使用算法 aes-256-gcm 加密一些数据,并使用 crypto.scryptSync 从密码中导出密钥。

步骤如下:

  1. 使用 crypto.scryptSync 从我们的密码中导出我们的 key
  2. 使用 crypto.randomBytes 创建一个 IV。
  3. 使用我们的密钥和 iv 使用我们的加密功能加密明文。
  4. 通过使用我们的解密函数解密来测试我们的加密数据。

这段代码如下:

const crypto = require("crypto");
const Algorithm = "aes-256-gcm";

function encrypt(plainText,key,iv) {
    const cipher = crypto.createCipheriv(Algorithm,iv);
    return { encrypted: Buffer.concat([cipher.update(plainText),cipher.final()]),authTag: cipher.getAuthTag() }
}

function decrypt(encrypted,iv,authTag) {
    const decipher = crypto.createDecipheriv(Algorithm,iv).setAuthTag(authTag);
    return Buffer.concat([decipher.update(encrypted),decipher.final()]);
}

const password = "Speak Friend and Enter";
const plainText = "There is nothing either good or bad but thinking makes it so.";

const salt = crypto.randomBytes(32);

// Create an encryption key from our password,ensuring it is 32 bytes long - AES-256 needs a 256 bit (32 byte) key 
const KEY = crypto.scryptSync(password,salt,32);
const IV = crypto.randomBytes(16);

console.log("Key (derived from password,hex):",KEY.toString("hex"));
console.log("IV (hex):",IV.toString("hex"));
console.log("Plaintext:",plainText);
const { encrypted,authTag } = encrypt(plainText,KEY,IV);
console.log("Encrypted (hex):",encrypted.toString("hex"));
const decrypted = decrypt(encrypted,IV,authTag)
console.log("Decrypted:",decrypted.toString("utf-8"));