RSA加密解密&签名验证

公钥加密&私钥签名的通俗说明

================================

一、公钥加密 

假设一下,我找了两个数字,一个是1,一个是2。我喜欢2这个数字,就保留起来,不告诉你们(私钥),然后我告诉大家,1是我的公钥。

我有一个文件,不能让别人看,我就用1加密了。别人找到了这个文件,但是他不知道2就是解密的私钥啊,所以他解不开,只有我可以用

数字2,就是我的私钥,来解密。这样我就可以保护数据了。

我的好朋友x用我的公钥1加密了字符a,加密后成了b,放在网上。别人偷到了这个文件,但是别人解不开,因为别人不知道2就是我的私钥,

只有我才能解密,解密后就得到a。这样,我们就可以传送加密的数据了。

二、私钥签名

如果我用私钥加密一段数据(当然只有我可以用私钥加密,因为只有我知道2是我的私钥),结果所有的人都看到我的内容了,因为他们都知

道我的公钥是1,那么这种加密有什么用处呢?

但是我的好朋友x说有人冒充我给他发信。怎么办呢?我把我要发的信,内容是c,用我的私钥2,加密,加密后的内容是d,发给x,再告诉他

解密看是不是c。他用我的公钥1解密,发现果然是c。

这个时候,他会想到,能够用我的公钥解密的数据,必然是用我的私钥加的密。只有我知道我得私钥,因此他就可以确认确实是我发的东西。

这样我们就能确认发送方身份了。这个过程叫做数字签名。当然具体的过程要稍微复杂一些。用私钥来加密数据,用途就是数字签名。

总结:公钥和私钥是成对的,它们互相解密。

 

公钥加密,私钥解密。

 

私钥数字签名,公钥验证

相对不那么通俗的说明

============================

 RSA加密算法是最常用的非对称加密算法

RSA公钥加密算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的。RSA取名来自开发他们三者的名字。RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的所有密码攻击,已被ISO推荐为公钥数据加密标准。目前该加密方式广泛用于网上银行、数字签名等场合。

密钥的长度越长,安全性就越好,但是加密解密所用的时间就会越多。

所以非对称加密一般都用于加密对称加密算法的密钥,而不是直接加密内容。

数字签名技术是将摘要信息用发送者的私钥加密,与原文一起传送给接收者。接收者只有用发送者的公钥才能解密被加密的摘要信息,然后用对收到的原文产生一个摘要信息,与解密的摘要信息对比。如果相同,则说明收到的信息是完整的,在传输过程中没有被修改,否则说明信息被修改过,因此数字签名能够验证信息的完整性。

测试代码

package com.inspur.cloud.am.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Scanner;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

public class RSAUtil {
	
	private static RSAPublicKey publicKey = null;
	private static RSAPrivateKey privateKey = null;
	static{
	
		publicKey = (RSAPublicKey)loadKeyByFile("publicKey.keystore","publicKey");
		privateKey = (RSAPrivateKey)loadKeyByFile("privateKey.keystore","privateKey");
	}

	public static void main(String[] args) {

		//------------------------
		
		//generateKeyPair();
		
		//------------------------
		
		//使用公钥加密
		//String cipherData = encrypt(publicKey, "你好".getBytes());
		//System.out.println(cipherData);
		
		//使用私钥解密
		//System.out.println(decrypt(privateKey, cipherData));
		
		//------------------------
		
		//使用私钥加密
		//String cipherData2 = encrypt(privateKey, "中国".getBytes());
		//System.out.println(cipherData2);
		
		//使用公钥解密
		//System.out.println(decrypt(publicKey, cipherData2));
		
		//------------------------
		
		//生成签名数据
		String originalData = "你好";
		String signData = sign(originalData);
		System.out.println(signData);
		
		//验证签名
		boolean check = doCheck(originalData, signData);
		System.out.println(check);
	}

	/**
	 * 生成公钥、私钥对
	 */
	private static void generateKeyPair() {

		try {
			// 返回生成指定算法的 public/private 密钥对的 KeyPairGenerator 对象。 参数RSA算法
			KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
			// 初始化RSA长度,RSA密钥长度必须是64的倍数,在512~65536之间。默认是1024
			keyPairGenerator.initialize(1024);
			// 生成一个密钥对
			KeyPair keyPair = keyPairGenerator.generateKeyPair();
			// 获得公钥
			RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
			// 获得私钥
			RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
			// 得到公钥字符串
			String publicKeyString = Base64.encodeBytes(publicKey.getEncoded());
			// 得到私钥字符串
			String privateKeyString = Base64.encodeBytes(privateKey.getEncoded());
			// 将密钥对写入到文件
			FileWriter fw1 = new FileWriter("publicKey.keystore");
			FileWriter fw2 = new FileWriter("privateKey.keystore");
			fw1.write(publicKeyString);
			fw2.write(privateKeyString);
			fw1.flush();
			fw1.close();
			fw2.flush();
			fw2.close();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 加载公钥/私钥
	 * @param path
	 * @return
	 */
    public static Object loadKeyByFile(String path,String type){  
    	StringBuilder key = new StringBuilder();
    	Scanner s = null;
        try {
           s = new Scanner(new File(path));
         //设置分隔符,不设置,则默认使用空格进行分割
         s.useDelimiter(System.getProperty("line.separator"));
         while(s.hasNext()){
        	 key.append(s.next());
          } //关闭扫描器s.close;
        } catch (FileNotFoundException e) {
           e.printStackTrace();
        }finally{
        	s.close();
        }
        try {  
            byte[] buffer = Base64.decode(key.toString());  
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");  
            if(type.equals("privateKey")){
            	PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);  
            	return keyFactory.generatePrivate(keySpec);  
            }else{
            	X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);  
            	return keyFactory.generatePublic(keySpec);
            }
        } catch (NoSuchAlgorithmException e) {  
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {  
        	e.printStackTrace();  
        } catch (NullPointerException e) {  
        	e.printStackTrace();  
        }  
        return null;
    }  
    
    /**
     * 使用公钥/私钥加密
     * @param key 加密密钥
     * @param plainTextData 原文
     * @return 密文
     * @throws Exception
     */
    public static String encrypt(Key key,byte[] plainTextData){  
        Cipher cipher = null;  
        try {
			cipher = Cipher.getInstance("RSA");
			cipher.init(Cipher.ENCRYPT_MODE, key);  
			byte[] output = cipher.doFinal(plainTextData);  
			return Base64.encodeBytes(output); 
		} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		}  
        return null;
    }  
    /**
     * 使用公钥/私钥解密
     * @param key 解密密钥
     * @param cipherData 密文
     * @return
     */
    public static String decrypt(Key key,String cipherData){  
        Cipher cipher = null;  
        try {
			cipher = Cipher.getInstance("RSA");
			cipher.init(Cipher.DECRYPT_MODE, key);  
			byte[] output = cipher.doFinal(Base64.decode(cipherData));  
			return new String(output); 
		} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		}  
        return null;
    } 
    
    /** 
     * 私钥签名 
     * @param content 待签名数据 
     * @return 签名值 
     */  
	public static String sign(String content) {
		try {
			java.security.Signature signature = Signature.getInstance("SHA1WithRSA");
			signature.initSign(privateKey);
			signature.update(content.getBytes());

			byte[] signed = signature.sign();
			return Base64.encodeBytes(signed);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	} 
	
	/**
	 * 使用公钥验证签名
	 * @param content
	 * @param sign
	 * @return
	 */
	public static boolean doCheck(String content, String sign) {
		try {
			Signature signature = Signature.getInstance("SHA1WithRSA");
			signature.initVerify(publicKey);
			signature.update(content.getBytes());

			boolean bverify = signature.verify(Base64.decode(sign));
			return bverify;

		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}  
}

猜你喜欢

转载自huangqiqing123.iteye.com/blog/2377682
今日推荐