[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}\n"; //公鑰加密 $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 "加密后:\n"; echo $encrypted."\n";//私鑰解密 $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 "解密后:\n"; echo $decrypted."\n";新建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.jarRSAEncrypt.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('\r');}}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('\r');}}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."\n";//私鑰解密 $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 "解密后:\n"; echo $decrypted."\n";執行結果:
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."\n";//私鑰解密 $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 "解密后:\n"; echo $decrypted."\n";執行結果:
Tt1p5XnamZkkVjGn1cVgEIb7U+CP27Xw93JQQUZyc2Up/rJL4Mx+dA8mxkva1a/I64sUTb7QD//8 gbss4bZY/DHrLityTt2/QjjQUFYD5/Aa1m1QKUBulWY4/C5so5dm6wrRnjolsIFUbY+RfH4B6hp1 taQGBRDum/xEX6OsJ9I= 解密后: taoshihan
?
?
轉載于:https://www.cnblogs.com/taoshihan/p/6340854.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的[Linux] 使用openssl实现RSA非对称加密的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Struts.xml配置解释
- 下一篇: DOM获取元素位置的三大系列offset