首页 > 其他分享 >公钥私钥和模数指数相互转换

公钥私钥和模数指数相互转换

时间:2024-04-08 19:55:18浏览次数:20  
标签:公钥 私钥 drbg rsa ret 模数 mbedtls printf pk

  • pem 格式公钥私钥读取解析
  • 公钥 私钥 pem 格式加解密示例
  • 根据私钥 pem 生成 模数和指数 N E D
  • 生成 模数和指数 N E D 的公钥私钥
  • N E D 导出 pem 格式
#include <SylixOS.h>
#include <stdio.h>
#include <crypto.h>
#include <mbedtls/ssl.h>
#include <mbedtls/platform.h>
#include <mbedtls/entropy.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/base64.h>
#include "libcrypto.h"
#define  CRYPTO_TEST_EN                 (1)                             /*  测试模块开关宏              */
#include <crypto_test.h>

#define ROUND_UP(x, align) (size_t)(((size_t)(x) +  (align - 1)) & ~(align - 1))
void printhex(char *name, UINT8 *data, size_t size);


/**
   公钥由模数 N 和公钥指数 E 组成,通常以如下形式表示:
   [ (N, E) ]

   私钥则包含模数 N、私钥指数 D,以及可能还包括原始素数 p 和 q,以防需要重新计算其他参数。
   私钥通常以如下形式表示:
    [ (N, D, p, q) ]
*/
#define BUFFER_SIZE 256
/**
 * 使用公钥私钥验证加密数据
*/
INT test_rsa_encry(void)
{
    int ret;
    mbedtls_pk_context priv_key, pub_key;
    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;
    mbedtls_rsa_context *rsa;
    unsigned char encrypted[BUFFER_SIZE], decrypted[BUFFER_SIZE];
    unsigned char *input = "hello world! \r\n";
    size_t olen, ilen = strlen(input);
    // const char *pers = "rsa_encrypt_decrypt_example";
    const char *pers = "rsa_key_generation";

    mbedtls_pk_init(&priv_key);
    mbedtls_pk_init(&pub_key);
    mbedtls_entropy_init(&entropy);
    mbedtls_ctr_drbg_init(&ctr_drbg);

    // 1. 加载RSA私钥和公钥
    ret = mbedtls_pk_parse_keyfile(&priv_key, "./prikey.txt", NULL);
    if (ret != 0) {
        printf("Failed to parse private key file: -0x%04x\n", -ret);
        goto exit;
    }

    ret = mbedtls_pk_parse_public_keyfile(&pub_key, "./pubkey.txt");
    if (ret != 0) {
        printf("Failed to parse public key file: -0x%04x\n", -ret);
        goto exit;
    }

    mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *)pers, strlen(pers));

    // 3. 使用私/公钥加密消息
    // ret = mbedtls_rsa_pkcs1_encrypt(mbedtls_pk_rsa(priv_key), mbedtls_ctr_drbg_random, &ctr_drbg, MBEDTLS_RSA_PRIVATE, ilen, input, encrypted);
    ret = mbedtls_rsa_pkcs1_encrypt(mbedtls_pk_rsa(pub_key), mbedtls_ctr_drbg_random, &ctr_drbg, MBEDTLS_RSA_PUBLIC, ilen, input, encrypted);
    if (ret != 0) {
        printf("Failed to encrypt text: -0x%04x\n", -ret);
        goto exit;
    }

    printhex("encrypted", encrypted, sizeof(encrypted));

    // 4. 使用公/私钥解密消息
    olen = BUFFER_SIZE;
    // ret = mbedtls_rsa_pkcs1_decrypt(mbedtls_pk_rsa(pub_key), mbedtls_ctr_drbg_random, &ctr_drbg, MBEDTLS_RSA_PUBLIC, &olen, encrypted, decrypted, BUFFER_SIZE);
    ret = mbedtls_rsa_pkcs1_decrypt(mbedtls_pk_rsa(priv_key), mbedtls_ctr_drbg_random, &ctr_drbg, MBEDTLS_RSA_PRIVATE, &olen, encrypted, decrypted, BUFFER_SIZE);
    if (ret != 0) {
        printf("Failed to decrypt text: -0x%04x\n", -ret);
        goto exit;
    }

    printf("encode data size: %d \n", olen);

    decrypted[olen] = '\0'; // Add null terminator for printing as a string
    printf("Decrypted message: %s\n", decrypted);

exit:
    mbedtls_pk_free(&priv_key);
    mbedtls_pk_free(&pub_key);
    mbedtls_entropy_free(&entropy);
    mbedtls_ctr_drbg_free(&ctr_drbg);

    return ret;
}

/**
 * 将 pem 格式的私钥 转换成对应的 rsa (N E D)
*/
INT test_pem_to_rsa(void)
{
    int ret;
    mbedtls_pk_context pk;
    mbedtls_rsa_context *rsa;
    unsigned char *p, *end;
    size_t len;

    mbedtls_pk_init(&pk);

    // 1. 加载PEM格式的私钥文件
    ret = mbedtls_pk_parse_keyfile(&pk, "./prikey.txt", NULL);
    if (ret != 0) {
        printf("Failed to parse private key file: -0x%04x\n", -ret);
        return -1;
    }

    // 2. 确保解析出的密钥是RSA类型
    if (mbedtls_pk_get_type(&pk) != MBEDTLS_PK_RSA) {
        printf("Private key is not an RSA key.\n");
        return -1;
    }

    // 3. 获取RSA上下文
    rsa = mbedtls_pk_rsa(pk);

    // 4. 解析 N、D、E 参数
    const mbedtls_mpi *N = &rsa->N;
    const mbedtls_mpi *E = &rsa->E;
    const mbedtls_mpi *D = &rsa->D;

    printf("E: %zu bits, 8 algin: %zu, n: %zu \n", mbedtls_mpi_bitlen(E), ROUND_UP(mbedtls_mpi_bitlen(E), 8), E->n);
    printf("N: %zu bits, 8 algin: %zu, n: %zu \n", mbedtls_mpi_bitlen(N), ROUND_UP(mbedtls_mpi_bitlen(N), 8), N->n);
    printf("D: %zu bits, 8 algin: %zu, n: %zu \n", mbedtls_mpi_bitlen(D), ROUND_UP(mbedtls_mpi_bitlen(D), 8), D->n);

    printhex("E", (UINT8 *)E->p, ROUND_UP(mbedtls_mpi_bitlen(E), 8)/8);
    printhex("N", (UINT8 *)N->p, ROUND_UP(mbedtls_mpi_bitlen(N), 8)/8);
    printhex("D", (UINT8 *)D->p, ROUND_UP(mbedtls_mpi_bitlen(D), 8)/8);

    // 清理资源
    mbedtls_pk_free(&pk);

    return 0;
}
/**
 * 写文件
*/
int test_write_to_file(char *filename, char *buff, int size)
{
    int fd = open(filename, O_RDWR | O_CREAT);
    if (fd < 0) {
        printf("open file %s failed! \n", filename);
        return  -1;
    }

    if (write(fd, buff, size) < 0) {
        printf("write file %s failed! \n", filename);
        return  -1;
    }

    close(fd);

    return  0;
}

#define MAX_PUBKEY_PEM_LEN 1024
#define MAX_PRIKEY_PEM_LEN 2048
/**
 * 将 rsa (N E D) 格式 导出 pem 格式的公私钥
*/
INT test_export_rsa_pem(mbedtls_rsa_context *rsa)
{
    mbedtls_pk_context pk;

    unsigned char pubkey_pem[MAX_PUBKEY_PEM_LEN];
    unsigned char prikey_pem[MAX_PRIKEY_PEM_LEN];
    int ret;

    // 初始化pk上下文
    mbedtls_pk_init(&pk);

    // 设置 PK 上下文为 RSA
    mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));

    // 获取 PK 上下文的 RSA 字段并设置 RSA 上下文
    mbedtls_rsa_copy(mbedtls_pk_rsa(pk), rsa);

    // 写入PEM公钥字符串
    ret = mbedtls_pk_write_pubkey_pem(&pk, pubkey_pem, MAX_PUBKEY_PEM_LEN);
    if (ret != 0) {
        printf("Error writing PEM public key: -0x%04x\n", -ret);
        return -1;
    }

    // 打印PEM公钥字符串
    printf("PEM Public Key:\n%s\n", pubkey_pem);

    // 导出私钥
    ret = mbedtls_pk_write_key_pem(&pk, prikey_pem, MAX_PRIKEY_PEM_LEN);
    if (ret != 0) {
        printf("Error writing PEM private key: -0x%04x\n", -ret);
        return -1;
    }

    printf("PEM Private Key:\n%s\n", prikey_pem);

    // 导出文件
    test_write_to_file("./pubkey.txt", pubkey_pem, strlen(pubkey_pem));
    test_write_to_file("./prikey.txt", prikey_pem, strlen(prikey_pem));

    // 读取验证
    if(test_pem_to_rsa() < 0) {
        printf("check failed! \n");
    }

    // 清理资源
    mbedtls_pk_free(&pk);

    return  0;
}

// #define KEY_BITS 2048 // 生成的RSA密钥位数,可以根据需要调整
#define KEY_BITS 4096 // 生成的RSA密钥位数,可以根据需要调整
/**
 * 生成 N E D 模数和指数
*/
int test_rsa_gen_N_E_D(void)
{
    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;
    mbedtls_rsa_context rsa;

    mbedtls_entropy_init(&entropy);
    mbedtls_ctr_drbg_init(&ctr_drbg);

    // 为熵源和DRBG提供种子
    const char personalization[] = "rsa_key_generation";
    if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
                               (const unsigned char *) personalization,
                               sizeof(personalization)) != 0) {
        printf("Failed to seed DRBG.\n");
        return -1;
    }

    mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0);

    // 生成新的RSA公私钥对
    if (mbedtls_rsa_gen_key(&rsa, mbedtls_ctr_drbg_random, &ctr_drbg, KEY_BITS,
                            65537) != 0) {
        printf("Failed to generate RSA key pair.\n");
        return -1;
    }

    // 获取模数N和指数E
    const mbedtls_mpi *N = &rsa.N;
    const mbedtls_mpi *E = &rsa.E;
    const mbedtls_mpi *D = &rsa.D;

    printf("E: %zu bits, 8 algin: %zu, n: %zu \n", mbedtls_mpi_bitlen(E), ROUND_UP(mbedtls_mpi_bitlen(E), 8), E->n);
    printf("N: %zu bits, 8 algin: %zu, n: %zu \n", mbedtls_mpi_bitlen(N), ROUND_UP(mbedtls_mpi_bitlen(N), 8), N->n);
    printf("D: %zu bits, 8 algin: %zu, n: %zu \n", mbedtls_mpi_bitlen(D), ROUND_UP(mbedtls_mpi_bitlen(D), 8), D->n);

    printhex("E", (UINT8 *)E->p, ROUND_UP(mbedtls_mpi_bitlen(E), 8)/8);
    printhex("N", (UINT8 *)N->p, ROUND_UP(mbedtls_mpi_bitlen(N), 8)/8);
    printhex("D", (UINT8 *)D->p, ROUND_UP(mbedtls_mpi_bitlen(D), 8)/8);

    // 导出 pem 格式
    test_export_rsa_pem(&rsa);

    mbedtls_rsa_free(&rsa);
    mbedtls_ctr_drbg_free(&ctr_drbg);
    mbedtls_entropy_free(&entropy);

    return 0;
}

/**
 * rsa (根据 N E D 加解密测试) 硬件加速测试
*/
INT test_N_E_D_encry_hw(void)
{
    int                    fd;
    UINT32                 uiDataSize   = 4096 / 8;
    UINT8                 *pucHardOut   = NULL;
    UINT8                 *pucHardOut1  = NULL;
    UINT8                 *pucSignIn    = NULL;
    UINT8                 *pucETmp      = NULL;
    CRYPTO_RSA_KEY         rsaKey;

    fd = open("/dev/crypto0", O_RDWR);
    if (fd < 0) {
        printf("open /dev/crypto0 failed, ecode: %d\n", errno);
        return -1;
    }

    pucHardOut = (UINT8 *)sys_malloc_align(uiDataSize*3, CONFIG_SYS_CACHELINE_SIZE);
    if (!pucHardOut) {
        printf("%s, %d: malloc %u error!\n", __func__, __LINE__, uiDataSize);
        goto  __exit;
    }

    lib_memset(pucHardOut, 0x0, uiDataSize*3);

    pucHardOut1 = pucHardOut + uiDataSize;
    pucETmp     = pucHardOut + uiDataSize*2;
    
    pucSignIn   = (UINT8 *)sys_malloc_align(512, CONFIG_SYS_CACHELINE_SIZE);
    if (!pucSignIn) {
        printf("%s, %d: malloc %u error!\n", __func__, __LINE__, uiDataSize);
        goto  __free_hardout;
    }

    lib_memset(pucSignIn, 0x0, 512);
    pucSignIn[0] = 0xAA;
    pucSignIn[1] = 0xBB;
    pucSignIn[2] = 0xCC;

    lib_memset(&rsaKey, 0x00, sizeof(rsaKey));
                                                                        /*  (N, D) 私钥加密             */
    rsaKey.uiAlgo = CRYPTO_RSA4096;
    rsaKey.puiN   = (UINT32 *)_G_cpucRsa4096_N;
    rsaKey.puiE   = (UINT32 *)_G_cpucRsa4096_D;

    printhex("sign in", pucSignIn, 512);

    if (crypto_rsa_verify(fd, &rsaKey, pucSignIn, pucHardOut)) {
        printf("crypto_rsa_verify error! errcode: %d.\n", errno);
        goto  __free_signin;
    }

    printhex("sign out", pucHardOut, 512);

    lib_memset(&rsaKey, 0x00, sizeof(rsaKey));
    lib_memcpy(pucETmp, _G_cpucRsa4096_E, sizeof(_G_cpucRsa4096_E));
                                                                        /*  (N, E) 公钥解密             */
    rsaKey.uiAlgo = CRYPTO_RSA4096;
    rsaKey.puiN   = (UINT32 *)_G_cpucRsa4096_N;
    rsaKey.puiE   = (UINT32 *)pucETmp;

    if (crypto_rsa_verify(fd, &rsaKey, pucHardOut, pucHardOut1)) {
        printf("crypto_rsa_verify error\n");
        goto  __free_signin;
    }

    printhex("verfiy out", pucHardOut1, 512);
    if (lib_memcmp(pucHardOut1, pucSignIn, 512) == 0) {
        printf("verfiy success!\n");
    } else {
        printf("verfiy failed!\n");
    }

__free_signin:
    sys_free(pucSignIn);

__free_hardout:
    sys_free(pucHardOut);

__exit:
    close(fd);

    return 0;
}

INT main(int argc, char const *argv[])
{
    test_rsa_gen_N_E_D();

    // test_N_E_D_encry_hw(fd);

    // test_rsa_encry();


    return 0;
}

void printhex(char *name, UINT8 *data, size_t size)
{
    int i = 0; 
    printf("\n%s:\n", name);
    for (i = 0; i < size; i++) {
        printf("%02x ", data[i]);
        if (i % 16 == 15) {
            printf("\n");
        }
    }
    printf("\n");
}

标签:公钥,私钥,drbg,rsa,ret,模数,mbedtls,printf,pk
From: https://www.cnblogs.com/han-guang-xue/p/18122413

相关文章

  • web渗透-SSH私钥泄露
    发现主机netdiscover-r192.168.164.0扫描端口看到开放80和31337端口都为http服务 浏览器访问测试查看80端口和31337端口网页和源代码并无发现有用信息 目录扫描 扫描出80端口并无有用信息扫描31337端口发现敏感文件robots.txt和目录.ssh 访问敏感文件和目......
  • App备案-iOS证书 Distribution Managed 公钥及证书SHA-1指纹的获取方法
    IOS平台App备案,apple不提供云管理式证书的下载,也就无法获取公钥及证书SHA-1指纹。  已经上架的应用不想重新打包发布的话。可以通过以下方法获取证书Certificate:访问AppleDeveloper(简体中文),使用App对应的iOS开发者账号登录。 苹果开发者账号地址 https://developer.......
  • SecureCRT通过私钥连接跳板机,再连接到目标服务器
    文章目录1.配置第一个session(跳板机)2.设置本地端口3.设置全局firewall4.配置第二个session(目标服务器)服务器那边给了一个私钥,现在需要通过私钥连接跳板机,再连接到目标服务器上......
  • scp与pscp公私钥条件下的文件传输
    一、常见用法scp是SecureCopyProtocol(安全复制协议)的缩写,可以在本地系统和远程系统之间复制文件,同时提供了数据加密和压缩功能,以确保数据在传输过程中的安全性和完整性。pscp是putty系列的工具,可以用在window平台作为scp的替代。远程>>本地[email protected]:/opt/s......
  • SSH中私钥和公钥的使用
    在SSH(SecureShell)中,密钥对用于加密和身份验证,保证了远程会话的安全。一个密钥对包括两部分:公钥和私钥。它们有不同的作用和特性:私钥私钥是一个用户保密的密钥,它绝不能被泄露或分享给其他人。保存在用户的本地计算机上,用于SSH进行安全的认证。通常由SSH客户端软件生成并......
  • iOS、Android获取apk公钥MD5信息
    背景国家工信部规定,所有国内在线或即将上线的APP做备案,否则无法通过域名访问。其中iOS和Android备案所需的APP相关信息我们不能直接明文获取,有公钥,MD5,包名,APP名,接口服务的域名等对于iOS端,如果是开发者,直接在苹果的证书管理网站上下载证书到本地打开,即可获得。参考对于Androi......
  • VScode 配置私钥免密登录
    VScode配置私钥免密登录配置公钥私钥进行免密登录在前文已经提及。在完成上述配置后,我们希望在VScode中配置,毕竟主要的开发环境还是在VScode上且连接到远程服务器会经常遇到网络不稳定需要重新输入密码登录的情况,所以更加凸显了配置私钥的必要性。前提条件本地主机中已有配置......
  • ubuntu22 安装ROS 解决公钥问题和源问题
    最近在做路径规划的东西,装这个ROS太费劲了,记录一下#设定环境sudoaptupdate&&sudoaptinstalllocalessudolocale-genen_USen_US.UTF-8sudoupdate-localeLC_ALL=en_US.UTF-8LANG=en_US.UTF-8exportLANG=en_US.UTF-8sudoaptinstallsoftware-properties-comm......
  • 利用openssl生成SM2公私钥对
      openssl1.1.1+版本增加了对SM2的支持,所以我们就能直接使用这些版本的opsnssl生成SM2的公私钥对。首先我们得在Linux或者Windows服务器中安装对应版本的openssl库,具体过程略。软件包请到官网下载:https://www.openssl.org/安装完成后,使用下列命令查看该版本的op......
  • 数据规模:如何处理大规模数据集
    1.背景介绍1.1数据的爆炸式增长随着互联网的普及和物联网的发展,数据量呈现出爆炸式增长。据统计,全球每天产生的数据量已经达到2.5亿GB,预计到2025年,全球数据总量将达到175ZB。这些数据包括社交媒体、电子商务、物联网设备、科学研究等各个领域的数据。如何有效地处理和分......