zoukankan      html  css  js  c++  java
  • RSA加解密用途简介及java示例

    在公司当前版本的中间件通信框架中,为了防止非授权第三方和到期客户端的连接,我们通过AES和RSA两种方式的加解密策略进行认证。对于非对称RSA加解密,因为其性能耗费较大,一般仅用于认证连接,不会用于每次报文本身的加解密(这一般使用AES(最主流的加密算法)/DES加密),对于较为安全的支付通道,则一般是约定定期交换加解密密钥,交换过程本身的报文则是通过RSA进行加解密的。这样就在单纯的对称加密的基础上提供了更好的保障,只要签名复杂,定期的更新足以使得破坏的成本高昂到超过破解的成本。在SSL中,基本上也是这样的实现方式。

    想DSA、ECDSA等只能用于签名,无法用于加密。

    一般来说,公钥会发布给客户端,客户端用其加密报文。私钥则用于解密报文。在java 实现的RSA中,可参考如下:

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.math.BigInteger;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.interfaces.RSAPrivateKey;
    import java.security.interfaces.RSAPublicKey;
    
    import org.apache.commons.codec.binary.Base64;
    
    public class RSAUtils {
        /**
         * 生成公钥和私钥, 一般一次性生成, 存储在文件中进行分发和使用
         */
        public static void generateKey() {  
            try {  
                KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");  
                kpg.initialize(1024);  //一般来说, 长度为2048是最好的, 也是推荐的
                KeyPair kp = kpg.genKeyPair();  
                PublicKey pbkey = kp.getPublic();  
                PrivateKey prkey = kp.getPrivate();  
                // 保存公钥  
                FileOutputStream f1 = new FileOutputStream("d:/pubkey.dat");  
                ObjectOutputStream b1 = new ObjectOutputStream(f1);  
                b1.writeObject(pbkey);  
                // 保存私钥  
                FileOutputStream f2 = new FileOutputStream("d:/privatekey.dat");  
                ObjectOutputStream b2 = new ObjectOutputStream(f2);  
                b2.writeObject(prkey);  
            } catch (Exception e) {  
            }  
        }
        
        /**
         * 公钥加密, 一般调用者传递明文, 从本地存储读取公钥进行加密
         * @param plainTxt
         * @return
         * @throws Exception
         */
        public static String pubEncrypt(String plainTxt) throws Exception {  
            String s = Base64.encodeBase64String(plainTxt.getBytes("UTF-8"));  
            // 获取公钥及参数e,n  
            FileInputStream f = new FileInputStream("d:/pubkey.dat");  
            ObjectInputStream b = new ObjectInputStream(f);  
            RSAPublicKey pbk = (RSAPublicKey) b.readObject();  
            BigInteger e = pbk.getPublicExponent();  
            BigInteger n = pbk.getModulus();  
            // 获取明文m  
            byte ptext[] = s.getBytes("UTF-8");  
            BigInteger m = new BigInteger(ptext);  
            // 计算密文c  
            BigInteger c = m.modPow(e, n);  
            // 保存密文  
            String ciperTxt = c.toString();  
            return ciperTxt; 
        }
        
        /**
         * 私钥解密, 一般调用者传递密文, 从本地存储读取私钥进行解密
         * @param ciperTxt
         * @return
         * @throws Exception
         */
        public static String privDecrypt(String ciperTxt) throws Exception {  
            BigInteger c = new BigInteger(ciperTxt);  
            // 读取私钥  
            FileInputStream f = new FileInputStream("d:/privatekey.dat");  
            ObjectInputStream b = new ObjectInputStream(f);  
            RSAPrivateKey prk = (RSAPrivateKey) b.readObject();  
            BigInteger d = prk.getPrivateExponent();  
            // 获取私钥参数及解密  
            BigInteger n = prk.getModulus();  
            BigInteger m = c.modPow(d, n);  
            // 显示解密结果  
            byte[] mt = m.toByteArray();  
            String plainTxt = new String(Base64.decodeBase64(mt),"UTF-8");
            return plainTxt;
        }  
        public static void main(String args[]) {  
            try {  
                // generateKey();  
                String ciperTxt = pubEncrypt("测试大中华123区");
                System.out.println("公钥加密密文:" + ciperTxt);
                System.out.println("私钥解密:" + privDecrypt(ciperTxt));  
            } catch (Exception e) {  
                System.out.println(e.toString());  
            }  
        }
    }

    PS:关于哪个加密、哪个解密的问题,记住以下原则即可(这个是从合理性角度,不是纯技术角度):

    既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证

    在java的安全体系范围内,有三个应该掌握的组件:Key Manager, Trust Manager 和Key Store。

    Key Manager是用于管理证书的,这意味着在一个会话的建立过程中,Key Manager控制发送哪个证书给对方。参考:http://docs.oracle.com/javase/7/docs/api/javax/net/ssl/X509ExtendedKeyManager.html

    Trust Manager用于管理远程证书,这意味着在一个会话的建立过程中,Trust Manager控制来自对方的哪个证书是可信的,如果服务端不认证客户端,则不需要;而客户端一般都要认证服务端,所以需要用到。参考:http://docs.oracle.com/javase/7/docs/api/javax/net/ssl/X509ExtendedTrustManager.html

    Key Store是证书的java封装实现。java要求所有的证书要么转换为java专有的二进制格式,要么使用PKCS#12格式,这些格式都是使用Key Store管理的。对于服务器证书,可以使用专有格式,对于客户端的键/证书对,可以使用PKCS#12格式。参考:http://docs.oracle.com/javase/7/docs/api/java/security/KeyStore.html

  • 相关阅读:
    centos8网络连接(1)虚拟机网卡和网络编辑器设置
    centos7离线安装ruby
    centos7安装ruby-2.6.5,简单快捷的下载与安装方式
    redis 4.0.13 -- 集群模式
    活了
    世界无我
    markdown_test
    关于mimikatz在webshell运行
    可用性自动化V3
    关于sqlmap常用
  • 原文地址:https://www.cnblogs.com/zhjh256/p/6104537.html
Copyright © 2011-2022 走看看