RSA公私钥和签名、验签过程
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RSA公私钥和签名、验签过程相关的知识,希望对你有一定的参考价值。
参考技术A RSA又叫非对称加密算法,这类加密算法有2个秘钥,你可以选择一个作为私钥(自己保存,重要),另一个作为公钥(对外公开,谁都可以知道)。其中用私钥加密的内容只能用对应的公钥解密,同理用公钥加密的内容也只能用对应的私钥解密。假设A生成了一对秘钥,私钥自己保存,公钥对外公开,且B获得了A的公钥。在A和B通信的过程中:
A向B发送信息:A用自己的私钥加密,B可以用其公钥解密;
B向A发送信息:B用(A给的)公钥加密数据,A可以用自己的私钥解密;
这样就保证了数据的安全传输;但是这中间存在问题,如果B向A发送数据的过程中被C拦截了,且C也获得了A的公钥,这样C就可以用公钥重新加密一份数据发送给A,这样就篡改了B发送给A的数据。为了辨别这种情况,就要说到数字签名的作用了。
因为在数据传输过程中有可能被篡改,因此我们要使用数字签名技术来校验发送方的身份,并且事后发送方无法抵赖。这里还以A和B为例,来看下数字签名的主要过程:
数字签名是什么?
java RSA实现私钥签名公钥验签私钥加密数据公钥解密数据
通过OpenSSL生成公私钥文件(如果没有OpenSSL工具建议下载Cmder工具自带OpenSSL指令)
1、生成RSA密钥的方法
genrsa -out private-rsa.key 2048
2、获取客户端公钥文件
openssl req -new -x509 -key private-rsa.key -days 750 -out public-rsa.cer
3、获取服务器私钥文件
openssl pkcs12 -export -name zhangsan -in public-rsa.cer -inkey private-rsa.key -out user-rsa.pfx
Java实现私钥签名、公钥验签、私钥加密数据、公钥解密数据
import javax.crypto.Cipher; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.security.KeyStore; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; public class Sha1withRSAUtil { private static final String publicKeyFileName = System.getProperty("user.dir") + File.separator + "pubkey.cer"; private static final String privateKeyFileName = System.getProperty("user.dir") + File.separator + "private.pfx"; private static final String pfxPassword = "123";//私钥文件获取时设置的密钥 private static String aliasName = "003";//alias名称 /** * 签名 * * @return 签名后经过base64处理的字符串 * @throws Exception */ public static String sign(String str) { String base64Sign = ""; InputStream fis = null; try { fis = new FileInputStream(privateKeyFileName); KeyStore keyStore = KeyStore.getInstance("PKCS12"); char[] pscs = pfxPassword.toCharArray(); keyStore.load(fis, pscs); PrivateKey priKey = (PrivateKey) (keyStore.getKey(aliasName, pscs)); // 签名 Signature sign = Signature.getInstance("SHA1withRSA"); sign.initSign(priKey); byte[] bysData = str.getBytes("UTF-8"); sign.update(bysData); byte[] signByte = sign.sign(); BASE64Encoder encoder = new BASE64Encoder(); base64Sign = encoder.encode(signByte); } catch (Exception e) { e.printStackTrace(); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } return base64Sign; } /** * 数据验证 * * @param signStr 加密后的数据 * @param verStr 原始字符 * @return */ public static boolean verify(String signStr, String verStr) throws Exception { boolean verfy = false; InputStream fis = null; try { fis = new FileInputStream(publicKeyFileName); CertificateFactory cf = CertificateFactory.getInstance("x509"); Certificate cerCert = cf.generateCertificate(fis); PublicKey pubKey = cerCert.getPublicKey(); BASE64Decoder decoder = new BASE64Decoder(); byte[] signed = decoder.decodeBuffer(signStr); Signature sign = Signature.getInstance("SHA1withRSA"); sign.initVerify(pubKey); sign.update(verStr.getBytes("UTF-8")); verfy = sign.verify(signed); } catch (Exception e) { e.printStackTrace(); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } return verfy; } /** * 通过公钥文件进行加密数据 * * @return 加密后经过base64处理的字符串 */ public static String encrypt(String source) throws Exception { InputStream fis = null; try { fis = new FileInputStream(publicKeyFileName); CertificateFactory cf = CertificateFactory.getInstance("x509"); Certificate cerCert = cf.generateCertificate(fis); PublicKey pubKey = cerCert.getPublicKey(); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, pubKey); byte[] sbt = source.getBytes(); byte[] epByte = cipher.doFinal(sbt); BASE64Encoder encoder = new BASE64Encoder(); String epStr = encoder.encode(epByte); return epStr; } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 通过私钥文件进行解密数据 * * @return 解密后的明文字符串 */ public static String decode(String source) throws Exception { BASE64Decoder b64d = new BASE64Decoder(); byte[] keyByte = b64d.decodeBuffer(source); InputStream fis = null; try { fis = new FileInputStream(privateKeyFileName); KeyStore keyStore = KeyStore.getInstance("PKCS12"); char[] pscs = pfxPassword.toCharArray(); keyStore.load(fis, pscs); PrivateKey priKey = (PrivateKey) (keyStore.getKey(aliasName, pscs)); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, priKey); byte[] epByte = cipher.doFinal(keyByte); return new String(epByte, "UTF-8"); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
使用方法
import com.util.rsa.Sha1withRSAUtil; public class Main { public static void main(String[] args) { String data = "name123456789"; String signData = Sha1withRSAUtil.sign(data); System.out.println(signData); try { boolean flag = Sha1withRSAUtil.verify(signData, data); System.out.println(flag); String eData = Sha1withRSAUtil.encrypt(data); System.out.println(eData); String dData = Sha1withRSAUtil.decode(eData); System.out.println(dData); } catch (Exception e) { e.printStackTrace(); } } }
以上是关于RSA公私钥和签名、验签过程的主要内容,如果未能解决你的问题,请参考以下文章