openssl加密文件
1. PHP對稱加密-AES
對稱加解密演算法中,當前最為安全的是 AES 加密演算法(以前應該是是 DES 加密演算法),PHP 提供了兩個可以用於 AES 加密演算法的函數簇: Mcrypt 和 OpenSSL 。
其中 Mcrypt 在 PHP 7.1.0 中被棄用(The Function Mycrypt is Deprecated),在 PHP 7.2.0 中被移除,所以即可起你應該使用 OpenSSL 來實現 AES 的數據加解密。
在一些場景下,我們不能保證兩套通信系統都使用了相函數簇去實現加密演算法,可能 siteA 使用了最新的 OpenSSL 來實現了 AES 加密,但作為第三方服務的 siteB 可能仍在使用 Mcrypt 演算法,這就要求我們必須清楚 Mcrypt 同 OpenSSL 之間的差異,以便保證數據加解密的一致性。
下文中我們將分別使用 Mcrypt 和 OpenSSL 來實現 AES-128/192/256-CBC 加解密,二者同步加解密的要點為:
協同好以上兩點,就可以讓 Mcrypt 和 OpenSSL 之間一致性的對數據進行加解密。
AES 是當前最為常用的安全對稱加密演算法,關於對稱加密這里就不在闡述了。
AES 有三種演算法,主要是對數據塊的大小存在區別:
AES-128:需要提供 16 位的密鑰 key
AES-192:需要提供 24 位的密鑰 key
AES-256:需要提供 32 位的密鑰 key
AES 是按數據塊大小(128/192/256)對待加密內容進行分塊處理的,會經常出現最後一段數據長度不足的場景,這時就需要填充數據長度到加密演算法對應的數據塊大小。
主要的填充演算法有填充 NUL("0") 和 PKCS7,Mcrypt 默認使用的 NUL("0") 填充演算法,當前已不被推薦,OpenSSL 則默認模式使用 PKCS7 對數據進行填充並對加密後的數據進行了 base64encode 編碼,所以建議開發中使用 PKCS7 對待加密數據進行填充,已保證通用性(alipay sdk 中雖然使用了 Mcrypt 加密簇,但使用 PKCS7 演算法對數據進行了填充,這樣在一定程度上親和了 OpenSSL 加密演算法)。
Mcrypt 的默認填充演算法。NUL 即為 Ascii 表的編號為 0 的元素,即空元素,轉移字元是 " ",PHP 的 pack 打包函數在 'a' 模式下就是以 NUL 字元對內容進行填充的,當然,使用 " " 手動拼接也是可以的。
OpenSSL的默認填充演算法。下面我們給出 PKCS7 填充演算法 PHP 的實現:
默認使用 NUL(" ") 自動對待加密數據進行填充以對齊加密演算法數據塊長度。
獲取 mcrypt 支持的演算法,這里我們只關注 AES 演算法。
注意:mcrypt 雖然支持 AES 三種演算法,但除 MCRYPT_RIJNDAEL_128 外, MCRYPT_RIJNDAEL_192/256 並未遵循 AES-192/256 標准進行加解密的演算法,即如果你同其他系統通信(java/.net),使用 MCRYPT_RIJNDAEL_192/256 可能無法被其他嚴格按照 AES-192/256 標準的系統正確的數據解密。官方文檔頁面中也有人在 User Contributed Notes 中提及。這里給出如何使用 mcrpyt 做標注的 AES-128/192/256 加解密
即演算法統一使用 MCRYPT_RIJNDAEL_128 ,並通過 key 的位數 來選定是以何種 AES 標准做的加密,iv 是建議添加且建議固定為16位(OpenSSL的 AES加密 iv 始終為 16 位,便於統一對齊),mode 選用的 CBC 模式。
mcrypt 在對數據進行加密處理時,如果發現數據長度與使用的加密演算法的數據塊長度未對齊,則會自動使用 " " 對待加密數據進行填充,但 " " 填充模式已不再被推薦,為了與其他系統有更好的兼容性,建議大家手動對數據進行 PKCS7 填充。
openssl 簇加密方法更為簡單明確,mcrypt 還要將加密演算法分為 cipher + mode 去指定,openssl 則只需要直接指定 method 為 AES-128-CBC,AES-192-CBC,AES-256-CBC 即可。且提供了三種數據處理模式,即 默認模式 0 / OPENSSL_RAW_DATA / OPENSSL_ZERO_PADDING 。
openssl 默認的數據填充方式是 PKCS7,為兼容 mcrpty 也提供處理 "0" 填充的數據的模式,具體為下:
options 參數即為重要,它是兼容 mcrpty 演算法的關鍵:
options = 0 : 默認模式,自動對明文進行 pkcs7 padding,且數據做 base64 編碼處理。
options = 1 : OPENSSL_RAW_DATA,自動對明文進行 pkcs7 padding, 且數據未經 base64 編碼處理。
options = 2 : OPENSSL_ZERO_PADDING,要求待加密的數據長度已按 "0" 填充與加密演算法數據塊長度對齊,即同 mcrpty 默認填充的方式一致,且對數據做 base64 編碼處理。注意,此模式下 openssl 要求待加密數據已按 "0" 填充好,其並不會自動幫你填充數據,如果未填充對齊,則會報錯。
故可以得出 mcrpty簇 與 openssl簇 的兼容條件如下:
建議將源碼復制到本地運行,根據運行結果更好理解。
1.二者使用的何種填充演算法。
2.二者對數據是否有 base64 編碼要求。
3.mcrypt 需固定使用 MCRYPT_RIJNDAEL_128,並通過調整 key 的長度 16, 24,32 來實現 ase-128/192/256 加密演算法。
2. 如何把openssl生成rsa加密的私鑰顯現可讀
首先需要進入openssl的交互界面,在命令行了輸入openssl即可;
1)生成RSA私鑰:
genrsa -out rsa_private_key.pem 1024
該命令會生成1024位的私鑰,生成成功的界面如下:
此時我們就可以在當前路徑下看到rsa_private_key.pem文件了。
2)把RSA私鑰轉換成PKCS8格式
輸入命令pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM –nocrypt,並回車
得到生成功的結果,這個結果就是PKCS8格式的私鑰,如下圖:
3) 生成SA公鑰
輸入命令rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem,並回車,
得到生成成功的結果,如下圖:
此時,我們可以看到一個文件名為rsa_public_key.pem的文件,打開它,可以看到-----BEGIN PUBLIC KEY-----開頭,
-----END PUBLIC KEY-----結尾的沒有換行的字元串,這個就是公用
3. 關於openssl AES/ECB/PKCS5Padding加密 求助
ecb加密方式,其實底層是調用AES_encrypt介面,你可以去看源碼。
下面的代碼給你一個參考,只不過,我是在調用aes_encrypt外面,自己嚴格控制了in和out的長度,out的長度大於in,並且必須是大於等於16的整數倍。
4. Linux裡面openssl作用是什麼
主要是用來安全的。
openssl命令 – 加密演算法
openSSL是一個強大的安全套接字層密碼庫,囊括主要的密碼演算法、常用的密鑰和證書封裝管理功能及SSL協議,並提供豐富的應用程序供測試或其它目的使用。對應的命令就是openssl命令,用於加密演算法。《Linux就該這么學》
語法格式:openssl [參數]
舉例子:
用SHA1演算法計算文件file.txt的哈西值,輸出到stdout:
# openssl dgst -sha1 file.txt
5. 如何用C語言來使用openssl rsa進行公鑰加密,已有公鑰和明文
1. 本程序使用2048位密鑰對,每次加密時,原始數據的最大長度為245位元組,加密後的密文長度為256位元組.(採用打PADDING 的加密方式)
2. 如果所加密數據長度大於245位元組,請分多次加密,後將密文按順序存儲;解密時,每次讀取256位元組,進行解密,將解密後的數據依次按順序存儲,即可還原原始數據.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#define OPENSSLKEY "test.key"
#define PUBLICKEY "test_pub.key"
#define BUFFSIZE 1024
char *my_encrypt(char *str, char *path_key); //加密
char *my_decrypt(char *str, char *path_key); //解密
int main(void)
{
char *source = "i like dancing !!!";
char *ptf_en, *ptf_de;
printf("source is :%s\n", source);
//1.加密
ptf_en = my_encrypt(source, PUBLICKEY);
if (ptf_en == NULL){
return 0;
}else{
printf("ptf_en is :%s\n", ptf_en);
}
//2.解密
ptf_de = my_decrypt(ptf_en, OPENSSLKEY);
if (ptf_de == NULL){
return 0;
}else{
printf("ptf_de is :%s\n", ptf_de);
}
if(ptf_en) free(ptf_en);
if(ptf_de) free(ptf_de);
return 0;
}
//加密
char *my_encrypt(char *str, char *path_key)
{
char *p_en = NULL;
RSA *p_rsa = NULL;
FILE *file = NULL;
int lenth = 0; //flen為源文件長度, rsa_len為秘鑰長度
//1.打開秘鑰文件
if((file = fopen(path_key, "rb")) == NULL)
{
perror("fopen() error 111111111 ");
goto End;
}
//2.從公鑰中獲取 加密的秘鑰
if((p_rsa = PEM_read_RSA_PUBKEY(file, NULL,NULL,NULL )) == NULL)
{
ERR_print_errors_fp(stdout);
goto End;
}
lenth = strlen(str);
p_en = (char *)malloc(256);
if(!p_en)
{
perror("malloc() error 2222222222");
goto End;
}
memset(p_en, 0, 256);
//5.對內容進行加密
if(RSA_public_encrypt(lenth, (unsigned char*)str, (unsigned char*)p_en, p_rsa, RSA_PKCS1_PADDING) < 0)
{
perror("RSA_public_encrypt() error 2222222222");
goto End;
}
End:
//6.釋放秘鑰空間, 關閉文件
if(p_rsa) RSA_free(p_rsa);
if(file) fclose(file);
return p_en;
}
//解密
char *my_decrypt(char *str, char *path_key)
{
char *p_de = NULL;
RSA *p_rsa = NULL;
FILE *file = NULL;
//1.打開秘鑰文件
file = fopen(path_key, "rb");
if(!file)
{
perror("fopen() error 22222222222");
goto End;
}
//2.從私鑰中獲取 解密的秘鑰
if((p_rsa = PEM_read_RSAPrivateKey(file, NULL,NULL,NULL )) == NULL)
{
ERR_print_errors_fp(stdout);
goto End;
}
p_de = (char *)malloc(245);
if(!p_de)
{
perror("malloc() error ");
goto End;
}
memset(p_de, 0, 245);
//5.對內容進行加密
if(RSA_private_decrypt(256, (unsigned char*)str, (unsigned char*)p_de, p_rsa, RSA_PKCS1_PADDING) < 0)
{
perror("RSA_public_encrypt() error ");
goto End;
}
End:
//6.釋放秘鑰空間, 關閉文件
if(p_rsa) RSA_free(p_rsa);
if(file) fclose(file);
return p_de;
}
6. 如何利用OpenSSL庫進行RSA加密和解密
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<openssl/rsa.h>
#include<openssl/engine.h>
intmain(intargc,char*argv[])
{
printf("openssl_testbegin ");
RSA*rsa=NULL;
charoriginstr[]="hello ";//這是我們需要加密的原始數據
//allocateRSAstructure,首先需要申請一個RSA結構題用於存放生成的公私鑰,這里rsa就是這個結構體的指針
rsa=RSA_new();
if(rsa==NULL)
{
printf("RSA_newfailed ");
return-1;
}
//generateRSAkeys
BIGNUM*exponent;
exponent=BN_new();//生成RSA公私鑰之前需要選擇一個奇數(oddnumber)來用於生成公私鑰
if(exponent==NULL)
{
printf("BN_newfailed ");
gotoFAIL1;
}
if(0==BN_set_word(exponent,65537))//這里選擇奇數65537
{
printf("BN_set_wordfailed ");
gotoFAIL1;
}
//這里molus的長度選擇4096,小於1024的molus長度都是不安全的,容易被破解
if(0==RSA_generate_key_ex(rsa,4096,exponent,NULL))
{
printf("RSA_generate_key_exfailed ");
gotoFAIL;
}
char*cipherstr=NULL;
//分配一段空間用於存儲加密後的數據,這個空間的大小由RSA_size函數根據rsa算出
cipherstr=malloc(RSA_size(rsa));
if(cipherstr==NULL)
{
printf("malloccipherstrbuffailed ");
gotoFAIL1;
}
//下面是實際的加密過程,最後一個參數paddingtype,有以下幾種。
/*
RSA_PKCS1_PADDINGPKCS#1v1.5padding..
RSA_PKCS1_OAEP_PADDING
EME-OAEPasdefinedinPKCS#1v2.0withSHA-1,..
RSA_SSLV23_PADDING
PKCS#1v1.5paddingwithanSSL-.
RSA_NO_PADDING
RawRSAencryption.ntheapplicationcode..
*/
//這里首先用公鑰進行加密,選擇了RSA_PKCS1_PADDING
if(RSA_size(rsa)!=RSA_public_encrypt(strlen(originstr)+1,originstr,cipherstr,rsa,RSA_PKCS1_PADDING))
{
printf("encryptionfailure ");
gotoFAIL2;
}
printf("theoriginalstringis%s ",originstr);
printf("theencryptedstringis%s ",cipherstr);
//Now,let'
//下面來用私鑰解密,首先需要一個buffer用於存儲解密後的數據,這個buffer的長度要足夠(小於RSA_size(rsa))
//這里分配一個長度為250的字元數組,應該是夠用的。
chardecrypted_str[250];
intdecrypted_len;
if(-1=(decrypted_len=RSA_private_decrypt(256,cipherstr,decrypted_str,rsa,RSA_PKCS1_PADDING)))
{
printf("decryptionfailure ");
gotoFAIL2;
}
printf("decryptedstringlengthis%d,decryped_stris%s ",decrypted_len,decrypted_str);
FAIL2:
free(cipherstr);
FAIL1:
BN_free(exponent);
FAIL:
RSA_free(rsa);
return0;
}
以上是源代碼,下面使用下面的編譯命令在源碼所在路徑下生成可執行文件
gcc *.c -o openssl_test -lcrypto -ldl -L/usr/local/ssl/lib -I/usr/local/ssl/include
其中,-lcrypto和-ldl是必須的,前者是OpenSSL中的加密演算法庫,後者是用於成功載入動態庫。
7. OpenSSL之3DES用法
3DES(或稱為Triple DES)是三重數據加密演算法(TDEA,Triple Data Encryption Algorithm)塊密碼的通稱。它相當於是對每個數據塊應用三次DES加密演算法。由於計算機運算能力的增強,原版DES密碼的密鑰長度變得容易被暴力破解;3DES即是設計用來提供一種相對簡單的方法,即通過增加DES的密鑰長度來避免類似的攻擊,而不是設計一種全新的塊密碼演算法。
其具體實現如下:設Ek()和Dk()代表DES演算法的加密和解密過程,K代表DES演算法使用的密鑰,P代表明文,C代表密文,這樣:
3DES加密過程為:C=Ek3(Dk2(Ek1(P)))
3DES解密過程為:P=Dk1(EK2(Dk3(C)))
本文假設你已經安裝好了OpenSSL,並且持有一份1.1.1的源碼。
3DES相關的頭文件在des.h中、源文件在crypto/des目錄中。
# define DES_ENCRYPT 1
# define DES_DECRYPT 0
這里定義了加密和解密的類型。
typedef unsigned int DES_LONG;
這個結構定義了DES的密鑰上下文。相關欄位含義:
ks —— 16輪子密鑰。
在1.1.1中,大多數的數據結構已經不再向使用者開放,從封裝的角度來看,這是更合理的。如果你在頭文件中找不到結構定義,不妨去源碼中搜一搜。
void DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output,
DES_key_schele *ks1, DES_key_schele *ks2,
DES_key_schele *ks3, int enc);
使用電子密碼本方式加解密一個分組。
ks1、ks2、ks3分別為傳入的三個64位密鑰。
其內部實現為:
可以看到內部使用了DES_encrypt3()這個內部分組加密函數,並且傳入了3個密鑰。
我們繼續來看DES_encrypt3()是如何利用這3個密鑰的。
void DES_encrypt3(DES_LONG *data, DES_key_schele *ks1,
DES_key_schele *ks2, DES_key_schele *ks3)
其內部實現為:
可以看到內部又繼續使用了DES_encrypt2()這個分組加密函數。沒有必要再繼續解開DES_encrypt2()了,因為它主要根據密鑰做分組的加解密處理。
關於三個密鑰的利用關系,在DES_encrypt3()中主要是做三次疊加運算:
使用第一個密鑰做分組加密運算。
使用第二個密鑰做分組解密運算。
使用第三個密鑰做分組加密運算。
3DES的疊加運算,根據密鑰的組合關系,經常又表現為以下模式:
void DES_ede3_cbc_encrypt(const unsigned char *input, unsigned char *output,
long length,
DES_key_schele *ks1, DES_key_schele *ks2,
DES_key_schele *ks3, DES_cblock *ivec, int enc);
使用密文分組鏈加解密。
參數ivec為初使化向量,在本函數返回時會被更新,可用於下一次分組運算。
註:
從源碼實現來看,雖然DES_ede3_cbc_encrypt()自身支持明文長度多於一個分組的計算,但是卻沒有處理填充,所以從統一封裝來看,建議開發者在使用這個函數時,同DES_ecb_encrypt()的用法一樣,傳入單個分組。
下面這個例子演示了使用普通DES加密,3DES的DES的兼容模式解密(即3個密鑰完全相同)。
輸出:
f8a8707fea7d45cd
3132333435363738