关于数字签名基础知识

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("签名验证失败!!");   
	        }   
	    }   

你可能感兴趣的:(java)