我在这里做错了什么?我一定错过了什么..
我正在使用EVP_Seal / EVP_Open API。我已经生成了公钥/私钥和证书。我看到了一些奇怪的东西 - 我解码后的第一个16字节是垃圾。如果我的数据很小(小于16字节),那么我没有从EVP_Open函数获得任何输出。
继承我的测试计划:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#define PORT 6999
#define HOST "localhost"
#define PUBLIC_KEYFILE "pubkey.pem"
#define CERT_FILE "server.crt"
#define PRIVATE_KEYFILE "server.key"
void run_client(void);
EVP_CIPHER_CTX en_ctx;
EVP_CIPHER_CTX de_ctx;
typedef struct {
int keylen;
unsigned char key[512];
unsigned char iv[EVP_MAX_IV_LENGTH];
} keys_t;
unsigned char msg[1024];
unsigned char enc_buf[1024];
unsigned char de_buf[1024];
int main(int argc, char **argv)
{
// Init malloc, free etc for OpenSSL's CRYPTO_malloc_init();
ERR_load_BIO_strings();
OpenSSL_add_all_algorithms();
run_client();
return 0;
}
int encrypt_with_cert(unsigned char **secret_key, int *keylen,
unsigned char **out_iv,
unsigned char *data, int *datalen)
{
FILE *fp;
X509 *x509;
EVP_PKEY *pkey;
unsigned char *ek;
int eklen;
int retval = 0;
unsigned char iv[EVP_MAX_IV_LENGTH];
int i=0;
RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH);
fp = fopen(CERT_FILE, "r");
if (!fp) {
fprintf(stderr, "Cannot open certificate file\n");
goto out;
}
x509 = PEM_read_X509(fp, NULL, 0, NULL);
if (x509 == NULL) {
ERR_print_errors_fp(stderr);
goto out;
}
fclose(fp);
pkey = X509_extract_key(x509);
X509_free(x509);
if (pkey == NULL) {
ERR_print_errors_fp(stderr);
}
EVP_CIPHER_CTX_init(&en_ctx);
ek = malloc(EVP_PKEY_size(pkey));
if (!EVP_SealInit(&en_ctx, EVP_aes_256_cbc(), &ek,
&eklen, iv, &pkey, 1)) {
fprintf(stderr, "EVP_SealInit failed\n");
retval = 3;
goto out_free;
}
int buf_len = 0;
int tot_len = 0;
printf("Encoding string: {%s}, len: %d\n", data, *datalen);
memset(enc_buf, 0 , 1024);
EVP_SealInit(&en_ctx, NULL, NULL, NULL, NULL, NULL, 1);
EVP_SealUpdate(&en_ctx, enc_buf, &buf_len, data, *datalen);
tot_len += buf_len;
EVP_SealFinal(&en_ctx, enc_buf+buf_len, &buf_len);
tot_len += buf_len;
*(enc_buf + tot_len) = '\0';
*datalen = tot_len;
printf("Encoded length: %d\n", tot_len);
printf("Encoded message: {");
for (i=0; i< tot_len; i++) {
printf("%02x", enc_buf[i]);
}
printf("}\n");
goto out;
out_free:
EVP_PKEY_free(pkey);
free(ek);
out:
*secret_key = ek;
*keylen = eklen;
*out_iv = iv;
return retval;
}
void decrypt_message(unsigned char *secret_key, int keylen,
unsigned char *iv, int buflen)
{
FILE *privkey;
int retval = 0;
int klen=0;
int tot_len = 0;
EVP_PKEY *pkey;
int i = 0;
privkey = fopen(PRIVATE_KEYFILE, "r");
if (!privkey) {
fprintf(stderr, "Error opening private key\n");
}
pkey = PEM_read_PrivateKey(privkey, NULL, 0 , NULL);
if (!pkey) {
fprintf(stderr, "Error loading Server's RSA private key\n");
retval = 2;
goto out;
}
if(keylen != EVP_PKEY_size(pkey)) {
EVP_PKEY_free(pkey);
fprintf(stderr, "keylength mismatch!\n");
retval = 2;
goto out;
}
klen = EVP_OpenInit(&de_ctx, EVP_aes_256_cbc(), secret_key, keylen, iv, pkey);
if (klen == 0) {
fprintf(stderr, "EVP_OpenInit failed\n");
}
int de_len = 0;
tot_len = 0;
printf("\n\nNow decoding..\n");
printf("Encoded length: %d\n", buflen);
printf("Encoded message: {");
for (i=0; i< buflen; i++) {
printf("%02x", enc_buf[i]);
}
printf("}\n");
EVP_OpenInit(&de_ctx, NULL, NULL, keylen, NULL, NULL);
EVP_OpenUpdate(&de_ctx, de_buf, &de_len, enc_buf, buflen);
tot_len += de_len;
EVP_OpenFinal(&de_ctx, de_buf+tot_len, &de_len);
tot_len += de_len;
*(de_buf+tot_len) = '\0';
printf("Decoded length: %d, String: %s\n", tot_len, de_buf);
out:
fclose(privkey);
return;
}
void run_client()
{
unsigned char *secret_key = NULL;
int keylen;
unsigned char *iv = NULL;
int data_len = 0;
int retval = 0;
//strcpy((char *)msg, "abcdefghijklmnopqrstuvwxyz0123456789");
//strcpy((char *)msg, "this is a secret message\n");
strcpy((char *)msg, "1234567890");
data_len = strlen((char *)msg) + 1;
retval = encrypt_with_cert(&secret_key, &keylen, &iv, msg, &data_len);
if (retval != 0) {
printf("encrypt with certificate failed! retval = %d\n", retval);
}
decrypt_message(secret_key, keylen, iv, data_len);
}
当我在这里运行时,我得到的是: [示例] $ gcc -Wall -g -o openssl_seal -lcrypto openssl_seal.c
[sample]$ ./openssl_seal
Encoding string: {1234567890}, len: 11
Encoded length: 16
Encoded message: {9753c483d6816b64693f604b2376f0a0}
Now decoding..
Encoded length: 16
Encoded message: {9753c483d6816b64693f604b2376f0a0}
Decoded length: 0, String:
[sample]$ gcc -Wall -g -o openssl_seal -lcrypto openssl_seal.c
[sample]$ ./openssl_seal
Encoding string: {abcdefghijklmnopqrstuvwxyz0123456789}, len: 37
Encoded length: 48
Encoded message: {ad264f30fe70cc6f9c8d712073bc72049e7f7515a28c1cf0aeef648d6c4c4bfd717ae2fd21396bb95eb7ec0ce88f7f9d}
Now decoding..
Encoded length: 48
Encoded message: {ad264f30fe70cc6f9c8d712073bc72049e7f7515a28c1cf0aeef648d6c4c4bfd717ae2fd21396bb95eb7ec0ce88f7f9d}
Decoded length: 37, String: abcd.VO[vтOqrstuvwxyz0123456789
答案 0 :(得分:0)
看起来您正在调用EVP_SealInit
两次,并且第二次忽略iv参数。您应该只调用此方法一次,保存IV参数并将其传输到解密端。同样,您只应拨打EVP_OpenInit
一次。