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,即可提高運行速度。