㈠ openssl 中调用哪个函数实现16字节des密钥cbc方式加密数据
使用OpenSSL的EVP接口实现des128加密的逻辑流程如下:
// 初始化上下文数据结构,指定算法(EVP_des_ede_cbc)、密钥(key)、初始化向量(initVector)
//
EVP_CIPHER_CTX_init(&ctx);
EVP_EncryptInit_ex(&ctx, EVP_des_ede_cbc(), NULL, key, initVector);
......
// 加数的中间过程调用EVP_EncryptUpdate,pInBuffer、inSize指定要加密的明文和长度。
// 函数从pOutBuffer,outSize中返回加密后的密文和长度。
// 可以反复调用该API加密多个数据块。注意所有EVP函数是失败时返回0值。
//
ret = EVP_EncryptUpdate(&ctx, pOutBuffer, &outSize, pInBuffer, inSize);
if (0 == ret) goto ErrorExit;
......
// 在所有数据块加密完成后调用Final函数取得最后的对齐数据。
//
ret = EVP_EncryptFinal_ex(&ctx, pOutBuffer, &outSize);
if (0 == ret) goto ErrorExit;
......
// 最后返回的时候别忘了释放资源。
ErrorExit:
EVP_CIPHER_CTX_cleanup(&ctx);
return ret;
解密过程与上面一样,只是中间调用的函数分别变成EVP_DecryptInit_ex、EVP_DecryptUpdate和EVP_DecryptFinal_ex。OpenSSL EVP接口的相关说明可以去查官方文档或请教网络老师。
㈡ 对于加密的总结(AES,RSA)
跟第三方联调的时候会碰到各种加密算法,所以总结一下。
AES不是将拿到的明文一次性加密,而是分组加密,就是先将明文切分成长度相等的块,每块大小128bit,再对每一小块进行加密。那么问题就来了,并不是所有的原始明文串能被等分成128bit,例如原串大小200bit,那么第二个块只有72bit,所以就需要对第二个块进行填充处理,让第二个块的大小达到128bit。常见的填充模式有
不进行填充,要求原始加密串大小必须是128bit的整数倍;
假设块大小8字节,如果这个块跟8字节还差n个字节,那么就在原始块填充n,直到满8字节。例:块{1,2,3},跟8字节差了5个字节,那么补全后的结果{1,2,3,5,5,5,5,5}后面是五个5,块{1,2,3,..7}跟8字节差了1个字节,那么补全后就是{1,2,3,...,7,1},就是补了一个1。
如果恰好8字节又选择了PKCS5Padding填充方式呢?块{1,2,3...8}填充后变成{1,2,3...8,8...8},原串后面被补了8个8,这样做的原因是方便解密,只需要看最后一位就能算出原块的大小是多少。
跟PKCS5Padding的填充方式一样,不同的是,PKCS5Padding只是对8字节的进行填充,PKCS7Padding可以对1~256字节大小的block进行填充。openssl里aes的默认填充方式就是PKCS7Padding
AES有多种加密模式,包括:ECB,CBC,CTR,OCF,CFB,最常见的还是ECB和CBC模式。
最简单的一种加密模式,每个块进行独立加密,块与块之间加密互不影响,这样就能并行,效率高。
虽然这样加密很简单,但是不安全,如果两个块的明文一模一样,那么加密出来的东西也一模一样。
openssl的相关函数:
CBC模式中引入了一个新的概念,初始向量iv。iv的作用就是为了防止同样的明文块被加密成同样的内容。原理是第一个明文块跟初始向量做异或后加密,第二个块跟第一个密文块做异或再加密,依次类推,避免了同样的块被加密成同样的内容。
openssl相关函数:
敲黑板!! 所以跟第三方对接的时候,如果对面说他们用aes加密,务必对他们发起灵魂三问:
签名的作用是让接受方验证你传过去的数据没有被篡改;加密的作用是保证数据不被窃取。
原理:你有一个需要被验签的原串A。
步骤一:选择hash算法将A进行hash得到hash_a;
步骤二:将hash_a进行加密,得到加密值encrypt_a;
步骤三:将原串A和加密的encrypt_a发给第三方,第三方进行验签。第三方先解密encrypt_a,得到一个hash值hash_a1,然后对原串A使用同样的hash算法进行hash,得到的即为加密前的hash_a,如果hash_a = hash_a1, 那么验签成功。
rsa使用私钥对信息加密来做签名,使用公钥解密去验签。
openssl相关函数:
注意:两个函数中的m,是原串hash后的值,type表示生成m的算法,例如NID_sha256表示使用sha256对原串进行的hash,返回1为签名成功或者验签成功,-1位为失败。
再次敲黑板!! 所以如果第三方说使用rsa验签,要让对方告知他们的hash算法。
首先明确,私钥加密不等于签名。加密的时候,使用使用公钥加密,第三方使用你的私钥进行解密。
openssl里公钥加密函数为RSA_public_encrypt,私钥解密函数为RSA_private_decrypt,具体的可以自己去查看下官方文档。
rsa也涉及到了填充方式,所以对接的时候也要问清楚
在使用公钥进行加密时,会发现每次加密出的结果都不一样,但使用私钥加密时,每次的结果都一样,网上查了一圈,说是因为填充方式的原因。
官方文档说明:
那么为什么一定要使用私钥做签名,公钥做加密,而不是公钥做签名,私钥做加密呢?
举个栗子:
㈢ openssl 对称加密有哪些
OpenSSL一共提供了8种对称加密算法,其中7种是分组加密算法,仅有的一种流加密算法是RC4。这7种分组加密算法分别是AES、DES、Blowfish、CAST、IDEA、RC2、RC5。
参考网络。
㈣ 如何利用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中的加密算法库,后者是用于成功加载动态库。
㈤ 如何调用openssl 的加解密算法 进行base64 aes-128
提供个加密函数代码:
#define MAX_ENCRYPT_LEN 1024
void MyEncrypt(const unsigned char *sMsg, int cbMsg, unsigned char *sEncryptMsg, int &cbEncryptMsg)
{
OpenSSL_add_all_algorithms();
//产生会话密钥
unsigned char SessionKey[16];
RAND_bytes(SessionKey,16);
//加密
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
if(EVP_EncryptInit_ex(&ctx,EVP_get_cipherbynid(NID_aes_128_ecb),NULL,SessionKey,NULL))
{
int offseti=0;
int offseto=0;
int offsett=0;
for(;;)
{
if(cbMsg-offseti<=MAX_ENCRYPT_LEN)
{
EVP_EncryptUpdate(&ctx, sEncryptMsg+offseto, &offsett, sMsg+offseti, cbMsg-offseti);
offseto+=offsett;
break;
}
else
{
EVP_EncryptUpdate(&ctx, sEncryptMsg+offseto, &offsett, sMsg+offseti, MAX_SIGN_MSG);
offseti+=MAX_SIGN_MSG;
offseto+=offsett;
}
}
EVP_EncryptFinal_ex(&ctx, sEncryptMsg+offseto, &offsett);
offseto+=offsett;
cbEncryptMsg=offseto;
}
EVP_CIPHER_CTX_cleanup(&ctx);
}
参数解释:
const unsigned char *sMsg 需要解密的明文
int cbMsg 明文长度
unsigned char *sEncryptMsg 输出密文
int &cbEncryptMsg 密文长度
好了,这个函数刚写的,验证了一下,是没有问题的
解密与这个比较类似