Rabin Cryptosystem with Implementation - GeeksforGeeks

17 Jan, 2020
Rabin Cryptosystem is an public-key cryptosystem invented by Michael Rabin. It uses asymmetric key encryption for communicating between two parties and encrypting the message.
The security of Rabin cryptosystem is related to the difficulty of factorization. It has the advantage over the others that the problem on which it banks has proved to be hard as integer factorization. It has the disadvantage also, that each output of the Rabin function can be generated by any of four possible inputs. if each output is a ciphertext, extra complexity is required on decryption to identify which of the four possible inputs was the true plaintext.
Steps in Rabin cryptosystem
Key generation
Generate two very large prime numbers, p and q, which satisfies the conditionp ≠ q → p ≡ q ≡ 3 (mod 4)For example:  p=139 and q=191Calculate the value of n  n = p.qPublish n as public key and save p and q as private key
Generate two very large prime numbers, p and q, which satisfies the conditionp ≠ q → p ≡ q ≡ 3 (mod 4)For example:  p=139 and q=191
Calculate the value of n  n = p.q
Publish n as public key and save p and q as private key
Encryption
Get the public key n.Convert the message to ASCII value. Then convert it to binary and extend the binary value with itself, and change the binary value back to decimal m.Encrypt with the formula:C = m2 mod nSend C to recipient.
Get the public key n.
Convert the message to ASCII value. Then convert it to binary and extend the binary value with itself, and change the binary value back to decimal m.
Encrypt with the formula:C = m2 mod n
Send C to recipient.
Decryption
Accept C from sender.Specify a and b with Extended Euclidean GCD such that, a.p + b.q = 1Compute r and s using following formula:r = C(p+1)/4 mod ps = C(q+1)/4 mod qNow, calculate X and Y using following formula:X = ( a.p.r + b.q.s ) mod pY = ( a.p.r – b.q.s ) mod qThe four roots are, m1=X, m2=-X, m3=Y, m4=-YNow, Convert them to binary and divide them all in half.Determine in which the left and right half are same. Keep that binary’s one half and convert it to decimal m. Get the ASCII character for the decimal value m. The resultant character gives the correct message sent by sender.
Accept C from sender.
Specify a and b with Extended Euclidean GCD such that, a.p + b.q = 1
Compute r and s using following formula:r = C(p+1)/4 mod ps = C(q+1)/4 mod q
Now, calculate X and Y using following formula:X = ( a.p.r + b.q.s ) mod pY = ( a.p.r – b.q.s ) mod q
The four roots are, m1=X, m2=-X, m3=Y, m4=-YNow, Convert them to binary and divide them all in half.
Determine in which the left and right half are same. Keep that binary’s one half and convert it to decimal m. Get the ASCII character for the decimal value m. The resultant character gives the correct message sent by sender.
Following is the implementation of Rabin cryptosystem in Java
// Java program to illustrate// Process of Rabin Cryptosystem  import java.math.BigInteger;import java.nio.charset.Charset;import java.security.SecureRandom;import java.util.Random;  class Cryptography {    private static Random r = new SecureRandom();    private static BigInteger TWO = BigInteger.valueOf(2);    private static BigInteger THREE = BigInteger.valueOf(3);    private static BigInteger FOUR = BigInteger.valueOf(4);      public static BigInteger[] generateKey(int bitLength)    {        BigInteger p = blumPrime(bitLength / 2);        BigInteger q = blumPrime(bitLength / 2);        BigInteger N = p.multiply(q);        return new BigInteger[] { N, p, q };    }      public static BigInteger encrypt(BigInteger m,                                     BigInteger N)    {        return m.modPow(TWO, N);    }      public static BigInteger[] decrypt(BigInteger c,                                       BigInteger p,                                       BigInteger q)    {        BigInteger N = p.multiply(q);        BigInteger p1 = c.modPow(p                                     .add(BigInteger.ONE)                                     .divide(FOUR),                                 p);        BigInteger p2 = p.subtract(p1);        BigInteger q1 = c.modPow(q                                     .add(BigInteger.ONE)                                     .divide(FOUR),                                 q);        BigInteger q2 = q.subtract(q1);          BigInteger[] ext = Gcd(p, q);        BigInteger y_p = ext[1];        BigInteger y_q = ext[2];          BigInteger d1 = y_p.multiply(p)                            .multiply(q1)                            .add(y_q.multiply(q)                                     .multiply(p1))                            .mod(N);        BigInteger d2 = y_p.multiply(p)                            .multiply(q2)                            .add(y_q.multiply(q)                                     .multiply(p1))                            .mod(N);        BigInteger d3 = y_p.multiply(p)                            .multiply(q1)                            .add(y_q.multiply(q)                                     .multiply(p2))                            .mod(N);        BigInteger d4 = y_p.multiply(p)                            .multiply(q2)                            .add(y_q.multiply(q)                                     .multiply(p2))                            .mod(N);          return new BigInteger[] { d1, d2, d3, d4 };    }      public static BigInteger[] Gcd(BigInteger a, BigInteger b)    {        BigInteger s = BigInteger.ZERO;        BigInteger old_s = BigInteger.ONE;        BigInteger t = BigInteger.ONE;        BigInteger old_t = BigInteger.ZERO;        BigInteger r = b;        BigInteger old_r = a;        while (!r.equals(BigInteger.ZERO)) {            BigInteger q = old_r.divide(r);            BigInteger tr = r;            r = old_r.subtract(q.multiply(r));            old_r = tr;              BigInteger ts = s;            s = old_s.subtract(q.multiply(s));            old_s = ts;              BigInteger tt = t;            t = old_t.subtract(q.multiply(t));            old_t = tt;        }        return new BigInteger[] { old_r, old_s, old_t };    }      public static BigInteger blumPrime(int bitLength)    {        BigInteger p;        do {            p = BigInteger.probablePrime(bitLength, r);        } while (!p.mod(FOUR).equals(THREE));        return p;    }}public class RabinCryptosystem {    public static void main(String[] args)    {        BigInteger[] key = Cryptography.generateKey(512);        BigInteger n = key[0];        BigInteger p = key[1];        BigInteger q = key[2];        String finalMessage = null;        int i = 1;        String s = "Hello";          System.out.println("Message sent by sender : " + s);          BigInteger m            = new BigInteger(                s.getBytes(                    Charset.forName("ascii")));        BigInteger c = Cryptography.encrypt(m, n);          System.out.println("Encrypted Message : " + c);          BigInteger[] m2 = Cryptography.decrypt(c, p, q);        for (BigInteger b : m2) {            String dec = new String(                b.toByteArray(),                Charset.forName("ascii"));            if (dec.equals(s)) {                finalMessage = dec;            }            i++;        }        System.out.println(            "Message received by Receiver : "            + finalMessage);    }}
Output:
Message sent by sender : Hello
Encrypted Message : 96683217050639837550625
Message received by Receiver : Hello

Articles
Java Programs
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
Time Complexity and Space Complexity
Docker - COPY Instruction
Time complexities of different data structures
Difference between Min Heap and Max Heap
SQL | Date functions
Convert a String to Character array in Java
Initializing a List in Java
Java Programming Examples
Convert Double to Integer in Java
Implementing a Linked List in Java using Class