Tôi đang viết một chương trình C mã hóa (dựa trên khóa riêng) và giải mã (dựa trên khóa công khai) văn bản. Tôi đang cố gắng làm điều này với lib OpenSSL. Có ai biết bất kỳ hướng dẫn tốt, hướng dẫn bắt đầu nhanh hoặc mã mẫu? Tôi đã không tìm thấy bất kỳ một phong nha trên web.Mã hóa/giải mã RSA
Trả lời
Dưới đây là một ví dụ tôi tạo ra để mã hóa một tập tin sử dụng RSA cho các thuật toán bất đối xứng và AES-128-CBC cho các thuật toán đối xứng, với các chức năng EVP OpenSSL:
#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/err.h>
#include <arpa/inet.h> /* For htonl() */
int do_evp_seal(FILE *rsa_pkey_file, FILE *in_file, FILE *out_file)
{
int retval = 0;
RSA *rsa_pkey = NULL;
EVP_PKEY *pkey = EVP_PKEY_new();
EVP_CIPHER_CTX ctx;
unsigned char buffer[4096];
unsigned char buffer_out[4096 + EVP_MAX_IV_LENGTH];
size_t len;
int len_out;
unsigned char *ek = NULL;
int eklen;
uint32_t eklen_n;
unsigned char iv[EVP_MAX_IV_LENGTH];
if (!PEM_read_RSA_PUBKEY(rsa_pkey_file, &rsa_pkey, NULL, NULL))
{
fprintf(stderr, "Error loading RSA Public Key File.\n");
ERR_print_errors_fp(stderr);
retval = 2;
goto out;
}
if (!EVP_PKEY_assign_RSA(pkey, rsa_pkey))
{
fprintf(stderr, "EVP_PKEY_assign_RSA: failed.\n");
retval = 3;
goto out;
}
EVP_CIPHER_CTX_init(&ctx);
ek = malloc(EVP_PKEY_size(pkey));
if (!EVP_SealInit(&ctx, EVP_aes_128_cbc(), &ek, &eklen, iv, &pkey, 1))
{
fprintf(stderr, "EVP_SealInit: failed.\n");
retval = 3;
goto out_free;
}
/* First we write out the encrypted key length, then the encrypted key,
* then the iv (the IV length is fixed by the cipher we have chosen).
*/
eklen_n = htonl(eklen);
if (fwrite(&eklen_n, sizeof eklen_n, 1, out_file) != 1)
{
perror("output file");
retval = 5;
goto out_free;
}
if (fwrite(ek, eklen, 1, out_file) != 1)
{
perror("output file");
retval = 5;
goto out_free;
}
if (fwrite(iv, EVP_CIPHER_iv_length(EVP_aes_128_cbc()), 1, out_file) != 1)
{
perror("output file");
retval = 5;
goto out_free;
}
/* Now we process the input file and write the encrypted data to the
* output file. */
while ((len = fread(buffer, 1, sizeof buffer, in_file)) > 0)
{
if (!EVP_SealUpdate(&ctx, buffer_out, &len_out, buffer, len))
{
fprintf(stderr, "EVP_SealUpdate: failed.\n");
retval = 3;
goto out_free;
}
if (fwrite(buffer_out, len_out, 1, out_file) != 1)
{
perror("output file");
retval = 5;
goto out_free;
}
}
if (ferror(in_file))
{
perror("input file");
retval = 4;
goto out_free;
}
if (!EVP_SealFinal(&ctx, buffer_out, &len_out))
{
fprintf(stderr, "EVP_SealFinal: failed.\n");
retval = 3;
goto out_free;
}
if (fwrite(buffer_out, len_out, 1, out_file) != 1)
{
perror("output file");
retval = 5;
goto out_free;
}
out_free:
EVP_PKEY_free(pkey);
free(ek);
out:
return retval;
}
int main(int argc, char *argv[])
{
FILE *rsa_pkey_file;
int rv;
if (argc < 2)
{
fprintf(stderr, "Usage: %s <PEM RSA Public Key File>\n", argv[0]);
exit(1);
}
rsa_pkey_file = fopen(argv[1], "rb");
if (!rsa_pkey_file)
{
perror(argv[1]);
fprintf(stderr, "Error loading PEM RSA Public Key File.\n");
exit(2);
}
rv = do_evp_seal(rsa_pkey_file, stdin, stdout);
fclose(rsa_pkey_file);
return rv;
}
Và ví dụ giải mã tương ứng:
#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/err.h>
#include <arpa/inet.h> /* For htonl() */
int do_evp_unseal(FILE *rsa_pkey_file, FILE *in_file, FILE *out_file)
{
int retval = 0;
RSA *rsa_pkey = NULL;
EVP_PKEY *pkey = EVP_PKEY_new();
EVP_CIPHER_CTX ctx;
unsigned char buffer[4096];
unsigned char buffer_out[4096 + EVP_MAX_IV_LENGTH];
size_t len;
int len_out;
unsigned char *ek;
unsigned int eklen;
uint32_t eklen_n;
unsigned char iv[EVP_MAX_IV_LENGTH];
if (!PEM_read_RSAPrivateKey(rsa_pkey_file, &rsa_pkey, NULL, NULL))
{
fprintf(stderr, "Error loading RSA Private Key File.\n");
ERR_print_errors_fp(stderr);
retval = 2;
goto out;
}
if (!EVP_PKEY_assign_RSA(pkey, rsa_pkey))
{
fprintf(stderr, "EVP_PKEY_assign_RSA: failed.\n");
retval = 3;
goto out;
}
EVP_CIPHER_CTX_init(&ctx);
ek = malloc(EVP_PKEY_size(pkey));
/* First need to fetch the encrypted key length, encrypted key and IV */
if (fread(&eklen_n, sizeof eklen_n, 1, in_file) != 1)
{
perror("input file");
retval = 4;
goto out_free;
}
eklen = ntohl(eklen_n);
if (eklen > EVP_PKEY_size(pkey))
{
fprintf(stderr, "Bad encrypted key length (%u > %d)\n", eklen,
EVP_PKEY_size(pkey));
retval = 4;
goto out_free;
}
if (fread(ek, eklen, 1, in_file) != 1)
{
perror("input file");
retval = 4;
goto out_free;
}
if (fread(iv, EVP_CIPHER_iv_length(EVP_aes_128_cbc()), 1, in_file) != 1)
{
perror("input file");
retval = 4;
goto out_free;
}
if (!EVP_OpenInit(&ctx, EVP_aes_128_cbc(), ek, eklen, iv, pkey))
{
fprintf(stderr, "EVP_OpenInit: failed.\n");
retval = 3;
goto out_free;
}
while ((len = fread(buffer, 1, sizeof buffer, in_file)) > 0)
{
if (!EVP_OpenUpdate(&ctx, buffer_out, &len_out, buffer, len))
{
fprintf(stderr, "EVP_OpenUpdate: failed.\n");
retval = 3;
goto out_free;
}
if (fwrite(buffer_out, len_out, 1, out_file) != 1)
{
perror("output file");
retval = 5;
goto out_free;
}
}
if (ferror(in_file))
{
perror("input file");
retval = 4;
goto out_free;
}
if (!EVP_OpenFinal(&ctx, buffer_out, &len_out))
{
fprintf(stderr, "EVP_SealFinal: failed.\n");
retval = 3;
goto out_free;
}
if (fwrite(buffer_out, len_out, 1, out_file) != 1)
{
perror("output file");
retval = 5;
goto out_free;
}
out_free:
EVP_PKEY_free(pkey);
free(ek);
out:
return retval;
}
int main(int argc, char *argv[])
{
FILE *rsa_pkey_file;
int rv;
if (argc < 2)
{
fprintf(stderr, "Usage: %s <PEM RSA Private Key File>\n", argv[0]);
exit(1);
}
rsa_pkey_file = fopen(argv[1], "rb");
if (!rsa_pkey_file)
{
perror(argv[1]);
fprintf(stderr, "Error loading PEM RSA Private Key File.\n");
exit(2);
}
rv = do_evp_unseal(rsa_pkey_file, stdin, stdout);
fclose(rsa_pkey_file);
return rv;
}
Tôi nghĩ điều đó khá dễ làm theo.
Tôi không thể hiểu tại sao bạn mang thuật toán mã hóa đối xứng vào ae vào hệ thống mật mã khóa công khai không đối xứng RSA? Điều này có đúng không? – scarface
@scarface: Vì nhiều lý do, hệ thống khóa không đối xứng không được sử dụng để mã hóa dữ liệu hàng loạt - chúng được sử dụng để mã hóa khóa cho hệ thống khóa đối xứng, được sử dụng để mã hóa dữ liệu hàng loạt. Đó chính là cách hoạt động của chức năng mã hóa phong bì EVP *. – caf
Tuyệt vời, cảm ơn bạn rất nhiều. – scarface
- 1. Mã RSA trong MATLAB
- 2. Mã hóa RSA .NET Giải mã Java
- 3. Mã hóa Java RSA - Giải mã .NET
- 4. Mã hóa RSA trong Android
- 5. Mã hóa RSA/Giải mã vấn đề trong .NET
- 6. Mã hóa RSA: Java tới PHP
- 7. Giải mã RSA trên Android - iPhone
- 8. Thư viện mã hóa RSA cho C++
- 9. Mã hóa RSA bằng khóa công khai
- 10. Mã hóa BouncyCastle RSA cho BlackBerry
- 11. Sử dụng Khóa công cộng RSA để giải mã một chuỗi đã được mã hóa bằng Khóa riêng RSA
- 12. kích thước khối tối đa RSA nào để mã hóa?
- 13. OCR một khóa RSA fob (mã bảo mật)
- 14. Mã hóa RSA của dữ liệu lớn trong C#
- 15. Giải mã C# RSA sử dụng Lâu đài Bouncy
- 16. RSA: Mã hóa tin nhắn bằng nhiều phím
- 17. Tải khóa RSA riêng được mã hóa PEM trong Crypto ++
- 18. Cách đọc mã Cảnh báo mã hóa SSL/TLS trong Ephemeral RSA
- 19. Mã hóa và giải mã chuỗi lớn trong java bằng cách sử dụng RSA
- 20. SessionSecurityTokenHandler cố gắng giải mã SessionSecurityToken trong cookie được mã hóa RSA bằng DPAPI; tại sao?
- 21. CryptographicException không liên tục xảy ra khi mã hóa/giải mã bằng RSA
- 22. Mã hóa và giải mã một chuỗi văn bản với RSA và des3 chính
- 23. Mã hóa/giải mã RSA tương thích với Javascript và PHP
- 24. Làm thế nào để mã hóa và giải mã văn bản thuần tuý bằng khóa RSA trong Go?
- 25. Gặp sự cố khi giải mã trong C# một cái gì đó được mã hóa trên iPhone bằng RSA
- 26. Mã hóa/giải mã các tệp lớn (.NET)
- 27. Lỗi mã hóa và giải mã 0x0407106B sử dụng OpenSSL
- 28. gửi RSA khóa công khai vào iphone và sử dụng nó để mã hóa
- 29. Mã hóa tin nhắn bằng khóa riêng RSA (như trong RSA_private_encrypt của OpenSSL)
- 30. Mô-đun mã hóa Erlang - ECDSA, RSA, SHA256 và như vậy trên
Bạn nên bắt đầu với bộ khởi động mã hóa. Bạn thường mã hóa bằng khóa công cộng và giải mã bằng khóa riêng. –