簡體   English   中英

如何在輸入錯誤密碼時顯示錯誤 NodeJS 加密 - createDecipheriv 和 pbkdf2

[英]how to show error when wrong password is given NodeJS crypto - createDecipheriv and pbkdf2

創建了一個加密文本的簡單應用程序,但是當給出錯誤的密碼或鹽時,我如何顯示錯誤。 repli上托管它。 但是當我輸入錯誤的密碼或鹽時,它只會解密它。 crypto.createDecipheriv()在加密中沒有回調或函數

const app = {
  encrypt(text, password, salt) {
    password = password.repeat(32).substr(0, 32);
    salt = salt.repeat(16).substr(0, 16);
    crypto.pbkdf2(password, salt, 10, 16, 'sha512', (err, key) => {
      if (err) {
        console.log(err); 
      } else {
        key = key.toString('hex');
        const cipher = crypto.createCipheriv('aes-256-gcm', key, salt);
        let encrypted = cipher.update(text, 'utf8', 'hex');
        console.log(encrypted);
      }
    });
  },
  decrypt(text, password, salt) {
    password = password.repeat(32).substr(0, 32);
    salt = salt.repeat(16).substr(0, 16);
    crypto.pbkdf2(password, salt, 10, 16, 'sha512', (err, key) => {
      if (err) {
        console.log(err); 
      } else {
        key = key.toString('hex');
        const cipher = crypto.createDecipheriv('aes-256-gcm', key, salt);
        let decrypted = cipher.update(text, 'hex', 'utf8');
        console.log(decrypted);
      }
    });
  }
}

const message = 'Hello World';
app.encrypt(message, 'password', 'salt');

const cipherText = 'a0a4e0ad97133494856502';
app.decrypt(cipherText, 'password', 'salt');

GCM在加密時會生成一個認證標簽(默認為16字節),用於解密時的認證。
一些庫(例如Java)在加密期間隱式連接密文和標簽(ciphertext|tag),並在解密期間隱式分離兩者(這並不重要,因為標簽不是秘密的)。
另一方面,NodeJS 的加密模塊獨立處理密文和標簽,因此必須明確考慮標簽。 它可以在使用getAuthTag()加密期間確定,並且必須在使用setAuthTag()解密期間設置。 發布的代碼中都缺少兩者。
同樣缺少的是在加密時生成標簽並在解密時執行身份驗證的final()調用。
為了在此示例中將標簽傳遞給解密,以下修復在加密期間將標簽與密文連接起來,並在解密期間將其分開(遵循 Java 模式)。

如果這些問題得到解決,則解密適用於正確的數據,並為不正確的數據顯示相應的消息: Error: Unsupported state or unable to authenticate data.

修復代碼,詳情見評論:

const crypto = require('crypto');

const app = {
  encrypt(text, password, salt) {
    password = password.repeat(32).substr(0, 32);
    salt = salt.repeat(16).substr(0, 16);
    crypto.pbkdf2(password, salt, 10, 16, 'sha512', (err, key) => {
      if (err) {
        console.log(err); 
      } else {
        key = key.toString('hex');
        const cipher = crypto.createCipheriv('aes-256-gcm', key, salt);
        let encrypted = cipher.update(text, 'utf8', 'hex') + cipher.final('hex'); // Fix 1a: call final(): create tag
        let tag = cipher.getAuthTag(); // Fix 2a: get tag 
        console.log(encrypted + tag.toString('hex')); // Fix 3a: concat ciphertext and tag 
      }
    });
  },
  decrypt(text, password, salt) {
    var tag = Buffer.from(text.substr(-32, 32), 'hex'); // Fix 3b: Separate ciphertext and tag
    var ciphertext = text.substr(0, text.length - 32);
    password = password.repeat(32).substr(0, 32);
    salt = salt.repeat(16).substr(0, 16);
    crypto.pbkdf2(password, salt, 10, 16, 'sha512', (err, key) => {
      if (err) {
        console.log(err); 
      } else {
        key = key.toString('hex');
        const cipher = crypto.createDecipheriv('aes-256-gcm', key, salt);
        cipher.setAuthTag(tag); // Fix 2b: set  tag
        try {
          let decrypted = cipher.update(ciphertext, 'hex', 'utf8') + cipher.final('utf8'); // Fix 1b: call final(): authenticate
          console.log(decrypted);
        } catch (e) {
          console.log("Authentication failed!");
        }
      }
    });
  }
}

const message = 'Hello World';
app.encrypt(message, 'password', 'salt');

const cipherText = 'a0a4e0ad971334948565023568ae285d45b9cefc80abe3afcf9155';
app.decrypt(cipherText, 'password', 'salt');
app.decrypt(cipherText, 'password123', 'salt');

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM