node.js - 将 ElGamal 加密从加密数字转换为字符串

标签 node.js string encryption encoding elgamal

我有以下 ElGamal 加密方案

const forge = require('node-forge');
const bigInt = require("big-integer");

// Generates private and public keys
function keyPairGeneration(p, q, g) {
    var secretKey = bigInt.randBetween(2, q.minus(2));
    var publicKey = g.modPow(secretKey, p);
    const keys = {
        secret: secretKey,
        public: publicKey
    }
    return keys;
}

// Generates a proxy and a user key
function generateProxyKeys(secretKey) {
    const firstKey = bigInt.randBetween(1, secretKey);
    const secondKey = secretKey.minus(firstKey);
    const keys = {
        firstKey: firstKey,
        secondKey: secondKey
    }
    return keys;
}

// Re-encrypts 
function preEncrypt(p, q, g, m, publicKey) {
    const k = bigInt.randBetween(1, q.minus(1));
    const c1 = g.modPow(k, p);
    // g^x = publicKey
    // m.publicKey^k
    const c2 = bigInt(m).multiply(publicKey.modPow(k, p)).mod(p);
    const c = {
        c1: c1, 
        c2: c2
    }
    return c;
}

function preDecrypt(p, c1, c2, key) {
    // (mg^xr) / (g^rx1)
    var decrypt = c2.multiply(c1.modPow(key, p).modInv(p)).mod(p); 
    return decrypt;
}

这对于数字来说效果很好。但是,我希望能够使用它来加密字符串(顺便说一句,它不是常规的 ElGamal,我认为区别与此上下文无关,但有关更多详细信息,请参阅 this question I asked )

我考虑过将字符串转换为整数,运行加密,然后在需要时转换回字符串。我找不到在 JS 中执行此操作的方法(这里发布了 this question 但代码不起作用)。有another similar question但它是在 Java 中,并且 JS 中的 BigInt 实现没有提供其中提到的方法。

是否有任何简单的方法可以将字符串转换为 BigInt?

最佳答案

任意长的消息

非对称加密不应用于加密任意长度的消息,因为它比对称加密慢得多。因此,我们可以对实际消息使用对称加密,对加密消息的 key 使用非对称加密。

对于任意大小的消息基本上有两种方法:

  1. 如果质数 p 足够大,适合对称密码(例如 AES)的通用 key 大小,那么您可以简单地生成随机 AES key (128、192 或 256 位) )并使用 AES 派生方案(例如 AES-GCM)来加密您的消息。然后,您从 AES key 中解码出一个数字(使用 fromArray ),以用作类似 ElGamal 的加密方案中的 m 。这称为hybrid encryption .

  2. 无论素数p有多大,您始终可以生成1范围内的随机m数>p-1 并使用它来生成非对称密文。之后,您可以将之前生成的 m 编码为字节数组(使用 toString(16) 生成十六进制编码的字符串,然后简单地将其解析为十六进制进行哈希)并使用用于获取 AES key 的加密哈希函数(例如 SHA-256)。然后,您可以使用 AES key 通过 AES-GCM 等对称方案来加密消息。这称为key encapsulation .

剩下的主要问题是数据格式:如何序列化密文的非对称部分和对称部分的数据?您如何读回它们以总是区分它们?有很多可能的解决方案。

短信

如果您要加密的消息的最大大小小于您使用的素数,则不需要上述两种方法。您只需获取消息的字节表示并将其转换为大整数。像这样的事情:

var arr = Array.prototype.slice.call(Buffer.from("some message"), 0);
var message = bigInt.fromArray(arr, 256);

这是一个big endian encoding .

只有当你的素数足够大时,这才有意义 should be for security .

关于node.js - 将 ElGamal 加密从加密数字转换为字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45617188/

相关文章:

string - Code Golf : "Color highlighting" of repeated text

c++ - 使用 C++、Openssl 和 aes 加密和解密字符串

angularjs - 是否可以将 Angular 2 Dart 前端与 Node.js 后端一起使用?

node.js - 使用 Azure Node SDK 获取应用程序设置

node.js - 加速 Socket.IO

string - 使用 {} 初始化 C++11 字符串

C++ 在句子中查找单词

node.js - 使用 AES256 和 Node.js 解密长度超过 15 个字符的输入数据时出错

php - openssl_encrypt 的密码参数是什么?

node.js - 在node.js amdefine中使用RequireJS插件