zoukankan      html  css  js  c++  java
  • [Linux] 使用openssl实现RSA非对称加密

    简单定义:公钥和私钥,加密和解密使用的是两个不同的密钥,所以是非对称

    系统:ubuntu 14.04

    软件:openssl java php

    生成公钥私钥

    使用命令生成私钥:

    openssl genrsa -out rsa_private_key.pem 1024
    

    参数:genrsa 生成密钥   -out 输出到文件  rsa_private_key.pem 文件名  1024 长度

    从私钥中提取公钥:

    openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
    

    参数: rsa 提取公钥  -in 从文件中读入  rsa_private_key.pem 文件名   -pubout  输出   -out 到文件  rsa_public_key.pem  文件名

    shell加解密

    新建一个readme.txt 内容是taoshihan

    使用公钥加密:

    openssl rsautl -encrypt -in readme.txt -inkey rsa_public_key.pem -pubin -out hello.en 
    

    参数: rsautl 加解密  -encrypt 加密  -in 从文件输入  readme.txt 文件名  -inkey  输入的密钥  rsa_public_key.pem  上一步生成的公钥  -pubin 表名输入是公钥文件  -out输出到文件  hello.en 输出文件名

    使用私钥解密:

    openssl rsautl -decrypt -in hello.en -inkey rsa_private_key.pem -out hello.de
    

    参数: -decrypt 解密  -in 从文件输入 hello.en 上一步生成的加密文件  -inkey 输入的密钥 rsa_private_key.pem 上一步生成的私钥  -out输出到文件  hello.de 输出的文件名

    cat hello.de // taoshihan

    php加解密

    $profile="taoshihan";
    echo "加密前:{$profile}
    ";
    //公钥加密
    $public_key=file_get_contents("rsa_public_key.pem");
    $pub_key = openssl_pkey_get_public($public_key); 
    openssl_public_encrypt($profile,$encrypted,$pub_key);
    $encrypted=base64_encode($encrypted);//因为加密后是乱码,所以base64一下
    echo "加密后:
    ";
    echo $encrypted."
    ";
    
    //私钥解密
    $private_key=file_get_contents("rsa_private_key.pem");
    $pi_key =  openssl_pkey_get_private($private_key); 
    openssl_private_decrypt(base64_decode($encrypted),$decrypted,$pi_key);
    echo "解密后:
    ";
    echo $decrypted."
    ";

    新建rsa.php的文件

    执行后结果:

    加密前:taoshihan
    加密后:
    ShjsdlTceurVfO0ocENqHGl9RXrQRm3vuprqchhuVOdX1ldJC2O2sIvjjpQfPWOkF1WA+tqdyIl9YJQ0/2DqAp4zaqI1TCNsXduGn2iUZQ88g7B5eSI7r/iWKcX527pLe95EBvFMw/D65tlYscI5RClcp3KrOw2fqDQZ3D3nKAI=
    解密后:
    taoshihan
    

    java加解密:

    准备jar包 bcprov-ext-jdk15on-156.jar

    wget http://www.bouncycastle.org/download/bcprov-ext-jdk15on-156.jar
    

    RSAEncrypt.java 文件

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.FileInputStream;  
    import java.io.FileOutputStream;
    import java.security.InvalidKeyException;
    import java.security.KeyFactory;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    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.security.KeyFactory;
    import java.security.interfaces.RSAPrivateKey;
    import java.security.spec.RSAPrivateKeySpec;
    
    import org.bouncycastle.asn1.ASN1Sequence;
    import org.bouncycastle.asn1.pkcs.RSAPrivateKeyStructure;
    
    import javax.crypto.BadPaddingException;
    import javax.crypto.Cipher;
    import javax.crypto.IllegalBlockSizeException;
    import javax.crypto.NoSuchPaddingException;
    
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    
    import sun.misc.BASE64Decoder;
    import sun.misc.BASE64Encoder;
    
    public class RSAEncrypt {
        /**
         * 私钥
         */
        private RSAPrivateKey privateKey;
    
        /**
         * 公钥
         */
        private RSAPublicKey publicKey;
        
        /**
         * 字节数据转字符串专用集合
         */
        private static final char[] HEX_CHAR= {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
        
    
        /**
         * 获取私钥
         * @return 当前的私钥对象
         */
        public RSAPrivateKey getPrivateKey() {
            return privateKey;
        }
    
        /**
         * 获取公钥
         * @return 当前的公钥对象
         */
        public RSAPublicKey getPublicKey() {
            return publicKey;
        }
    
        /**
         * 随机生成密钥对
         */
        public void genKeyPair(){
            KeyPairGenerator keyPairGen= null;
            try {
                keyPairGen= KeyPairGenerator.getInstance("RSA");
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            keyPairGen.initialize(1024, new SecureRandom());
            KeyPair keyPair= keyPairGen.generateKeyPair();
            this.privateKey= (RSAPrivateKey) keyPair.getPrivate();
            this.publicKey= (RSAPublicKey) keyPair.getPublic();
        }
    
        /**
         * 从文件中输入流中加载公钥
         * @param in 公钥输入流
         * @throws Exception 加载公钥时产生的异常
         */
        public void loadPublicKey(InputStream in) throws Exception{
            try {
                BufferedReader br= new BufferedReader(new InputStreamReader(in));
                String readLine= null;
                StringBuilder sb= new StringBuilder();
                while((readLine= br.readLine())!=null){
                    if(readLine.charAt(0)=='-'){
                        continue;
                    }else{
                        sb.append(readLine);
                        sb.append('
    ');
                    }
                }
                loadPublicKey(sb.toString());
            } catch (IOException e) {
                throw new Exception("公钥数据流读取错误");
            } catch (NullPointerException e) {
                throw new Exception("公钥输入流为空");
            }
        }
    
    
        /**
         * 从字符串中加载公钥
         * @param publicKeyStr 公钥数据字符串
         * @throws Exception 加载公钥时产生的异常
         */
        public void loadPublicKey(String publicKeyStr) throws Exception{
            try {
                BASE64Decoder base64Decoder= new BASE64Decoder();
                byte[] buffer= base64Decoder.decodeBuffer(publicKeyStr);
                KeyFactory keyFactory= KeyFactory.getInstance("RSA");
                X509EncodedKeySpec keySpec= new X509EncodedKeySpec(buffer);
                this.publicKey= (RSAPublicKey) keyFactory.generatePublic(keySpec);
            } catch (NoSuchAlgorithmException e) {
                throw new Exception("无此算法");
            } catch (InvalidKeySpecException e) {
                throw new Exception("公钥非法");
            } catch (IOException e) {
                throw new Exception("公钥数据内容读取错误");
            } catch (NullPointerException e) {
                throw new Exception("公钥数据为空");
            }
        }
    
        /**
         * 从文件中加载私钥
         * @param keyFileName 私钥文件名
         * @return 是否成功
         * @throws Exception 
         */
        public void loadPrivateKey(InputStream in) throws Exception{
            try {
                BufferedReader br= new BufferedReader(new InputStreamReader(in));
                String readLine= null;
                StringBuilder sb= new StringBuilder();
                while((readLine= br.readLine())!=null){
                    if(readLine.charAt(0)=='-'){
                        continue;
                    }else{
                        sb.append(readLine);
                        sb.append('
    ');
                    }
                }
                loadPrivateKey(sb.toString());
            } catch (IOException e) {
                throw new Exception("私钥数据读取错误");
            } catch (NullPointerException e) {
                throw new Exception("私钥输入流为空");
            }
        }
    
        public void loadPrivateKey(String privateKeyStr) throws Exception{
            try {
                BASE64Decoder base64Decoder= new BASE64Decoder();
                byte[] buffer= base64Decoder.decodeBuffer(privateKeyStr);
    
                RSAPrivateKeyStructure asn1PrivKey = new RSAPrivateKeyStructure((ASN1Sequence) ASN1Sequence.fromByteArray(buffer));
                RSAPrivateKeySpec rsaPrivKeySpec = new RSAPrivateKeySpec(asn1PrivKey.getModulus(), asn1PrivKey.getPrivateExponent());
                KeyFactory keyFactory= KeyFactory.getInstance("RSA");
                RSAPrivateKey  priKey=(RSAPrivateKey) keyFactory.generatePrivate(rsaPrivKeySpec);
                this.privateKey=priKey;
    
                // PKCS8EncodedKeySpec keySpec= new PKCS8EncodedKeySpec(buffer);
                // KeyFactory keyFactory= KeyFactory.getInstance("RSA");
                //this.privateKey= (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
            } catch (NoSuchAlgorithmException e) {
                throw new Exception("无此算法");
            } catch (InvalidKeySpecException e) {
                throw new Exception("私钥非法");
            } catch (IOException e) {
                throw new Exception("私钥数据内容读取错误");
            } catch (NullPointerException e) {
                throw new Exception("私钥数据为空");
            }
        }
    
        /**
         * 加密过程
         * @param publicKey 公钥
         * @param plainTextData 明文数据
         * @return
         * @throws Exception 加密过程中的异常信息
         */
        public byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData) throws Exception{
            if(publicKey== null){
                throw new Exception("加密公钥为空, 请设置");
            }
            Cipher cipher= null;
            try {
                cipher= Cipher.getInstance("RSA/ECB/PKCS1Padding", new BouncyCastleProvider());
                cipher.init(Cipher.ENCRYPT_MODE, publicKey);
                byte[] output= cipher.doFinal(plainTextData);
                return output;
            } catch (NoSuchAlgorithmException e) {
                throw new Exception("无此加密算法");
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
                return null;
            }catch (InvalidKeyException e) {
                throw new Exception("加密公钥非法,请检查");
            } catch (IllegalBlockSizeException e) {
                throw new Exception("明文长度非法");
            } catch (BadPaddingException e) {
                throw new Exception("明文数据已损坏");
            }
        }
    
        /**
         * 解密过程
         * @param privateKey 私钥
         * @param cipherData 密文数据
         * @return 明文
         * @throws Exception 解密过程中的异常信息
         */
        public byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData) throws Exception{
            if (privateKey== null){
                throw new Exception("解密私钥为空, 请设置");
            }
            Cipher cipher= null;
            try {
                cipher= Cipher.getInstance("RSA/ECB/PKCS1Padding", new BouncyCastleProvider());
                cipher.init(Cipher.DECRYPT_MODE, privateKey);
                byte[] output= cipher.doFinal(cipherData);
                return output;
            } catch (NoSuchAlgorithmException e) {
                throw new Exception("无此解密算法");
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
                return null;
            }catch (InvalidKeyException e) {
                throw new Exception("解密私钥非法,请检查");
            } catch (IllegalBlockSizeException e) {
                throw new Exception("密文长度非法");
            } catch (BadPaddingException e) {
                throw new Exception("密文数据已损坏");
            }        
        }
    
        
        /**
         * 字节数据转十六进制字符串
         * @param data 输入数据
         * @return 十六进制内容
         */
        public static String byteArrayToString(byte[] data){
            StringBuilder stringBuilder= new StringBuilder();
            for (int i=0; i<data.length; i++){
                //取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移
                stringBuilder.append(HEX_CHAR[(data[i] & 0xf0)>>> 4]);
                //取出字节的低四位 作为索引得到相应的十六进制标识符
                stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);
                if (i<data.length-1){
                    stringBuilder.append(' ');
                }
            }
            return stringBuilder.toString();
        }
    
    
        public static void main(String[] args){
            RSAEncrypt rsaEncrypt= new RSAEncrypt();
            //加载公钥
            try {
                rsaEncrypt.loadPublicKey(new FileInputStream("rsa_public_key.pem"));
                System.out.println("加载公钥成功");
            } catch (Exception e) {
                System.err.println(e.getMessage());
                System.err.println("加载公钥失败");
            }
    
            //加载私钥
            try {
                rsaEncrypt.loadPrivateKey(new FileInputStream("rsa_private_key.pem"));
                System.out.println("加载私钥成功");
            } catch (Exception e) {
                System.err.println(e.getMessage());
                System.err.println("加载私钥失败");
            }
    
            //测试字符串
            String encryptStr= "taoshihan";
            System.out.println("加密前:");
            System.out.println(encryptStr);
            try {
                //加密
                byte[] cipher = rsaEncrypt.encrypt(rsaEncrypt.getPublicKey(), encryptStr.getBytes());
                //解密
                byte[] plainText = rsaEncrypt.decrypt(rsaEncrypt.getPrivateKey(), cipher);
                BASE64Encoder encode = new BASE64Encoder(); 
                String buffer= encode.encode(cipher);
                System.out.println("加密后:");
                System.out.println(new String(buffer));
                System.out.println("解密后:");
                System.out.println(new String(plainText));
            } catch (Exception e) {
                System.err.println(e.getMessage());
            }
        }
    }

    带包编译和执行

    javac -cp bcprov-ext-jdk15on-156.jar RSAEncrypt.java 
    java -cp .:bcprov-ext-jdk15on-156.jar RSAEncrypt
    

    执行结果:

    加载公钥成功
    加载私钥成功
    加密前:
    taoshihan
    加密后:
    Tt1p5XnamZkkVjGn1cVgEIb7U+CP27Xw93JQQUZyc2Up/rJL4Mx+dA8mxkva1a/I64sUTb7QD//8
    gbss4bZY/DHrLityTt2/QjjQUFYD5/Aa1m1QKUBulWY4/C5so5dm6wrRnjolsIFUbY+RfH4B6hp1
    taQGBRDum/xEX6OsJ9I=
    解密后:
    taoshihan
    

    shell使用公钥加密,php使用私钥解密

    shell:

    openssl rsautl -encrypt -in readme.txt -inkey rsa_public_key.pem -pubin|base64
    
    加密后的字符串
    
    lNJ50ODiofcp+adrtAI943HOsjdDTg3UMfUkt0NI7DhUjxCM+NAlBH08WVQRtYK9W8ZoQOta3QH6
    PzmJT4WsI0yfNGiUWYgoYgSOtPURSQMbaCt3DM2Y5mEKqzbKLrhN+S+9Jrtmef1VuBUes8wN6rOD
    UHxI+vDwQ+utRJRRo9U=
    

    php:

    <?php
    $encrypted="lNJ50ODiofcp+adrtAI943HOsjdDTg3UMfUkt0NI7DhUjxCM+NAlBH08WVQRtYK9W8ZoQOta3QH6
    PzmJT4WsI0yfNGiUWYgoYgSOtPURSQMbaCt3DM2Y5mEKqzbKLrhN+S+9Jrtmef1VuBUes8wN6rOD
    UHxI+vDwQ+utRJRRo9U=";
    echo $encrypted."
    ";
    
    //私钥解密
    $private_key=file_get_contents("rsa_private_key.pem");
    $pi_key =  openssl_pkey_get_private($private_key); 
    openssl_private_decrypt(base64_decode($encrypted),$decrypted,$pi_key);
    echo "解密后:
    ";
    echo $decrypted."
    ";

    执行结果:

    lNJ50ODiofcp+adrtAI943HOsjdDTg3UMfUkt0NI7DhUjxCM+NAlBH08WVQRtYK9W8ZoQOta3QH6
    PzmJT4WsI0yfNGiUWYgoYgSOtPURSQMbaCt3DM2Y5mEKqzbKLrhN+S+9Jrtmef1VuBUes8wN6rOD
    UHxI+vDwQ+utRJRRo9U=
    解密后:
    taoshihan

    java使用公钥加密,php解密:

    拿上一步java生成的加密后字符串

    <?php
    $encrypted="Tt1p5XnamZkkVjGn1cVgEIb7U+CP27Xw93JQQUZyc2Up/rJL4Mx+dA8mxkva1a/I64sUTb7QD//8
    gbss4bZY/DHrLityTt2/QjjQUFYD5/Aa1m1QKUBulWY4/C5so5dm6wrRnjolsIFUbY+RfH4B6hp1
    taQGBRDum/xEX6OsJ9I=";
    echo $encrypted."
    ";
    
    //私钥解密
    $private_key=file_get_contents("rsa_private_key.pem");
    $pi_key =  openssl_pkey_get_private($private_key); 
    openssl_private_decrypt(base64_decode($encrypted),$decrypted,$pi_key);
    echo "解密后:
    ";
    echo $decrypted."
    ";

    执行结果:

    Tt1p5XnamZkkVjGn1cVgEIb7U+CP27Xw93JQQUZyc2Up/rJL4Mx+dA8mxkva1a/I64sUTb7QD//8
    gbss4bZY/DHrLityTt2/QjjQUFYD5/Aa1m1QKUBulWY4/C5so5dm6wrRnjolsIFUbY+RfH4B6hp1
    taQGBRDum/xEX6OsJ9I=
    解密后:
    taoshihan
    

      

      

     

  • 相关阅读:
    luogu P3295 [SCOI2016]萌萌哒
    luogu P4916 魔力环
    CF997C Sky Full of Stars
    CF961G Partitions
    android屏蔽软键盘并且显示光标
    设置和获取Android中各种音量
    自定义广播
    发送广播
    android取高度
    Java数字格式化
  • 原文地址:https://www.cnblogs.com/taoshihan/p/6340854.html
Copyright © 2011-2022 走看看