Node.js 节点加密:用于验证的加密/解密令牌

Node.js 节点加密:用于验证的加密/解密令牌,node.js,encryption,cryptography,token,Node.js,Encryption,Cryptography,Token,我想对令牌进行加密和解密,以便在不访问数据库的情况下确定它是否是有效令牌 我的代码用于看起来完全不同的令牌,但如果我只更改一个字母,则返回结果,不会抛出错误,因此看起来令牌是有效的 这是我的代码加上手动更改字母: var crypto = require("crypto"); var cryptSecret = "a!=ksljdk34ajSDkl"; var token = "1d3889647173d415e24195ce5cafc36c1edcc053"; function _enco

我想对令牌进行加密和解密,以便在不访问数据库的情况下确定它是否是有效令牌

我的代码用于看起来完全不同的令牌,但如果我只更改一个字母,则返回结果,不会抛出错误,因此看起来令牌是有效的

这是我的代码加上手动更改字母:

var crypto = require("crypto");

var cryptSecret = "a!=ksljdk34ajSDkl";
var token = "1d3889647173d415e24195ce5cafc36c1edcc053";

function _encodeUrlSaveBase64(str) {
  return str.replace(/\+/g, "-").replace(/\//g, "_").replace(/\=+$/, "");
}

function _decodeUrlSaveBase64(str) {
  str = (str + "===").slice(0, str.length + (str.length % 4));
  return str.replace(/-/g, "+").replace(/_/g, "/");
}

function _encrypt(data) {
  var cipher = crypto.createCipher("aes256", cryptSecret);
  var str = cipher.update(data, "utf8", "base64") + cipher.final("base64");
  str = _encodeUrlSaveBase64(str);
  return str;
}

function _decrypt(data) {
  var str = _decodeUrlSaveBase64(data);
  var decipher = crypto.createDecipher("aes256", cryptSecret);
  str = decipher.update(str, "base64", "utf8") + decipher.final("utf8");
  return str;
}

console.log("token:    ", token);
var encrypted = _encrypt(token);
console.log("encrypted:", encrypted);
// change fourth letter to upper-case B (instead of lower-case)
encrypted = "bYzBYnU8FX7Rxs6Hae-yZkXvlwlRnhMQdLrT07e6YBy79nrK8FIpbKbxsYsXUmbk";
console.log("changed  :", encrypted);
console.log("decrypt  :", _decrypt(encrypted));
它输出:

token:     1d3889647173d415e24195ce5cafc36c1edcc053
encrypted: bYzbYnU8FX7Rxs6Hae-yZkXvlwlRnhMQdLrT07e6YBy79nrK8FIpbKbxsYsXUmbk
changed  : bYzBYnU8FX7Rxs6Hae-yZkXvlwlRnhMQdLrT07e6YBy79nrK8FIpbKbxsYsXUmbk
decrypt  : �g�
1��/b���e2.195ce5cafc36c1edcc053
它通常会抛出如下错误:

TypeError: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
    at Decipher.Cipher.final (crypto.js:302:27)
    at _decrypt (/***/test.js:25:59)
    at Object.<anonymous> (/***/test.js:35:27)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    at Module.load (module.js:349:32)
    at Function.Module._load (module.js:305:12)
    at Function.Module.runMain (module.js:490:10)
    at startup (node.js:123:16)
    at node.js:1128:3

我是否做错了什么,或者这就是工作方式?

您需要区分加密隐藏和签名验证。在您的情况下,您正在隐藏令牌的内容。验证令牌的一个简单解决方案是使用秘密的哈希:

hashvalue = tokenvalue + hashfunction(tokenvalue + secret)
在验证时,切掉tokenvalue并再次计算hashvalue,如果它不匹配,则一定有人篡改了该令牌。一个流行的例子是


该方案有一些缺点,最大的缺点是各方都需要秘密来验证令牌,因此能够创建新的有效令牌。IBM因此切换到LTPA v2的公钥。

ECB模式下的AES不会对密文执行任何类型的身份验证。无论如何,ECB模式是高度可疑的,因为它泄露了有关明文的信息,并允许各种有趣的重播攻击,包括将多个密文拼接在一起。Cookie加密非常困难。还有,我希望你没有和全世界分享你的秘密。好吧,也许我误用了一些词汇。我只是想检查一下令牌是否有效。我问了我的一位同事,他给了我上面的代码。。。如果我试图解密一个无效的令牌(如aabbcc),就会抛出错误,我知道该令牌无效。我的问题是,微小的更改不会导致错误。在本例中,我将查询数据库,并在那里尝试验证它时出错。也许这是正确的行为?如果您只是想知道令牌何时由于传输错误而中断,请使用像md5、sha1、sha2这样的哈希函数,而不使用我提到的秘密。当您想要阻止坏人发送恶意/随机令牌时,请使用带有秘密的哈希。两者都称为验证。