当前位置: 首页 > news >正文

杭州微网站开发公司电话如何建立公司网站网页

杭州微网站开发公司电话,如何建立公司网站网页,深圳网站建设及优化,凡科教育文章目录 1.为什么需要非对称密钥----对称密钥配送问题2.什么是公钥密码-非对称密钥3.神奇的数学关系-RSA加密数学原理4.RSA数学步骤5.RSA使用5.1 使用openssl命令实现RSA加密解密5.2 使用openssl API 接口实现RSA 加密解密5.3 使用mbedtls API实现RSA 加密解密5.4 使用openssl…

文章目录

    • 1.为什么需要非对称密钥----对称密钥配送问题
    • 2.什么是公钥密码-非对称密钥
    • 3.神奇的数学关系-RSA加密数学原理
    • 4.RSA数学步骤
    • 5.RSA使用
      • 5.1 使用openssl命令实现RSA加密解密
      • 5.2 使用openssl API 接口实现RSA 加密解密
      • 5.3 使用mbedtls API实现RSA 加密解密
      • 5.4 使用openssl API 实现RSA 加签验签
      • 5.5 使用mbedtls API实现RSA 加签验签
      • 5.6 RSA使用总结

1.为什么需要非对称密钥----对称密钥配送问题

对称密钥配送问题是指在使用对称密钥加密算法时,如何安全地将密钥传输给通信双方的问题。由于对称密钥需要保持机密性,因此在传输过程中可能会面临被窃听或篡改的风险。
在这里插入图片描述

以下是几种常见的解决对称密钥配送问题的方法:

  • 预先共享密钥:通信双方事先共享一个密钥,并确保在通信之前将其保存在安全的位置。这要求双方在通信开始之前就建立了一定的信任关系,并能够安全地交换密钥。

  • 密钥分发中心(Key Distribution Center,KDC):KDC作为第三方可信实体,负责生成、分发和管理对称密钥。通信双方首先与KDC进行身份认证,然后从KDC获取加密通信所需的密钥。

  • 混合加密机制:使用非对称加密算法结合对称加密算法,通信双方首先使用非对称密钥加密传输对称密钥,然后再使用对称密钥进行加密通信。这样可以在保证对称密钥安全性的同时,利用非对称算法解决密钥配送问题。

  • Diffie-Hellman密钥交换协议:Diffie-Hellman密钥交换协议允许通信双方在公开渠道上协商一个共享的秘密密钥,而不需要事先共享密钥或依赖可信第三方。通过数学运算,双方可以独立计算出相同的密钥。

2.什么是公钥密码-非对称密钥

公钥密码,也称为非对称密码,是一种密码算法体系,其中使用了两个相关联但不同的密钥:公钥和私钥。这两个密钥是成对生成的,其中一个用于加密数据(公钥),另一个用于解密数据(私钥)。

公钥密码系统的工作原理如下:

  • 公钥加密私钥解密:发送方使用接收方的公钥对消息进行加密,然后将密文发送给接收方。只有拥有相应私钥的接收方才能解密密文并读取原始消息。

  • 私钥签名公钥验签:发送方使用自己的私钥对消息进行签名,然后将签名附加到消息中。接收方可以使用发送方的公钥验证签名的真实性和完整性,以确保消息未被篡改。

公钥密码系统具有以下特点和优势:

  • 安全性:公钥密码系统基于数学难题,如大素数分解、离散对数等,这些问题在计算上很难逆转。因此,即使攻击者获得了公钥,也很难从中推导出私钥,保证了数据的机密性和安全性。

  • 密钥配送问题:相对于对称加密算法,公钥密码系统解决了密钥配送问题。每个用户只需要保存自己的私钥,而公钥可以自由传播。这样,通信双方无需事先共享密钥,可以安全地进行加密通信。

  • 数字签名:公钥密码系统可以用于生成和验证数字签名,确保消息的完整性、真实性和不可抵赖性。通过使用私钥对消息进行签名,发送方可以证明其身份,并且无法否认自己的行为。

常见的公钥密码算法包括RSA、椭圆曲线密码学(ECC)、Diffie-Hellman密钥交换等。这些算法在信息安全领域得到广泛应用,用于加密通信、数字签名、密钥交换等场景。公钥密码系统为安全通信提供了重要的技术基础。

3.神奇的数学关系-RSA加密数学原理

  1. RSA密码算法中的公钥和私钥之间存在严格而神奇的数学关系,公私钥之间是一一对应的;
    详细RSA 数学原理请参考 RSA加密数学原理详解

4.RSA数学步骤

在这里插入图片描述
RSA(Rivest-Shamir-Adleman)是一种基于数论的公钥密码算法,其核心原理涉及到以下几个数学概念和操作:
在这里插入图片描述

  1. 选择素数:
    在RSA中,首先需要选择两个大素数 p 和 q。这两个素数需要保密,并且应该足够大,以增加破解的难度, 大素数一般来自于随机数, 先
    使用随机数生成器生成一个大整数, 再判断该大整数是否为素数。
    p = 3,q = 11
  2. 计算模数:
    计算模数 n = p * q。模数 n 是一个大整数,它将用于加密和解密过程中的运算。
    n = p * q = 33
  3. 计算欧拉函数:
    欧拉函数 φ(n) 是与模数 n 互质的小于 n 的正整数的个数。对于两个素数 p 和 q,欧拉函数可以表示为 φ(n) = (p-1)(q-1)。
    φ(n) = (p-1)(q-1) = (3-1)(11-1) = 20*
  4. 选择加密指数:
    选择一个加密指数 e,满足 1 < e < φ(n) 且 e 与 φ(n) 互质。加密指数 e 将用于加密明文。e的常见选择有3、 17和65537, 它们都是素数并可加快模幂运
    算速度。
    e =3
  5. 计算解密指数:
    计算解密指数 d,使得 (d * e) mod φ(n) = 1。解密指数 d 将用于解密密文。
    3d mod 20 = 1 d = 7
  6. 加密:
    将明文 M 转换为整数 m(0 ≤ m < n),然后计算密文 C = m^e mod n。密文 C 是加密后的整数。
    c=me mod N = 53 mod 33 = 26
  7. 解密:
    接收者使用私钥(解密指数 d 和模数 n)进行解密。计算明文 m = C^d mod n,然后将整数 m 转换回原始明文 M。
    m=cd mod N = 267 mod 33 = 5

5.RSA使用

5.1 使用openssl命令实现RSA加密解密

在这里插入图片描述

  1. 在 Linux 环境下,openssl genrsa 命令用于生成 RSA 密钥对。下面是详细介绍该命令的使用方法和常见参数:

    openssl genrsa [options] [-out filename] [numbits]
    

    常见参数说明:

  • -options:可选参数,用于指定不同选项。

  • -out filename:可选参数,用于指定生成的密钥文件名,默认为标准输出。

  • numbits:可选参数,用于指定密钥长度(位数),默认为 2048 位。
    常见选项:

    • -aes128、-aes192、-aes256:分别用于指定使用 AES-128、AES-192、AES-256 加密密钥。
    • -des、-des3:分别用于指定使用 DES、Triple DES 加密密钥。
    • -rand file(s):用于指定随机种子文件路径,多个文件路径可以用逗号分隔。
    • -rand file:file…:用于指定多个随机种子文件。
    • -f4:用于指定 RSA 公钥指数(默认为 F4,即 65537)。
    • -help:显示帮助信息。
  • 示例用法:

    • 生成默认(2048 位)的 RSA 密钥对,并将私钥保存到文件 private.pem 中:
    openssl genrsa -out private.pem
    
    • 生成 4096 位的 RSA 密钥对,并将私钥保存到文件 private.pem 中:
    openssl genrsa -out private.pem 4096
    
    • 生成默认(2048 位)的 RSA 密钥对,并使用 AES-256 加密私钥,同时将私钥保存到文件 private.pem 中:
    openssl genrsa -aes256 -out private.pem
    
    • 生成默认(2048 位)的 RSA 密钥对,并使用指定的随机种子文件生成密钥:
    openssl genrsa -rand /dev/random -out private.pem
    
    1. 在 Linux 环境下,OpenSSL 提供了 openssl rsa 命令用于操作 RSA 密钥。它可以用于生成、转换和管理 RSA 密钥,以及执行与密钥相关的其他操作。下面是 openssl rsa 命令的使用方法和常见命令控制参数的详细介绍:
    openssl rsa [options] [-in filename] [-out filename]
    

    常见命令控制参数说明:

  • options:可选参数,用于指定不同选项。

  • -in filename:可选参数,用于指定输入的密钥文件名,默认为标准输入。

  • -out filename:可选参数,用于指定输出的密钥文件名,默认为标准输出。
    常见选项:

  • -pubin:读取公钥文件。

  • -pubout:将密钥转换为公钥形式输出。

  • -inform PEM、-inform DER:分别用于指定输入密钥的格式为 PEM 格式或 DER 格式。

  • -outform PEM、-outform DER:分别用于指定输出密钥的格式为 PEM 格式或 DER 格式。

  • -passin arg:用于指定输入密钥文件或加密密钥口令的密码。

  • -passout arg:用于指定输出密钥文件的密码。

  • -text:以文本格式显示密钥信息。

  • -noout:不进行任何输出,仅执行操作。
    示例用法:

    • 显示 PEM 格式私钥文件 private.pem 的信息:
    openssl rsa -in private.pem -text
    
    • 将 PEM 格式私钥文件 private.pem 转换为 DER 格式,并保存到文件 private.der:
    openssl rsa -in private.pem -outform DER -out private.der
    
    • 将 PEM 格式公钥文件 public.pem 转换为 DER 格式,并保存到文件 public.der:
    openssl rsa -pubin -in public.pem -outform DER -out public.der
    
    • 将 PEM 格式密钥文件 private.pem 的密码更改为新密码,并将结果保存到文件 new_private.pem:
    openssl rsa -in private.pem -passin pass:oldpass -des3 -out new_private.pem -passout pass:newpass
    
  1. 在 Linux 环境下,OpenSSL 提供了 openssl rsautl 命令用于执行 RSA 加密、解密、签名和验证等操作。它可以使用 RSA 密钥对进行数据的加解密和签名验证。下面是 openssl rsautl 命令的使用方法和常见命令控制参数的详细介绍:

    openssl rsautl [options] [-in filename] [-out filename]
    

常见命令控制参数说明:

  • options:可选参数,用于指定不同选项。
  • -in filename:可选参数,用于指定输入的文件名,默认为标准输入。
  • -out filename:可选参数,用于指定输出的文件名,默认为标准输出。

常见选项:

  • -encrypt:使用公钥进行加密。
  • -decrypt:使用私钥进行解密。
  • -sign:使用私钥进行签名。
  • -verify:使用公钥进行签名验证。
  • -inkey filename:用于指定包含 RSA 密钥的文件名。
  • -keyform PEM、-keyform DER:分别用于指定输入密钥的格式为 PEM 格式或 DER 格式。
  • -pubin:读取公钥文件。
  • -passin arg:用于指定输入密钥文件或加密密钥口令的密码。
  • -raw:以原始二进制格式处理输入数据。
  • -hexdump:以十六进制格式显示加解密后的数据。
  • -oaep:使用 OAEP(Optimal Asymmetric Encryption Padding)进行加解密操作。
  • -pkcs:使用 PKCS#1 标准进行加解密操作。

示例用法:

  • 使用公钥文件 public.pem 对文件 plain.txt 进行加密,并将结果保存到文件 encrypted.dat:

    openssl rsautl -encrypt -inkey public.pem -pubin -in plain.txt -out encrypted.dat
    
  • 使用私钥文件 private.pem 对文件 encrypted.dat 进行解密,并将结果保存到文件 decrypted.txt:

    openssl rsautl -decrypt -inkey private.pem -in encrypted.dat -out decrypted.txt
    
  • 使用私钥文件 private.pem 对文件 data.txt 进行签名,并将结果保存到文件 signature.bin:

    openssl rsautl -sign -inkey private.pem -in data.txt -out signature.bin
    
  • 使用公钥文件 public.pem 对文件 data.txt 的签名进行验证:

    openssl rsautl -verify -inkey public.pem -pubin -in data.txt -in signature.bin
    

    注意事项:

    • 在使用 openssl rsautl 命令之前,需要确保已生成 RSA 密钥对,可以使用 openssl genrsa 命令生成。
    • 公钥和私钥文件一般采用 PEM 格式或 DER 格式。
    • 对于加密和解密操作,需要使用匹配的公钥和私钥。
    • 对于签名和验证操作,需要使用匹配的私钥和公钥。
  1. 下面是使用 OpenSSL 命令生成 RSA 密钥对,并使用公钥加密、私钥解密的完整命令流:

    • 生成 RSA 密钥对:
    openssl genrsa -out private_key.pem 2048
    

    上述命令将生成一个长度为 2048 位的 RSA 私钥,并保存在 private_key.pem 文件中。

  • 从私钥中提取公钥:

    openssl rsa -in private_key.pem -out public_key.pem -pubout
    

    上述命令将从私钥文件 private_key.pem 中提取公钥,并保存在 public_key.pem 文件中。

  • 使用公钥进行加密:

    openssl rsautl -encrypt -inkey public_key.pem -pubin -in plaintext.txt -out encrypted.txt
    

    上述命令将使用公钥文件 public_key.pem 对文件 plaintext.txt 进行加密,并将结果保存到 encrypted.txt 中。

  • 使用私钥进行解密:

    openssl rsautl -decrypt -inkey private_key.pem -in encrypted.txt -out decrypted.txt
    

    上述命令将使用私钥文件 private_key.pem 对文件 encrypted.txt 进行解密,并将结果保存到 decrypted.txt 中。

5.2 使用openssl API 接口实现RSA 加密解密

  1. 生成RSA密钥对
// 生成公钥文件和私钥文件,私钥文件带密码
int generate_key_files(const char *pub_keyfile, const char *pri_keyfile, const unsigned char *passwd, int passwd_len)
{RSA *rsa = NULL;RAND_seed(rnd_seed, sizeof(rnd_seed));rsa = RSA_generate_key(RSA_KEY_LENGTH, RSA_F4, NULL, NULL);if(rsa == NULL){printf("RSA_generate_key error!\n");return -1;}// 开始生成公钥文件BIO *bp = BIO_new(BIO_s_file());if(NULL == bp){printf("generate_key bio file new error!\n");return -1;}if(BIO_write_filename(bp, (void *)pub_keyfile) <= 0){printf("BIO_write_filename error!\n");return -1;}if(PEM_write_bio_RSAPublicKey(bp, rsa) != 1){printf("PEM_write_bio_RSAPublicKey error!\n");return -1;}// 公钥文件生成成功,释放资源printf("Create public key ok!\n");BIO_free_all(bp);// 生成私钥文件bp = BIO_new_file(pri_keyfile, "w+");if(NULL == bp){printf("generate_key bio file new error2!\n");return -1;}if(PEM_write_bio_RSAPrivateKey(bp, rsa,EVP_des_ede3_ofb(), (unsigned char *)passwd, passwd_len, NULL, NULL) != 1){printf("PEM_write_bio_RSAPublicKey error!\n");return -1;}// 释放资源printf("Create private key ok!\n");BIO_free_all(bp);RSA_free(rsa);return 0;
}
  1. 读取公钥
// 打开公钥文件,返回EVP_PKEY结构的指针
EVP_PKEY* open_public_key(const char *keyfile)
{EVP_PKEY* key = NULL;RSA *rsa = NULL;OpenSSL_add_all_algorithms();BIO *bp = BIO_new(BIO_s_file());;BIO_read_filename(bp, keyfile);if(NULL == bp){printf("open_public_key bio file new error!\n");return NULL;}rsa = PEM_read_bio_RSAPublicKey(bp, NULL, NULL, NULL);if(rsa == NULL){printf("open_public_key failed to PEM_read_bio_RSAPublicKey!\n");BIO_free(bp);RSA_free(rsa);return NULL;}printf("open_public_key success to PEM_read_bio_RSAPublicKey!\n");key = EVP_PKEY_new();if(NULL == key){printf("open_public_key EVP_PKEY_new failed\n");RSA_free(rsa);return NULL;}EVP_PKEY_assign_RSA(key, rsa);return key;
}
  1. 读取私钥
// 打开私钥文件,返回EVP_PKEY结构的指针
EVP_PKEY* open_private_key(const char *keyfile, const unsigned char *passwd)
{EVP_PKEY* key = NULL;RSA *rsa = RSA_new();OpenSSL_add_all_algorithms();BIO *bp = NULL;bp = BIO_new_file(keyfile, "rb"); if(NULL == bp){printf("open_private_key bio file new error!\n");return NULL;}rsa = PEM_read_bio_RSAPrivateKey(bp, &rsa, NULL, (void *)passwd);if(rsa == NULL){printf("open_private_key failed to PEM_read_bio_RSAPrivateKey!\n");BIO_free(bp);RSA_free(rsa);return NULL;}printf("open_private_key success to PEM_read_bio_RSAPrivateKey!\n");key = EVP_PKEY_new();if(NULL == key){printf("open_private_key EVP_PKEY_new failed\n");RSA_free(rsa);return NULL;}EVP_PKEY_assign_RSA(key, rsa);return key;
}
  1. 公钥加密
// 使用密钥加密,这种封装格式只适用公钥加密,私钥解密,这里key必须是公钥
int rsa_key_encrypt(EVP_PKEY *key, const unsigned char *orig_data, size_t orig_data_len, unsigned char *enc_data, size_t &enc_data_len)
{EVP_PKEY_CTX *ctx = NULL;OpenSSL_add_all_ciphers();ctx = EVP_PKEY_CTX_new(key, NULL);if(NULL == ctx){printf("ras_pubkey_encryptfailed to open ctx.\n");EVP_PKEY_free(key);return -1;}if(EVP_PKEY_encrypt_init(ctx) <= 0){printf("ras_pubkey_encryptfailed to EVP_PKEY_encrypt_init.\n");EVP_PKEY_free(key);return -1;}if(EVP_PKEY_encrypt(ctx,enc_data,&enc_data_len,orig_data,orig_data_len) <= 0){printf("ras_pubkey_encryptfailed to EVP_PKEY_encrypt.\n");EVP_PKEY_CTX_free(ctx);EVP_PKEY_free(key);return -1;}EVP_PKEY_CTX_free(ctx);EVP_PKEY_free(key);return 0;
}
  1. 私钥解密
// 使用密钥解密,这种封装格式只适用公钥加密,私钥解密,这里key必须是私钥
int rsa_key_decrypt(EVP_PKEY *key, const unsigned char *enc_data, size_t enc_data_len, unsigned char *orig_data, size_t &orig_data_len, const unsigned char *passwd)
{EVP_PKEY_CTX *ctx = NULL;OpenSSL_add_all_ciphers();ctx = EVP_PKEY_CTX_new(key, NULL);if(NULL == ctx){printf("ras_prikey_decryptfailed to open ctx.\n");EVP_PKEY_free(key);return -1;}if(EVP_PKEY_decrypt_init(ctx) <= 0){printf("ras_prikey_decryptfailed to EVP_PKEY_decrypt_init.\n");EVP_PKEY_free(key);return -1;}if(EVP_PKEY_decrypt(ctx,orig_data,&orig_data_len,enc_data,enc_data_len) <= 0){printf("ras_prikey_decryptfailed to EVP_PKEY_decrypt.\n");EVP_PKEY_CTX_free(ctx);EVP_PKEY_free(key);return -1;}EVP_PKEY_CTX_free(ctx);EVP_PKEY_free(key);return 0;
}
  1. 测试函数
int main(int argc, char **argv)
{char origin_text[] = "hello world!";char enc_text[512] = "";char dec_text[512] = "";size_t enc_len = 512;size_t dec_len = 512;// 生成公钥和私钥文件generate_key_files(PUBLIC_KEY_FILE, PRIVATE_KEY_FILE, (const unsigned char *)RSA_PRIKEY_PSW, strlen(RSA_PRIKEY_PSW));EVP_PKEY *pub_key = open_public_key(PUBLIC_KEY_FILE);EVP_PKEY *pri_key = open_private_key(PRIVATE_KEY_FILE, (const unsigned char *)RSA_PRIKEY_PSW);rsa_key_encrypt(pub_key, (const unsigned char *)&origin_text, sizeof(origin_text), (unsigned char *)enc_text, enc_len);rsa_key_decrypt(pri_key, (const unsigned char *)enc_text, enc_len, (unsigned char *)dec_text, dec_len, (const unsigned char *)RSA_PRIKEY_PSW);return 0;
}

5.3 使用mbedtls API实现RSA 加密解密

在这里插入图片描述
在这里插入图片描述


#if defined(MBEDTLS_RSA_C)#include <stdio.h>
#include "string.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/rsa.h"static char buf[516];static void dump_rsa_key(mbedtls_rsa_context *ctx)
{size_t olen;printf("\n  +++++++++++++++++ rsa keypair +++++++++++++++++\n\n");mbedtls_mpi_write_string(&ctx->N , 16, buf, sizeof(buf), &olen);printf("N: %s\n", buf); mbedtls_mpi_write_string(&ctx->E , 16, buf, sizeof(buf), &olen);printf("E: %s\n", buf);mbedtls_mpi_write_string(&ctx->D , 16, buf, sizeof(buf), &olen);printf("D: %s\n", buf);mbedtls_mpi_write_string(&ctx->P , 16, buf, sizeof(buf), &olen);printf("P: %s\n", buf);mbedtls_mpi_write_string(&ctx->Q , 16, buf, sizeof(buf), &olen);printf("Q: %s\n", buf);mbedtls_mpi_write_string(&ctx->DP, 16, buf, sizeof(buf), &olen);printf("DP: %s\n", buf);mbedtls_mpi_write_string(&ctx->DQ, 16, buf, sizeof(buf), &olen);printf("DQ: %s\n", buf);mbedtls_mpi_write_string(&ctx->QP, 16, buf, sizeof(buf), &olen);printf("QP: %s\n", buf);printf("\n  +++++++++++++++++ rsa keypair +++++++++++++++++\n\n");
}static void dump_buf(uint8_t *buf, uint32_t len)
{int i;for (i = 0; i < len; i++) {printf("%s%02X%s", i % 16 == 0 ? "\r\n\t" : " ", buf[i], i == len - 1 ? "\r\n" : "");}
}uint8_t output_buf[2048/8];int mbedtls_rsa_test(void)
{int ret;size_t olen;const char* msg = "HelloWorld";uint8_t decrypt_buf[20];const char *pers = "rsa_test";mbedtls_entropy_context entropy;mbedtls_ctr_drbg_context ctr_drbg;mbedtls_rsa_context ctx;/* 1. init structure */mbedtls_entropy_init(&entropy);mbedtls_ctr_drbg_init(&ctr_drbg);mbedtls_rsa_init(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);/* 2. update seed with we own interface ported */printf( "\n  . Seeding the random number generator..." );ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,(const unsigned char *) pers,strlen(pers));if(ret != 0) {printf( " failed\n  ! mbedtls_ctr_drbg_seed returned %d(-0x%04x)\n", ret, -ret);goto exit;}printf( " ok\n" );/* 3. generate an RSA keypair */printf( "\n  . Generate RSA keypair..." );ret = mbedtls_rsa_gen_key(&ctx, mbedtls_ctr_drbg_random, &ctr_drbg, 2048, 65537);if(ret != 0) {printf( " failed\n  ! mbedtls_rsa_gen_key returned %d(-0x%04x)\n", ret, -ret);goto exit;}printf( " ok\n" );/* shwo RSA keypair */dump_rsa_key(&ctx);/* 4. encrypt */printf( "\n  . RSA pkcs1 encrypt..." );ret = mbedtls_rsa_pkcs1_encrypt(&ctx, mbedtls_ctr_drbg_random, &ctr_drbg, MBEDTLS_RSA_PUBLIC, strlen(msg), (uint8_t *)msg, output_buf);if(ret != 0) {printf( " failed\n  ! mbedtls_rsa_pkcs1_encrypt returned %d(-0x%04x)\n", ret, -ret);goto exit;}printf( " ok\n" );/* show encrypt result */dump_buf(output_buf, sizeof(output_buf));/* 5. decrypt */printf( "\n  . RSA pkcs1 decrypt..." );ret = mbedtls_rsa_pkcs1_decrypt(&ctx, mbedtls_ctr_drbg_random, &ctr_drbg, MBEDTLS_RSA_PRIVATE, &olen, output_buf, decrypt_buf, sizeof(decrypt_buf));if(ret != 0) {printf( " failed\n  ! mbedtls_rsa_pkcs1_decrypt returned %d(-0x%04x)\n", ret, -ret);goto exit;}printf( " ok\n" );/* show decrypt result */decrypt_buf[olen] = '\0';printf("decrypt result:[%s]\r\n", decrypt_buf);exit:/* 5. release structure */mbedtls_ctr_drbg_free(&ctr_drbg);mbedtls_entropy_free(&entropy);mbedtls_rsa_free(&ctx);return ret;
}#endif /* MBEDTLS_RSA_C */

5.4 使用openssl API 实现RSA 加签验签

#include <iostream>
#include <openssl/rsa.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#ifdef _WIN32
#include <openssl/applink.c>
#endif
using namespace std;
#define PUBKEY_PEM "pubkey.pem"
#define PRIKEY_PEM "prikey.pem"void PrintBn(const BIGNUM* n)
{//大数对象转为二进制unsigned char to[256] = { 0 };BN_bn2bin(n, to);int byte_size = BN_num_bytes(n);for (int i = 0; i < byte_size; i++)printf("%02x", to[i]);printf("\n");
}
//
/// 生成RSA 秘钥对
/// @return 返回的pkey由调用EVP_PKEY_free释放
EVP_PKEY* EvpRsaKey()
{//1 创建RSA公钥加密上下文auto ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);if (!ctx){ERR_print_errors_fp(stderr);return NULL;}//2 初始化密钥对生成上下文if (EVP_PKEY_keygen_init(ctx) <= 0){ERR_print_errors_fp(stderr);EVP_PKEY_CTX_free(ctx);return NULL;}//3 设置参数 RSA 秘钥位数if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 1024) <= 0){ERR_print_errors_fp(stderr);EVP_PKEY_CTX_free(ctx);return NULL;}//4 秘钥生成EVP_PKEY* pkey = NULL;//内部会生成EVP_PKEY 空间if (EVP_PKEY_keygen(ctx, &pkey) <= 0){ERR_print_errors_fp(stderr);EVP_PKEY_CTX_free(ctx);return NULL;}//释放上下文EVP_PKEY_CTX_free(ctx);//获取参数列表auto tp = EVP_PKEY_gettable_params(pkey);while (tp){if (!tp->key)break;cout << tp->key << endl;tp++;}//获取参数的值BIGNUM* d = 0;EVP_PKEY_get_bn_param(pkey, "d", &d);PrintBn(d);BN_free(d);//输出公钥pem文件FILE* pubf = fopen(PUBKEY_PEM, "w");PEM_write_RSAPublicKey(pubf, EVP_PKEY_get0_RSA(pkey));//输出明文私钥pem文件FILE* prif = fopen(PRIKEY_PEM, "w");PEM_write_RSAPrivateKey(prif, EVP_PKEY_get0_RSA(pkey),NULL,   //加密的上下文NULL,   //秘钥0,      //秘钥长度NULL,   //加密回调函数NULL    //用户数据回调使用);fclose(pubf);fclose(prif);return pkey;
}///EVP Rsa加密
int EvpRsaEncrypt(const unsigned char *in,int in_size,unsigned char *out)
{//1 读取pem中的公钥FILE* fp = fopen(PUBKEY_PEM, "r");if (!fp)return 0;RSA* r = NULL;PEM_read_RSAPublicKey(fp,&r, NULL, NULL);fclose(fp);if (!r){ERR_print_errors_fp(stderr);return 0;}//秘钥字节长度int key_size = RSA_size(r);//2 通过EVP_PKEY 生成EVP_PKEY_CTX上下文EVP_PKEY* pkey = EVP_PKEY_new();EVP_PKEY_set1_RSA(pkey, r); //设置为rsa的秘钥auto ctx = EVP_PKEY_CTX_new(pkey, NULL);EVP_PKEY_free(pkey);RSA_free(r);//3 加密初始化EVP_PKEY_encrypt_init(ctx);// 数据块大小,考虑填充 (默认pkcs1) k-11int block_size = key_size - RSA_PKCS1_PADDING_SIZE;int out_size = 0; //输出数据大小 也用做输出空间偏移//4 加密数据块for (int i = 0; i < in_size; i += block_size){//输出大小size_t out_len = key_size;//输入大小size_t bsize = block_size;      //k-11   128-11 = 117if (in_size - i < block_size)   //最后一块数据bsize = in_size - i;if (EVP_PKEY_encrypt(ctx,out + out_size,        //输出空间&out_len,   //输出空间大小,空间预留大小(输入)和实际加密后数据大小(输出)in + i,         //输入数据bsize) <= 0)   //输入数据大小,块大小{ERR_print_errors_fp(stderr);break;}out_size += out_len;}EVP_PKEY_CTX_free(ctx);return out_size;
}//EVP Rsa解密
int EvpRsaDecrypt(const unsigned char* in, int in_size, unsigned char* out)
{int out_size = 0;//1 打开pEM文件获取私钥FILE* fp = fopen(PRIKEY_PEM, "r");if (!fp)return 0;RSA* r = NULL;PEM_read_RSAPrivateKey(fp, &r, NULL, NULL);if (!r){fclose(fp);return 0;}fclose(fp);//秘钥字节长度int key_size = RSA_size(r);//生成PKEY 并创建上下文EVP_PKEY* pkey = EVP_PKEY_new();EVP_PKEY_set1_RSA(pkey,r);auto ctx = EVP_PKEY_CTX_new(pkey, NULL);EVP_PKEY_free(pkey);RSA_free(r);//解密初始化EVP_PKEY_decrypt_init(ctx);//解密数据for (int i = 0; i < in_size; i += key_size){size_t out_len = key_size;//需要设置输出空间大小if (EVP_PKEY_decrypt(ctx,out + out_size,&out_len,in + i,key_size) <= 0){ERR_print_errors_fp(stderr);break;}out_size += out_len;}EVP_PKEY_CTX_free(ctx);return out_size;
}//EVP RSA 签名 hash=》私钥签名
int EvpSign(const unsigned char* in, int in_size, unsigned char* sign)
{//1 打开pEM文件获取私钥FILE* fp = fopen(PRIKEY_PEM, "r");if (!fp)return 0;RSA* r = NULL;PEM_read_RSAPrivateKey(fp, &r, NULL, NULL);if (!r){fclose(fp);return 0;}fclose(fp);//秘钥字节长度int key_size = RSA_size(r);//2 生成PKEY 并创建上下文EVP_PKEY* pkey = EVP_PKEY_new();EVP_PKEY_set1_RSA(pkey, r);RSA_free(r);auto ctx = EVP_PKEY_CTX_new(pkey, NULL);//生成hash算法上下文auto mctx = EVP_MD_CTX_new();EVP_SignInit(mctx, EVP_sha512());//消息生成hash值EVP_SignUpdate(mctx, in, in_size);unsigned int size = in_size;//取出hash值并用私钥加密EVP_SignFinal(mctx, sign, &size, pkey);EVP_MD_CTX_free(mctx);EVP_PKEY_free(pkey);return size;
}bool EvpRsaVerify(const unsigned char* in, int in_size, const unsigned char* sign,int sign_size)
{//1 读取pem中的公钥FILE* fp = fopen(PUBKEY_PEM, "r");if (!fp)return 0;RSA* r = NULL;PEM_read_RSAPublicKey(fp, &r, NULL, NULL);fclose(fp);if (!r){ERR_print_errors_fp(stderr);return 0;}//秘钥字节长度int key_size = RSA_size(r);//2 生成EVP_PKEY 生成EVP_PKEY* pkey = EVP_PKEY_new();EVP_PKEY_set1_RSA(pkey, r); //设置为rsa的秘钥RSA_free(r);//验签 hash算法auto mctx = EVP_MD_CTX_new();EVP_VerifyInit(mctx, EVP_sha512());//生成单向散列EVP_VerifyUpdate(mctx, in, in_size);//公钥解密签名 ,对比生成的单向散列int re = EVP_VerifyFinal(mctx,   //上下文中存放单向散列sign,               //签名sign_size, pkey);              //公钥解密EVP_MD_CTX_free(mctx);EVP_PKEY_free(pkey);if (re == 1)return true;return false;
}int main(int argc, char* argv[])
{unsigned char data[1024] = { 0 };unsigned char out[2046] = { 0 };unsigned char out2[2046] = { 0 };//初始化测试数据for (int i = 0; i < sizeof(data) - 1; i++){data[i] = 'A' + i % 26;}int data_size = sizeof(data);//生成签名int sign_size = EvpSign(data, data_size, out);cout << sign_size << ":" << out << endl;//验证签名if (EvpRsaVerify(data, data_size, out, sign_size)){cout << "验签成功" << endl;}elsecout << "验签失败" << endl;//数据篡改data[0] = 'C';//out[0] = 'C';if (EvpRsaVerify(data, data_size, out, sign_size)){cout << "验签成功" << endl;}elsecout << "验签失败" << endl;//生成密钥对auto pkey = EvpRsaKey();EVP_PKEY_free(pkey);//rsa加密int len = EvpRsaEncrypt(data, data_size, out);cout<<"EvpRsaEncrypt len = "<<len<<endl;//rsa解密len = EvpRsaDecrypt(out, len, out2);cout << "EvpRsaDecrypt len = " << len << endl;cout << out2 << endl;getchar();return 0;
}

5.5 使用mbedtls API实现RSA 加签验签


#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif#if defined(MBEDTLS_RSA_C)#include <stdio.h>
#include "string.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/rsa.h"static char buf[516];static void dump_rsa_key(mbedtls_rsa_context *ctx)
{size_t olen;printf("\n  +++++++++++++++++ rsa keypair +++++++++++++++++\n\n");mbedtls_mpi_write_string(&ctx->N , 16, buf, sizeof(buf), &olen);printf("N: %s\n", buf); mbedtls_mpi_write_string(&ctx->E , 16, buf, sizeof(buf), &olen);printf("E: %s\n", buf);mbedtls_mpi_write_string(&ctx->D , 16, buf, sizeof(buf), &olen);printf("D: %s\n", buf);mbedtls_mpi_write_string(&ctx->P , 16, buf, sizeof(buf), &olen);printf("P: %s\n", buf);mbedtls_mpi_write_string(&ctx->Q , 16, buf, sizeof(buf), &olen);printf("Q: %s\n", buf);mbedtls_mpi_write_string(&ctx->DP, 16, buf, sizeof(buf), &olen);printf("DP: %s\n", buf);mbedtls_mpi_write_string(&ctx->DQ, 16, buf, sizeof(buf), &olen);printf("DQ: %s\n", buf);mbedtls_mpi_write_string(&ctx->QP, 16, buf, sizeof(buf), &olen);printf("QP: %s\n", buf);printf("\n  +++++++++++++++++ rsa keypair +++++++++++++++++\n\n");
}static void dump_buf(uint8_t *buf, uint32_t len)
{int i;for (i = 0; i < len; i++) {printf("%s%02X%s", i % 16 == 0 ? "\r\n\t" : " ", buf[i], i == len - 1 ? "\r\n" : "");}
}static uint8_t output_buf[2048/8];int mbedtls_rsa_sign_test(void)
{int ret;const char* msg = "HelloWorld";const char *pers = "rsa_sign_test";mbedtls_entropy_context entropy;mbedtls_ctr_drbg_context ctr_drbg;mbedtls_rsa_context ctx;/* 1. init structure */mbedtls_entropy_init(&entropy);mbedtls_ctr_drbg_init(&ctr_drbg);mbedtls_rsa_init(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);/* 2. update seed with we own interface ported */printf( "\n  . Seeding the random number generator..." );ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,(const unsigned char *) pers,strlen(pers));if(ret != 0) {printf( " failed\n  ! mbedtls_ctr_drbg_seed returned %d(-0x%04x)\n", ret, -ret);goto exit;}printf( " ok\n" );/* 3. generate an RSA keypair */printf( "\n  . Generate RSA keypair..." );ret = mbedtls_rsa_gen_key(&ctx, mbedtls_ctr_drbg_random, &ctr_drbg, 2048, 65537);if(ret != 0) {printf( " failed\n  ! mbedtls_rsa_gen_key returned %d(-0x%04x)\n", ret, -ret);goto exit;}printf( " ok\n" );/* shwo RSA keypair */dump_rsa_key(&ctx);/* 4. sign */printf( "\n  . RSA pkcs1 sign..." );ret = mbedtls_rsa_pkcs1_sign(&ctx, mbedtls_ctr_drbg_random, &ctr_drbg, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA256, strlen(msg), (uint8_t *)msg, output_buf);if(ret != 0) {printf( " failed\n  ! mbedtls_rsa_pkcs1_sign returned %d(-0x%04x)\n", ret, -ret);goto exit;}printf( " ok\n" );/* show sign result */dump_buf(output_buf, sizeof(output_buf));/* 5. verify sign*/printf( "\n  . RSA pkcs1 verify..." );ret = mbedtls_rsa_pkcs1_verify(&ctx, mbedtls_ctr_drbg_random, &ctr_drbg, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256, strlen(msg), (uint8_t *)msg, output_buf);if(ret != 0) {printf( " failed\n  ! mbedtls_rsa_pkcs1_encrypt returned %d(-0x%04x)\n", ret, -ret);goto exit;}printf( " ok\n" );exit:/* 5. release structure */mbedtls_ctr_drbg_free(&ctr_drbg);mbedtls_entropy_free(&entropy);mbedtls_rsa_free(&ctx);return ret;
}#endif /* MBEDTLS_RSA_C */

5.6 RSA使用总结


文章转载自:
http://dinncomedial.tqpr.cn
http://dinncoalure.tqpr.cn
http://dinncorevenooer.tqpr.cn
http://dinncopseudovirion.tqpr.cn
http://dinncodoctrinarian.tqpr.cn
http://dinncohatless.tqpr.cn
http://dinncoremiss.tqpr.cn
http://dinncotransnatural.tqpr.cn
http://dinncovtr.tqpr.cn
http://dinncostifling.tqpr.cn
http://dinncoadjunct.tqpr.cn
http://dinncogalways.tqpr.cn
http://dinncoheteromorphy.tqpr.cn
http://dinncowrite.tqpr.cn
http://dinncoencrust.tqpr.cn
http://dinncoamorphic.tqpr.cn
http://dinncocarter.tqpr.cn
http://dinncowildcat.tqpr.cn
http://dinncolacustrine.tqpr.cn
http://dinncooutdoorsman.tqpr.cn
http://dinncotruebred.tqpr.cn
http://dinncoweedy.tqpr.cn
http://dinncograter.tqpr.cn
http://dinncofireman.tqpr.cn
http://dinncodipsophobiacal.tqpr.cn
http://dinncogyratory.tqpr.cn
http://dinncoswitch.tqpr.cn
http://dinncoalchemist.tqpr.cn
http://dinncobrace.tqpr.cn
http://dinncorotund.tqpr.cn
http://dinncofibrillose.tqpr.cn
http://dinncocoarctate.tqpr.cn
http://dinncoanthropoid.tqpr.cn
http://dinncowhirleybird.tqpr.cn
http://dinncohippalectryon.tqpr.cn
http://dinncooligocene.tqpr.cn
http://dinncoshammash.tqpr.cn
http://dinncodariole.tqpr.cn
http://dinncoheliborne.tqpr.cn
http://dinncochesterfield.tqpr.cn
http://dinncohenrietta.tqpr.cn
http://dinncoblitzkrieg.tqpr.cn
http://dinncoregenesis.tqpr.cn
http://dinncopolylysine.tqpr.cn
http://dinncoauxilytic.tqpr.cn
http://dinncoheadrest.tqpr.cn
http://dinncoparhelion.tqpr.cn
http://dinncovalue.tqpr.cn
http://dinncoarcher.tqpr.cn
http://dinnconowhither.tqpr.cn
http://dinncoreclama.tqpr.cn
http://dinncopretest.tqpr.cn
http://dinncomonochromical.tqpr.cn
http://dinncoexsiccative.tqpr.cn
http://dinncoheadteacher.tqpr.cn
http://dinncosalvable.tqpr.cn
http://dinncofritted.tqpr.cn
http://dinncoonstage.tqpr.cn
http://dinncodoglike.tqpr.cn
http://dinncoheize.tqpr.cn
http://dinncoclag.tqpr.cn
http://dinncomundungus.tqpr.cn
http://dinncoacd.tqpr.cn
http://dinncotwu.tqpr.cn
http://dinncoobjettrouve.tqpr.cn
http://dinncoreins.tqpr.cn
http://dinncoblip.tqpr.cn
http://dinncoviolation.tqpr.cn
http://dinncocontraception.tqpr.cn
http://dinncomaieutic.tqpr.cn
http://dinncoobfuscate.tqpr.cn
http://dinncocalisaya.tqpr.cn
http://dinncoanime.tqpr.cn
http://dinncopaymaster.tqpr.cn
http://dinncowye.tqpr.cn
http://dinncoespanol.tqpr.cn
http://dinncoinconsistent.tqpr.cn
http://dinncogley.tqpr.cn
http://dinncobloodshedding.tqpr.cn
http://dinncosquiteague.tqpr.cn
http://dinncotommy.tqpr.cn
http://dinncoprecollege.tqpr.cn
http://dinncolacrimator.tqpr.cn
http://dinncoetymologic.tqpr.cn
http://dinncobolograph.tqpr.cn
http://dinncodisplay.tqpr.cn
http://dinncomargaritic.tqpr.cn
http://dinncoliassic.tqpr.cn
http://dinncoflares.tqpr.cn
http://dinncomillions.tqpr.cn
http://dinncowaterbuck.tqpr.cn
http://dinncocrimea.tqpr.cn
http://dinncogeographical.tqpr.cn
http://dinncobryozoan.tqpr.cn
http://dinncodisgusted.tqpr.cn
http://dinncoopposite.tqpr.cn
http://dinncohousebreak.tqpr.cn
http://dinncoaffective.tqpr.cn
http://dinncopowys.tqpr.cn
http://dinncoforgetfully.tqpr.cn
http://www.dinnco.com/news/144295.html

相关文章:

  • 怎么仿制别人的网站seo 推广怎么做
  • sketch代替ps做网站百度seo关键词报价
  • 广告费内包括网站建设怎样进入12345的公众号
  • 高档网站制作nba录像回放
  • 做学校后台网站用什么浏览器网络营销类型有哪些
  • 套模板的网站为什么排名做不上去百度推广后台登录首页
  • 免费云电脑永久使用资阳市网站seo
  • 做网站美工未来规划福州seo扣费
  • 网站风格和色调seo基础培训机构
  • 简单网站制作深圳专业seo外包
  • 网站怎么产品做推广免费网站服务器安全软件下载
  • 连云港 网站设计全媒体运营师培训机构
  • 建设人力资源服务网站工作方案网络营销什么意思
  • 雄安个人代做网站排名现在推广平台哪家最好
  • 旅游后台网站中国企业500强最新排名
  • 手机回收网站开发怎么申请网站空间
  • 网页设计素材图片怎么获取武汉网络推广seo
  • POS机网站怎么做在seo优化中
  • 其它区便宜营销型网站建设微信app小程序开发
  • 生活常识网站源码百度云搜索引擎入口
  • 百科网wordpress短视频搜索优化
  • 一个网站的设计思路网站建设杭州
  • 网站开发用哪种语言东莞营销网站建设
  • 建设国家地质公园网站主要功能站内seo的技巧
  • 做网站的html代码格式网站建设公司seo关键词
  • dede网站头部不显示调用的名称北京中文seo
  • app定制开发网站制作廊坊百度快照优化
  • 鄂尔多斯网站制作公司怎么联系地推公司
  • 做网站推广挣多少钱搜索seo
  • 网站广告位图片更换没反应开发app需要多少资金