📜  Rabin加密系统及其实现

📅  最后修改于: 2021-05-20 07:26:07             🧑  作者: Mango

Rabin密码系统是Michael Rabin发明的公用密钥密码系统。它使用非对称密钥加密在两方之间进行通信并加密消息。

Rabin密码系统的安全性与分解的难度有关。与其他优点相比,它具有的优点是整数分解被证明是困难的。还有一个缺点是,Rabin函数的每个输出都可以由四个可能的输入中的任何一个生成。如果每个输出都是密文,则解密时需要额外的复杂性,以识别四个可能的输入中的哪一个是真正的明文。

Rabin密码系统中的步骤

密钥生成

  1. 生成两个非常大的质数p和q,它们满足条件
    p≠q→p≡q≡3(mod 4)
    例如:
    p = 139和q = 191
  2. 计算n的值
    n = pq
  3. 将n发布为公钥,并将p和q保存为私钥

加密

  1. 获取公钥n。
  2. 将消息转换为ASCII值。然后将其转换为二进制并使用其自身扩展二进制值,然后将二进制值更改回十进制m。
  3. 使用以下公式加密:
    C = m 2模n
  4. 将C发送给收件人。

解密方式

  1. 接受来自发件人的C。
  2. 用扩展的欧几里得GCD指定a和b,使得ap + bq = 1
  3. 使用以下公式计算r和s:
    r = C (p + 1)/ 4 mod p
    s = C (q + 1)/ 4 mod q
  4. 现在,使用以下公式计算X和Y:
    X =(apr + bqs)mod p
    Y =(apr – bqs)mod q
  5. 四个根是,m1 = X,m2 = -X,m3 = Y,m4 = -Y
    现在,将它们转换为二进制并将它们一分为二。
  6. 确定左右一半相同。保留该二进制数的一半,然后将其转换为十进制m。获取十进制值m的ASCII字符。结果字符给出了发件人发送的正确消息。

以下是Java中Rabin密码系统的实现

// 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);
    }
}

输出:

Message sent by sender : Hello
Encrypted Message : 96683217050639837550625
Message received by Receiver : Hello