RSA加密/解密

我正在编写一个C程序,用于加密(基于私钥)和解密(基于公钥)文本。 我正在尝试使用OpenSSL lib。 有谁知道任何好的教程,快速入门指南或示例代码? 我没有在网上找到任何像样的人。

以下是我使用RSA为非对称算法加密文件而使用AES-128-CBC为对称算法加密文件的示例,以及OpenSSL EVP函数:

#include  #include  #include  #include  #include  #include  #include  /* 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 \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; } 

和相应的解密示例:

 #include  #include  #include  #include  #include  #include  #include  /* 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 \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; } 

我认为这很容易理解。