Rabin密码系统是Michael Rabin发明的公用密钥密码系统。它使用非对称密钥加密在两方之间进行通信并加密消息。
Rabin密码系统的安全性与分解的难度有关。与其他优点相比,它具有的优点是整数分解被证明是困难的。还有一个缺点是,Rabin函数的每个输出都可以由四个可能的输入中的任何一个生成。如果每个输出都是密文,则解密时需要额外的复杂性,以识别四个可能的输入中的哪一个是真正的明文。
Rabin密码系统中的步骤
密钥生成
- 生成两个非常大的质数p和q,它们满足条件
p≠q→p≡q≡3(mod 4)
例如:
p = 139和q = 191 - 计算n的值
n = pq - 将n发布为公钥,并将p和q保存为私钥
加密
- 获取公钥n。
- 将消息转换为ASCII值。然后将其转换为二进制并使用其自身扩展二进制值,然后将二进制值更改回十进制m。
- 使用以下公式加密:
C = m 2模n - 将C发送给收件人。
解密方式
- 接受来自发件人的C。
- 用扩展的欧几里得GCD指定a和b,使得ap + bq = 1
- 使用以下公式计算r和s:
r = C (p + 1)/ 4 mod p
s = C (q + 1)/ 4 mod q - 现在,使用以下公式计算X和Y:
X =(apr + bqs)mod p
Y =(apr – bqs)mod q - 四个根是,m1 = X,m2 = -X,m3 = Y,m4 = -Y
现在,将它们转换为二进制并将它们一分为二。 - 确定左右一半相同。保留该二进制数的一半,然后将其转换为十进制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