今天早上发了一文简单说了一下RSA公钥密码的实现。晚上就简单修改了一下早上完成的工具类然后做了一个实现数字签名的工具。还是很有意思的。
RSA的工具类做了一点小改动
createKeyPair()创建公私钥对的方法访问权限改为public
encryptWithRSA(String str,String privateKeyFile)RSA加密的方法加入了另一个参数——私钥地址。
decryptWithRSA(String secret,String publicKeyFile)RSA解密的方法加入了另一个参数——公钥地址。
原来的工具类中是用公钥加密,私钥解密的。因为现在要实现数字签名,就改成了私钥加密公钥解密。
======================RSA工具类的具体实现和原理请看我的上一文=======================
接下来介绍下几个类:
这个工具有四个类组成:
Md5_Utils——实现MD5摘要运算
RSASignUtils——实现RSA的密钥对生成,加密和解密操作
View——视图模块(其实就是几个syso)
InputUtils——输入工具类,主要是格式化输入,判断输入合法性
DigitalSignature——主类,完成具体的操作。
主类中生成公私钥对的方法:
private static void createKeyPair() throws Exception {
View.ask("是否将公私钥对存放到默认路径?Y/N");
if (InputUtils.getYesOrNot()) {
RSASignUtils.createKeyPair();
View.showInfo("公私钥对存放的路径是:" + new File("").getPath());
} else {
View.ask("请输入目标路径:");
RSASignUtils.setKeyPath(InputUtils.getPath());
RSASignUtils.createKeyPair();
}
View.showInfo("生成密钥对成功!");
}
主类中的私钥签名方法:
// 签名
private static void signature() throws Exception {
View.ask("请输入用于加密的私钥的路径:");
String file = InputUtils.getFile();
View.ask("请输入被签名的信息:");
String text = InputUtils.getString();
String hashText = Md5_Utils.getMD5Value(text);
View.ask("是否加密信息?Y/N");
String secret = "";
if (InputUtils.getYesOrNot()) {
secret = RSASignUtils.encryptWithRSA(hashText + text, file);
} else {
secret = RSASignUtils.encryptWithRSA(hashText, file) + "||||"+text;
}
View.showInfo("签名成功!签名后的信息为:"+secret);
}
主类中的公钥验证的方法:
// 验证
private static void verification() {
try{
View.ask("请输入用于解密的公钥的路径:");
String file = InputUtils.getFile();
View.ask("请输入被验证的信息:");
String text = InputUtils.getString();
String info = null;
String hashInfo = null;
if (text.contains("||||")) {
String secret = text.split("||||")[0];
info = text.split("||||")[1];
hashInfo = RSASignUtils.decryptWithRSA(secret, file);
}else{
String str = RSASignUtils.decryptWithRSA(text, file);
hashInfo = str.substring(0, 32);
info = str.substring(32);
}
if (Md5_Utils.getMD5Value(info).equals(hashInfo)) {
View.showInfo("验证成功!是合法的签名!传输过程中没有被篡改!");
View.showInfo("明文信息是:"+info);
}else{
View.inputError("请注意!消息验证不正确!");
}
}catch(Exception e){
View.inputError("请注意!消息验证不正确!");
}
}
main方法:
public static void main(String[] args) throws Exception {
boolean isContinue = true;
while (isContinue) {
View.welcome();
switch (InputUtils.getSelect()) {
case 1:
createKeyPair();
break;
case 2:
signature();
break;
case 3:
verification();
break;
case 4:
isContinue = false;
break;
default:
View.inputError();
break;
}
}
}
其实也没啥要说的,看看代码应该就明白了。View类和InputUtils类就不贴出来了,里面没啥干货。
其实我还是有一点疑问,因为在解密时需要输入签名后的信息,签名后的信息复制出来的时候有四五行,必须要将这四五行合为一行才能正确验证,否则Scanner读到一行就不读了,我也没有想到其他办法,希望大家能给我好的建议。
整个工具代码放到Git上了,大家去看吧.