代码之家  ›  专栏  ›  技术社区  ›  mcansado

单向ElGamal代理重新加密实现

  •  2
  • mcansado  · 技术社区  · 7 年前

    我在JavaScript中实现了一个ElGamal方案(代码很糟糕,只是想快速测试它),基于 this

    var forge = require('node-forge');
    var bigInt = require("big-integer");
    
    var bits = 160;
    forge.prime.generateProbablePrime(bits, function(err, num) {
      // Create prime factor and convert to bigInt
      var factor = bigInt(num.toString(10));
      // Find a larger prime of which factor is prime factor
      // Determine a large even number as a co-factor
      var coFactor = bigInt.randBetween("2e260", "3e260"); // should be bitLength(prime) - bitLength(factor)
      var prime = 4;
      while(!coFactor.isEven() || !prime.isPrime()) {
        coFactor = bigInt.randBetween("2e260", "3e260"); // should be bitLength(prime) - bitLength(factor)
        prime = coFactor.multiply(factor);
        prime = prime.add(1);
      }
      // Get a generator g for the multiplicative group mod factor
      var j = prime.minus(1).divide(factor);
      var h = bigInt.randBetween(2, prime.minus(1));
      var g = h.modPow(j, factor);
      // Alice's keys
      // Secret key
      var a = bigInt.randBetween(2, factor.minus(2));
      // Public key
      var A = g.modPow(a, prime);
      // Bob's keys
      // Secret key
      var b = bigInt.randBetween(2, factor.minus(2));
      // Public key
      var B = g.modPow(b, prime);
      // Shared secret
      // Calculated by Alice
      var Sa = B.modPow(a, prime);
      // Calculated by Bob
      var Sb = A.modPow(b, prime);
      // Check
      // Encryption by Alice
      var k = bigInt.randBetween(1, factor.minus(1));
      var c1 = g.modPow(k, prime);
      // Using Bob's public key
      var m = bigInt(2234266) // our message
      var c2 = m.multiply(B.modPow(k, prime));
      // Decryption by Bob
      var decrypt = c1.modPow((prime.minus(b).minus(bigInt(1))), prime).multiply(c2).mod(prime);
      console.log(decrypt); // should be 2234266
    

    这似乎是可行的,最后的解密步骤返回原始数字。我现在想把它转换成一个单向代理重新加密方案,基于以下想法,取自 this 论文(第6页,左栏)。

    所以你不必阅读这篇文章,背后的逻辑是我们可以分割私钥 x 分为两部分 x1 x2 x = x1 + x2 .代理将获得 x1 ,将结果传递给最终用户,最终用户将使用 x1 .

    Convertion to unidirection ElGamal

    • m=明文消息
    • g=组的发电机
    • x=密钥

    现在,我尝试通过在代码中添加

      // Proxy re-encryption test
      // x is secret key
      var x = bigInt.randBetween(1, factor.minus(1));
      var x1 = bigInt.randBetween(1, x);
      var x2 = x.minus(x1);
      // y is public key
      var y = g.modPow(x, prime);
      var r = bigInt.randBetween(1, factor.minus(1));
      var c3 = g.modPow(r, prime);
      // mg^xr
      var c4 = bigInt(2234266).multiply(y.modPow(r, prime));
    
      var _decryptP = c4.divide(g.modPow(x1.multiply(r), prime));
      var _decryptF = _decryptP.divide(g.modPow(x2.multiply(r), prime));
    });
    

    遵循与上述等式相同的逻辑。然而 _decryptF 不返回 2234266

    1 回复  |  直到 7 年前
        1
  •  2
  •   Artjom B.    7 年前

    您至少有两个问题:

    • divide a / b 实际上是指 a * (b -1 (mod p)) (mod p) .

    • multiply prime ). 你必须申请 mod 对结果进行操作。从技术上讲,你只需要做最后一次

    以下是有效的结果代码:

      // Proxy re-encryption test
      // x is secret key
      var x = bigInt.randBetween(1, factor.minus(1));
      var x1 = bigInt.randBetween(1, x);
      var x2 = x.minus(x1);
      // y is public key
      var y = g.modPow(x, prime);
      var r = bigInt.randBetween(1, factor.minus(1));
      var c3 = g.modPow(r, prime);
      // mg^xr
      var c4 = m.multiply(y.modPow(r, prime)).mod(prime);
    
      var _decryptP = c4.multiply(c3.modPow(x1, prime).modInv(prime)).mod(prime);
      var _decryptF = _decryptP.multiply(c3.modPow(x2, prime).modInv(prime)).mod(prime);
      console.log(_decryptF); // should be 2234266
    });
    

    Full code