Diffie-Hellman Key Exchange with Javascript sometimes wrong

落爺英雄遲暮 提交于 2021-02-07 09:13:53

问题


After watching this video http://youtu.be/3QnD2c4Xovk

I've been trying to follow it step by step, and haven't been able to produce the same results.

Notably, when I try to do Math.pow(3, 54)%17, I get 7. While the speaker gets 15.

I wrote a method that is supposed to simulate Diffie Hellman's key exchange using exactly what I found on http://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange

This is my code:

function diffieHellman(generator, prime, alice_secret, bob_secret){
  var alice_public = Math.pow(generator, alice_secret)%prime
    , bob_public = Math.pow(generator, bob_secret)%prime
    , alice_private = Math.pow(bob_public, alice_secret)%prime
    , bob_private = Math.pow(alice_public, bob_secret)%prime;
  console.log("alice"
  , "\n\t", "secret -- ", alice_secret
  , "\n\t", "public -- ", alice_public
  , "\n\t", "private -- ", alice_private
  )
  console.log("bob"
  , "\n\t", "secret -- ", bob_secret
  , "\n\t", "public -- ", bob_public
  , "\n\t", "private -- ", bob_private
  )
  return {
    alice:{
      secret: alice_secret
    , public: alice_public
    , private: alice_private
    },
    bob:{
      secret: bob_secret
    , public: bob_public
    , private: bob_private
    }
  }
};

These examples work:

diffieHellman(3, 17, 4, 12) // 1, 1
diffieHellman(3, 23, 6, 19) // 12, 12
diffieHellman(3, 13, 8, 4) // 9, 9

However, some numbers don't work

diffieHellman(3, 17, 40, 120) // 13, 0
diffieHellman(3, 23, 16, 129) // 21, 2
diffieHellman(3, 13, 44, 11) // 9, 1

What am I doing wrong?

Edit -- I'm not trying to implement Diffie-Hellman's Key Exchange in Javascript for a project. It's just the language I'm most comfortable with, but I am afraid if this could be a javascript limitation.


回答1:


3^54 is 58149737003040059690390169. It causes an overflow, therefore you should implement modular exponentation, since i don't know javascript too well i have written a c code which should be easy to implement in javascript :

int power(int a, int b, int prime){
      int result;
      if(b == 0){
           result = 1;
      }else if(b == 1){
           result = a % prime;
      }else if(b % 2 == 0){
           result = power((a*a) % prime, b/2, prime);
           result = result % prime;
      }else{
           result = power((a*a) % prime, b/2, prime);
           result = (result * a) % prime;
      }
  return result;
  }

Now you can call this function :

int value = power(3, 54, 17);

and it should work.

Edit: added javascript version

function power(a, b, prime) {
    if (b <= 0) {
        return 1;
    } else if (b === 1) {
        return a % prime;
    } else if (b % 2 === 0) {
        return power((a * a) % prime, b / 2 | 0, prime) % prime;
    } else {
        return (power((a * a) % prime, b / 2 | 0, prime) * a) % prime;
    }
}



回答2:


The problem is the limited precision of Javascript numbers that causes rounding errors in your code where you first exponentiate and then calculate the modulus. For your example numbers, you could fix this by periodically calculating the modulus inside the exponentiation, e.g. by never calculating more than a square before taking the modulus. But for actual cryptography your calculations will involve numbers too big to be handled as Javascript numbers (and most programming languages pose the same problem). The usual approach is to use a large integer (or even arbitrary precision) library. If you do end up implementing your own cryptography, please watch out for side channels, e.g. by calling library functions that are not constant time or allow cache-based attacks by using data dependent array indices.



来源:https://stackoverflow.com/questions/24677932/diffie-hellman-key-exchange-with-javascript-sometimes-wrong

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!