RSA数字签名
**
一、实验目的
**
学习RSA算法在数字签名方面的使用,掌握公钥签名中最基础的签名算法-RSA数字签名算法的编写。
二、实验要求
1. 熟悉RAS基本算法。
2. 熟悉RAS数字签名算法。
3. 掌握如何使用JavaBigInteger类,简单实现最基础的RSA公私钥签名算法。
三、开发环境
JDK1.7,Java开发环境(本实验采用Windows+eclipse作为实验环境),要求参与实验的同学按照对称加密提供的方法,提前安装好JDK。
四、实验内容
【1-1】RAS签名算法的实现
1.实现公私钥生成算法:根据书本上的知识, RAS公私钥生成算法首选需要选取两个大素数 和 ,并计算 ,进一步计算欧拉函数 。接着随机选取一个整数 满足 ,其中, 。最后,计算的 逆元 。因此,签名私钥为 ,公钥为 。具体的代码如下:
public void initKeys() {
BigInteger p = newBigInteger(1024, 500, new Random());
BigInteger q = newBigInteger(1024, 500, new Random());
assert(p.compareTo(q) != 0);
n = p.multiply(q);
BigIntegerfi_n = p.subtract(BigInteger.ONE)
.multiply(q.subtract(BigInteger.ONE));
e = newBigInteger(512, 100, new Random());
d = e.modInverse(fi_n);
System.out.println("n : " + n);
System.out.println("e : " + e);
System.out.println("d : " + d);
}
其中,需要在前面定义 、 和 三个全局变量。
public class RSASignatureAlgorithm {
BigIntegern;
BigIntegere;
BigIntegerd;
2.实现签名算法:RSA签名算法是对待签名的消息 进行签名,具体签名的形式如下:
此时, 即为签名后的信息。因此,可根据公式,写代码如下:
public BigInteger signature(byte m[]) {
BigInteger s = __hash(m).modPow(d, n);
System.out.println("s : " + s);
Return s;
}
而哈希函数的输出是一个值,其实现可以如下:
public BigInteger __hash(byte m[]) {
MessageDigest md;
try {
md = MessageDigest.getInstance(“SHA-256”);
md.update(m);
byte b[] = newbyte[33];
System.arraycopy(md.digest(), 0, b, 1, 32);
returnnewBigInteger(b);
} catch (NoSuchAlgorithmException e) {
System.out.println(“this cannot happen.”);
}
returnnull;
}
3.实现验证签名算法:RSA签名验证算法即判定公式 是否成立。因此,代码的实现可以如下来进行:
public boolean verify(byte m[], BigInteger s) {
BigIntegerleft = __hash(m).mod(n);
BigInteger right = s.modPow(e, n);
returnleft.compareTo(right) == 0;
}
4.实现main方法,在main方法中调用算法进行测试:
publicstaticvoidmain(String args[]) {
RSASignatureAlgorithmrs a = new RSASignatureAlgorithm();
rsa.initKeys();
byte m[] = “My name is XXX-, my students number is XXX.”.getBytes();
BigInteger s = rsa.signature(m);
System.out.println("Real signature verify result : " + rsa.verify(m, s));
s = s.add(BigInteger.ONE);
System.out.println("Faked signature verify result : " + rsa.verify(m, s));
}
【1-2】完整参考代码
importjava.math.BigInteger;
importjava.security.MessageDigest;
importjava.security.NoSuchAlgorithmException;
importjava.util.Random;
public class RSASignatureAlgorithm {
BigInteger n;
BigInteger e;
BigInteger d;
publicBigInteger __hash(byte m[]) {
MessageDigest md;
try {
md = MessageDigest.getInstance("SHA-256");
md.update(m);
byte b[] = newbyte[33];
System.arraycopy(md.digest(), 0, b, 1, 32);
return new BigInteger(b);
} catch (NoSuchAlgorithmException e) {
System.out.println("this cannot happen.");
}
return null;
}
public void initKeys() {
BigInteger p = new BigInteger(1024, 500, new Random());
BigInteger q = new BigInteger(1024, 500, new Random());
assert(p.compareTo(q) != 0);
n = p.multiply(q);
BigIntegerfi_n = p.subtract(BigInteger.ONE)
.multiply(q.subtract(BigInteger.ONE));
e = newBigInteger(512, 100, new Random());
d = e.modInverse(fi_n);
System.out.println("n : " + n);
System.out.println("e : " + e);
System.out.println("d : " + d);
}
public BigInteger signature(byte m[]) {
BigInteger s = __hash(m).modPow(d, n);
System.out.println("s : " + s);
return s;
}
public boolean verify(byte m[], BigInteger s) {
BigInteger left = __hash(m).mod(n);
BigInteger right = s.modPow(e, n);
return left.compareTo(right) == 0;
}
public static void main(String args[]) {
RSASignatureAlgorithm rsa = new RSASignatureAlgorithm();
rsa.initKeys();
byte m[] = "My name is XXX, my students number is XXX.".getBytes();
BigInteger s = rsa.signature(m);
System.out.println("Real signature verify result : " + rsa.verify(m, s));
s = s.add(BigInteger.ONE);
System.out.println("Faked signature verify result : " + rsa.verify(m, s));
}
}
注
RSA签名算法是用其生成的私钥 来对待签名的消息 进行数据签名,而用其公钥 来进行验证。其中私钥 是进行秘密保存的,而且只有签名方才拥有该私钥,这就达到了不可否认性。如果两者用反了,就是RSA的加解密算法,也就是用公钥 来对消息 进行加密,而用私钥 来解密。此外,在教科书式学习中可以将随机数的大小从1024调到512,即可提高运行速度。