关于数字签名基础知识

1.消息摘要
public class MessageDigestExample {

public static void main(String[] args) throws Exception {

String beforeDegist = "asdf";
System.out.println("摘要前:"+beforeDegist);

//初始信息要转换成字节流的形式
byte[] plainText = beforeDegist.getBytes("GBK");

//使用getInstance("算法")来获得消息摘要,这里使用SHA-1的160位算法
// MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
MessageDigest messageDigest = MessageDigest.getInstance("MD5");

// System.out.println("\n" + messageDigest.getProvider().getInfo());

//开始使用算法
messageDigest.update(plainText);

//输出算法运算结果 \

String afterDegist = new String(messageDigest.digest(),"GBK");
System.out.println("摘要后:"+afterDegist);
}

}


2.私钥加密
/**  
* 此例子是对一个字符串信息,用一个私钥(key)加密,然后在用该私钥解密,验证是否一致
* 私钥加密,是对称加密
* 使用对称算法。比如:A用一个密钥对一个文件加密,而B读取这个文件的话,则需要和A一样的密钥,双方共享一
* 个私钥(而在web环境下,私钥在传递时容易被侦听)
*
* 附:主要对称算法有:DES(实际密钥只用到56 位)
* AES(支持三种密钥长度:128、192、256位),通常首先128位,其他的还有DESede等
*/

public static void main(String[] args) throws Exception {

String before = "asdf";
byte[] plainText = before.getBytes("UTF8");

//1步**********************************************************************
System.out.println("Start generate AES key.");
//得到一个使用AES算法的KeyGenerator的实例
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
//定义密钥长度128位
keyGen.init(128);
//通过KeyGenerator产生一个key(密钥算法刚才已定义,为AES)
Key key = keyGen.generateKey();
System.out.println("Finish generating AES key."+key);
//2步**********************************************************************
//获得一个私钥加密类Cipher,定义Cipher的基本信息:ECB是加密方式,PKCS5Padding是填充方法
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");

//3步**********************************************************************
//使用私钥加密
System.out.println("\n用私钥加密...");
//把刚才生成的key当作参数,初始化使用刚才获得的私钥加密类,Cipher.ENCRYPT_MODE意思是加密
cipher.init(Cipher.ENCRYPT_MODE, key);

//私钥加密类Cipher进行加密,加密后返回一个字节流byte[]
byte[] cipherText = cipher.doFinal(plainText);

//以UTF8格式把字节流转化为String
String after1 = new String(cipherText, "UTF8");
System.out.println("用私钥加密完成:"+after1);


//4步**********************************************************************
//使用私钥对刚才加密的信息进行解密,看看是否一致,Cipher.DECRYPT_MODE意思是解密钥
System.out.println("\n用私钥解密...");
cipher.init(Cipher.DECRYPT_MODE, key);

//对刚才私钥加密的字节流进行解密,解密后返回一个字节流byte[]
byte[] newPlainText = cipher.doFinal(cipherText);

String after2 = new String(newPlainText, "UTF8");
System.out.println("用私钥解密完成:"+after2);
}



3.公钥加密
/**  
* 此例子是一个公钥加密例子,Cipher类使用KeyPairGenerator(顾名思义:一对钥匙生成器)生成的公钥和私钥
*
* 公钥加密也叫不对称加密,不对称算法使用一对密钥对,一个公钥,一个私钥,使用公钥加密的数据,只有私钥能
* 解开(可用于加密);同时,使用私钥加密的数据,只有公钥能解开(签名)。但是速度很慢(比私钥加密慢100到
* 1000倍),公钥的主要算法有RSA,还包括Blowfish,Diffie-Helman 等
*/

public static void main(String[] args) throws Exception {

String before = "asdf";
byte[] plainText = before.getBytes("UTF8");

//产生一个RSA密钥生成器KeyPairGenerator(顾名思义:一对钥匙生成器)
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
//定义密钥长度1024位
keyGen.initialize(1024);
//通过KeyPairGenerator产生密钥,注意:这里的key是一对钥匙!!
KeyPair key = keyGen.generateKeyPair();

//获得一个RSA的Cipher类,使用公钥加密
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

System.out.println("\n用公钥加密...");
//Cipher.ENCRYPT_MODE意思是加密,从一对钥匙中得到公钥 key.getPublic()
cipher.init(Cipher.ENCRYPT_MODE, key.getPublic());
//用公钥进行加密,返回一个字节流
byte[] cipherText = cipher.doFinal(plainText);
//以UTF8格式把字节流转化为String
String after1 = new String(cipherText, "UTF8");
System.out.println("用公钥加密完成:"+after1);


//使用私钥解密
System.out.println("\n用私钥解密...");
//Cipher.DECRYPT_MODE意思是解密,从一对钥匙中得到私钥 key.getPrivate()
cipher.init(Cipher.DECRYPT_MODE, key.getPrivate());
//用私钥进行解密,返回一个字节流
byte[] newPlainText = cipher.doFinal(cipherText);

String after2 = new String(newPlainText, "UTF8");
System.out.println("用私钥解密完成:"+after2);
}



4.数字签名
/**  
* 此例子是数字签名的例子,使用RSA私钥对消息摘要(这里指的是原始数据)进行签名,然后使用公钥验证签名
* A通过使用B的公钥加密数据后发给B,B利用B的私钥解密就得到了需要的数据(进过B公钥加密的数据只有B的私钥能够
* 解开,但C可以使用B的公钥加密一份数据发给B,这样一来,问题来了,B收到的数据到 底是A发过来的还是C发过来的呢)
* 由于私钥是唯一的,那么A就可以利用A自己的私钥进行加密,然后B再利用A的公钥来解密,就可以确定:一定是A的消
* 息,数字签名的原理就基于此
* 总结:A想将目标数据传给B,此时A需要准备1和2两部分
* 1:A使用B的公钥将原始信息加密,以起到保密作用
* 2:A使用A的私钥将原始信息的摘要进行签名,以起到接收方B确定是A发过来的作用(A用A的私钥对目标数据的摘要进行签
* 名,然后传给B,同时,C用C的私钥对任意信息进行签名也传给B,B想接受的是A的数据(比如说一个转帐请求),于是B
* 就通过A的公钥对接受到的两个信息进行解密,解开的就是A(A的公钥能且只能解开A的私钥加密的数据))
*/

public static void main(String[] args) throws Exception {

String before = "asdf";
byte[] plainText = before.getBytes("UTF8");

//形成RSA公钥对
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024);
KeyPair key = keyGen.generateKeyPair();

//使用私钥签名**********************************************************
Signature sig = Signature.getInstance("SHA1WithRSA");
sig.initSign(key.getPrivate());//sig对象得到私钥
//签名对象得到原始数据
sig.update(plainText);//sig对象得到原始数据(现实中用的是原始数据的摘要,摘要的是单向的,即摘要算法后无法解密)
byte[] signature = sig.sign();//sig对象用私钥对原始数据进行签名,签名后得到签名signature
String after1 = new String(signature, "UTF8");
System.out.println("\n用私钥签名后:"+after1);

//使用公钥验证**********************************************************
sig.initVerify(key.getPublic());//sig对象得到公钥
//签名对象得到原始信息
sig.update(plainText);//sig对象得到原始数据(现实中是摘要)
try {
if (sig.verify(signature)) {//sig对象用公钥解密签名signature得到原始数据(即摘要),一致则true
System.out.println("签名验证正确!!");
} else {
System.out.println("签名验证失败!!");
}
} catch (SignatureException e) {
System.out.println("签名验证失败!!");
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值