1

i need a way to calculate:

m = a. b ^(p-1-x) mod p

in javascript. i have found this algorithm for calculating base^exp%mod:

function expmod(base, exp, mod){
if (exp == 0) return 1;
if (exp % 2 == 0){
    return Math.pow((this.expmod(base, (exp / 2), mod)), 2) % mod;
}
else {
    return (base * (this.expmod(base, (exp - 1), mod))) % mod;
}          

}

and it's works great. but I can't seem to find a way to do this for

m         = a. b ^(p-1-x) mod p

i'm sorry if this question not perfect. this is my first question here. thank you.

Justin Iurman
  • 18,954
  • 3
  • 35
  • 54

1 Answers1

4

I have no experience with cryptography, but, since no one else is answering, I'll give it a shot.

Your question didn't quite make sense to me the way it was phrased, so I decided to implement a complete Elgamal in JavaScript so that I could understand your problem in context. Here's what I came up with:

// Abstract:

var Alphabet = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ \n𮃩∆";

Alphabet = Alphabet.split("");

var Crypto = function (alpha, gen, C) {
    var p, B, encrypt, decrypt, f, g, modInv, modPow, toAlpha, to10;
    toAlpha = function (x) {
        var y, p, l, n;
        if (x === 0) {
            return "!!!!";
        }
        y = [];
        n = 4;
        n = Math.ceil(n);
        while (n--) {
            p = Math.pow(alpha.length, n);
            l = Math.floor(x / p);
            y.push(alpha[l]);
            x -= l * p;
        }
        y = y.join("");
        return y;
    };
    to10 = function (x) {
        var y, p, n;
        y = 0;
        p = 1;
        x = x.split("");
        n = x.length;
        while (n--) {
            y += alpha.indexOf(x[n]) * p;
            p *= alpha.length;
        }
        return y;
    };
    modInv = function (gen, mod) {
        var v, d, u, t, c, q;
        v = 1;
        d = gen;
        t = 1;
        c = mod % gen;
        u = Math.floor(mod / gen);
        while (d > 1) {
            q = Math.floor(d / c);
            d = d % c;
            v = v + q * u;
            if (d) {
                q = Math.floor(c / d);
                c = c % d;
                u = u + q * v;
            }
        }
        return d ? v : mod - u;
    };
    modPow = function (base, exp, mod) {
        var c, x;
        if (exp === 0) {
            return 1;
        } else if (exp < 0) {
            exp = -exp;
            base = modInv(base, mod);
        }
        c = 1;
        while (exp > 0) {
            if (exp % 2 === 0) {
                base = (base * base) % mod;
                exp /= 2;
            } else {
                c = (c * base) % mod;
                exp--;
            }
        }
        return c;
    };
    p = 91744613;
    C = parseInt(C, 10);
    if (isNaN(C)) {
        C = Math.round(Math.sqrt(Math.random() * Math.random()) * (p - 2) + 2);
    }
    B = modPow(gen, C, p);
    decrypt = function (a) {
        var d, x, y;
        x = a[1];
        y = modPow(a[0], -C, p);
        d = (x * y) % p;
        d = Math.round(d) % p;
        return alpha[d - 2];
    };
    encrypt = function (key, d) {
        var k, a;
        k = Math.ceil(Math.sqrt(Math.random() * Math.random()) * 1E10);
        d = alpha.indexOf(d) + 2;
        a = [];
        a[0] = modPow(key[1], k, key[0]);
        a[1] = (d * modPow(key[2], k, key[0])) % key[0];
        return a;
    };
    f = function (message, key) {
        var n, x, y, w;
        y = [];
        message = message.split("");
        n = message.length;
        while (n--) {
            x = encrypt(key, message[n]);
            y.push(toAlpha(x[0]));
            y.push(toAlpha(x[1]));
        }
        y = y.join("");
        return y;
    };
    g = function (message) {
        var n, m, d, x;
        m = [];
        n = message.length / 8;
        while (n--) {
            x = message[8 * n + 4];
            x += message[8 * n + 5];
            x += message[8 * n + 6];
            x += message[8 * n + 7];
            m.unshift(x);
            x = message[8 * n];
            x += message[8 * n + 1];
            x += message[8 * n + 2];
            x += message[8 * n + 3];
            m.unshift(x);
        }
        x = [];
        d = [];
        n = m.length / 2;
        while (n--) {
            x[0] = m[2 * n];
            x[1] = m[2 * n + 1];
            x[0] = to10(x[0]);
            x[1] = to10(x[1]);
            d.push(decrypt(x));
        }
        message = d.join("");
        return message;
    };
    return {
        pubKey: [p, gen, B],
        priKey: C,
        decrypt: g,
        encrypt: f
    };
};

// Usage:

var Alice = Crypto(Alphabet, 69);

var Bob = Crypto(Alphabet, 69);

var message = "Hello!";
console.log(message);
// "Hello!"

message = Alice.encrypt(message, Bob.pubKey);
print(message);
// "Pl)7t&rfGueuL@|)H'P,*<K\.hxw+∆d*`?Io)lg~Adz-6xrR" or something like it.

message = Bob.decrypt(message);
console.log(message);
// "Hello!"

So, basically, Crypto handles all of the Elgamal algorithms, using modPow when it needs to. I think that the modPow function was what you were originally after, wasn't it? The version that you originally posted uses repeated squaring instead of ordinary exponentiation, presumably for purposes of performance, but they're both reasonably speedy.

It still isn't clear to me, though, why you needed a different algorithm for doing "m = a. b ^(p-1-x) mod p". I never needed anything like that in implementing my Elgamal, so I'm not sure what this corresponds to. I did need to implement a function that calculates the modular multiplicative inverse, which I called modInv. Is that what you wanted? I used a stripped-down version of the Extended Euclidean Algorithm to make it.

If it helps, feel free to copy part or all of my code for your project.

And, if you have any more questions about this, please ask me!

EDIT: Note, this code is not intended for actual production-grade encryption. It is really just a proof of concept for the algorithm. With a little work, however, it could be made more secure. Let me know.


EDIT: To encrypt and decrypt text, do the following:

Create a new Crypto object to encrypt the text, and then save it:

var Alice=Crypto(Alphabet, 69);

Here, Alice is just some variable, Alphabet is the 29-symbol alphabet that I defined at the top of the code, and 69 is a primitive root mod 91744613.

Then, create another Crypto object to decrypt the text, and then save it:

var Bob=Crypto(Alphabet, 69);

Although Bob was created in the same way as Alice, they are different objects. Bob cannot decrypt text intended for Alice, and Alice cannot decrypt text intended for Bob.

Now, use Alice's encrypt method to encrypt some text, and save the result:

var codedMessage=Alice.encrypt("HELLO, WORLD.", Bob.pubKey);

Here, message is an empty variable, "HELLO, WORLD." is the text to be encrypted (or the contents of a text file). Bob.key is Bob's public key. We must use Bob's key in the encryption so that Bob (and only Bob) can decrypt the text. The resulting encrypted text will look something like this: "Pl)7t&rfGueuL@|)H'P,*<K\.hxw+∆d*?Io)lg~Adz-6xrR"`. Note that even with the same message, different output will be generated each time. It will still always decrypt to the same value.

Now, in theory, we can send this encrypted text over whatever un-secure channel we want, and no one will be able to decode it. When Bob receives the encrypted text, however, he can decode it. To do this:

var plainMessage=Bob.decrypt(codedMessage);

Now, plainMessage will contain the text "HELLO, WORLD.", which you can read or do whatever you want with.

So, all together, just these four lines will do it:

var Alice=Crypto(Alphabet, 69);
var Bob=Crypto(Alphabet, 69);
var codedMessage=Alice.encrypt("HELLO, WORLD.", Bob.pubKey);
var plainMessage=Bob.decrypt(codedMessage);

// Now, plainMessage contains "HELLO, WORLD."

If you specifically want to do this with text files, then you can either copy-and-paste the contents into the javascript, or you can look into loading the contents of a text file into javascript. To get started, see this SO, and this HG.

Community
  • 1
  • 1
mindoftea
  • 816
  • 6
  • 16
  • Yes, sir. I have another question, how can i use it to encrypt text files? – user3543541 Apr 21 '14 at 04:13
  • Use my code, you mean? I've implemented encrypt and decrypt functions, which you see used at the bottom of the snippet. I'll edit my answer to include more specific information. – mindoftea Apr 21 '14 at 04:23
  • @user3543541, I've made some edits that should answer your additional question. – mindoftea Apr 21 '14 at 04:51
  • I want to apply this in to thunderbird addons, and the public key (y, g and p) need to be manually input so that alice and bob can exchange key and manually encrypt and decrypt. How can i do this? I'm sorry for having so much questions sir. – user3543541 Apr 21 '14 at 06:35
  • Look, so, am I right in thinking that you haven't done much JavaScript coding? I don't know much about Thunderbird, so I'm not sure what's involved in making add-ons for it. It sounds to me like what you want is a user interface for the Elgamal. I'll build a minimal one for you in HTML, and send you a link. – mindoftea Apr 21 '14 at 14:41
  • What is the recipient's public key? – user3543541 Apr 22 '14 at 07:29
  • I thought you said you said you wanted something where you could input the recipient's public key, so that's what I built. What you could do, if you want to test it, is open that program in two different windows, one for Alice and one for Bob, and then exchange public keys between the windows. Data encrypted in one can then be decrypted by the other. – mindoftea Apr 22 '14 at 12:32
  • @user3543541, you can also just copy your own public key down into the recipient's public key box. Then you are sending a message for yourself, so that same window will be able to encrypt and then decrypt the resulting text. – mindoftea Apr 22 '14 at 12:53
  • How do you generate those keys? It suppose to be like this: y = g^x mod p y, g, p = public key y = big random prime number g and p = random number x = private key help me sir. – user3543541 Apr 24 '14 at 10:40
  • You first pick a large prime called `p`. Then you pick a primitive element `gen` mod `p`. Then you pick a random number, `c`, between 2 and p-2. Now, compute `b` such that `b= gen^c % p`. Your public key is `[p, gen, b]`, and your private key is `c`. This is all in the code. – mindoftea Apr 24 '14 at 13:04
  • I only know what I know about this from internet research. If you read through these articles, you'll know as much as I do about it: http://homepages.math.uic.edu/~leon/mcs425-s08/handouts/el-gamal.pdf, http://en.wikipedia.org/wiki/ElGamal_encryption#The_algorithm, http://www.math.wvu.edu/~kristakay/2.4%20-%20ElGamal%20Public%20Key%20Cryptosystem.pdf. – mindoftea Apr 24 '14 at 13:05
  • Can you edit the http://jsfiddle.net/mindoftea/bud9V/ to browse some txt files and encrypt/ decrypt it? – user3543541 Apr 25 '14 at 04:17
  • Look, I don't know why you need this, but I can't just write it all for you. I'm happy to help you, but you really need to learn to code if you're going to do this. Specifically with regard to txt files, see the last paragraph of my answer. Try to implement it. If you run into a specific problem, post another question. – mindoftea Apr 25 '14 at 05:10