# Rabin Cryptosystem with Implementation

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

1. Generate two very large prime numbers, p and q, which satisfies the condition
p ≠ q → p ≡ q ≡ 3 (mod 4)
For example:
p=139 and q=191
2. Calculate the value of n
n = p.q
3. Publish n as public key and save p and q as private key

Encryption

1. Get the public key n.
2. 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.
3. Encrypt with the formula:
C = m2 mod n
4. Send C to recipient.

Decryption

1. Accept C from sender.
2. Specify a and b with Extended Euclidean GCD such that, a.p + b.q = 1
3. Compute r and s using following formula:
r = C(p+1)/4 mod p
s = C(q+1)/4 mod q
4. Now, calculate X and Y using following formula:
X = ( a.p.r + b.q.s ) mod p
Y = ( a.p.r – b.q.s ) mod q
5. The four roots are, m1=X, m2=-X, m3=Y, m4=-Y
Now, Convert them to binary and divide them all in half.
6. 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
```

My Personal Notes arrow_drop_up Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.

Article Tags :

1

Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.