openssl+ RSA + linux 签名校验开发实例(C++)

一、RSA签名校验

RSA签名校验是一种用于验证数字签名的过程,它确保签名是由拥有相应私钥的合法实体创建的。以下是RSA签名校验的理论知识点:

  1. RSA密钥对: RSA签名使用一对公钥和私钥。公钥用于验证签名,私钥用于创建签名。

  2. 数字签名过程:

    • 消息哈希: 对要签名的消息进行哈希运算,通常使用SHA-256等哈希算法,以确保消息的唯一性和完整性。
    • 私钥签名: 使用私钥对消息的哈希值进行加密,形成数字签名。
  3. 数字签名校验过程:

    • 消息哈希: 接收到签名后,对原始消息进行相同的哈希运算,得到消息的哈希值。
    • 公钥验证: 使用签名者的公钥对数字签名进行解密,得到解密后的哈希值。
    • 比较哈希值: 将解密后的哈希值与原始消息的哈希值进行比较。如果相同,则签名验证通过,否则失败。
  4. RSA签名验证的数学基础:

    • RSA签名验证的关键是使用签名者的公钥进行解密。只有持有相应私钥的实体才能正确地对消息进行签名。
    • RSA的安全性基于大整数分解问题的难解性。在没有私钥的情况下,从签名中分解出原始哈希值的难度使得其他实体无法伪造合法的签名。
  5. 填充方案: 在实际应用中,为增加安全性,通常使用填充方案对消息进行填充。常见的填充方案包括PKCS#1 v1.5和OAEP。

  6. 常见错误:

    • 签名长度: 确保签名长度与RSA密钥长度相匹配。签名长度超过密钥长度时可能导致验证失败。
    • 密钥匹配: 使用正确的公钥进行验证,确保公钥和私钥匹配。
  7. 安全性注意事项:

    • 使用足够长的RSA密钥长度,通常建议使用2048位或更长的密钥。
    • 定期更新密钥对,以防止安全性降低。

理解以上理论知识有助于正确实现和使用RSA签名,并在应用中确保数据的安全性和完整性。

二、RSA签名校验开发实例

下面是一个简单的示例,演示如何使用OpenSSL库在Linux环境下进行RSA签名和验证。在这个示例中,我们使用PEM格式的密钥对进行签名和验证。

#include <iostream>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>

// 用于读取PEM格式的私钥文件
RSA* readPrivateKey(const char* privateKeyFile) {
    FILE* file = fopen(privateKeyFile, "r");
    if (!file) {
        perror("Error opening private key file");
        return nullptr;
    }

    RSA* rsa = PEM_read_RSAPrivateKey(file, nullptr, nullptr, nullptr);
    fclose(file);

    if (!rsa) {
        ERR_print_errors_fp(stderr);
    }

    return rsa;
}

// 对消息进行RSA签名
bool signMessage(const char* message, RSA* privateKey, unsigned char* signature, unsigned int* signatureLength) {
    EVP_PKEY* pkey = EVP_PKEY_new();
    EVP_PKEY_set1_RSA(pkey, privateKey);

    EVP_MD_CTX* ctx = EVP_MD_CTX_new();
    if (!ctx) {
        perror("Error creating context");
        EVP_PKEY_free(pkey);
        return false;
    }

    if (EVP_DigestSignInit(ctx, nullptr, EVP_sha256(), nullptr, pkey) != 1) {
        perror("Error initializing sign context");
        EVP_MD_CTX_free(ctx);
        EVP_PKEY_free(pkey);
        return false;
    }

    if (EVP_DigestSignUpdate(ctx, message, strlen(message)) != 1) {
        perror("Error updating sign context");
        EVP_MD_CTX_free(ctx);
        EVP_PKEY_free(pkey);
        return false;
    }

    if (EVP_DigestSignFinal(ctx, signature, signatureLength) != 1) {
        perror("Error finalizing sign context");
        EVP_MD_CTX_free(ctx);
        EVP_PKEY_free(pkey);
        return false;
    }

    EVP_MD_CTX_free(ctx);
    EVP_PKEY_free(pkey);

    return true;
}

// 验证RSA签名
bool verifySignature(const char* message, RSA* publicKey, const unsigned char* signature, unsigned int signatureLength) {
    EVP_PKEY* pkey = EVP_PKEY_new();
    EVP_PKEY_set1_RSA(pkey, publicKey);

    EVP_MD_CTX* ctx = EVP_MD_CTX_new();
    if (!ctx) {
        perror("Error creating context");
        EVP_PKEY_free(pkey);
        return false;
    }

    if (EVP_DigestVerifyInit(ctx, nullptr, EVP_sha256(), nullptr, pkey) != 1) {
        perror("Error initializing verify context");
        EVP_MD_CTX_free(ctx);
        EVP_PKEY_free(pkey);
        return false;
    }

    if (EVP_DigestVerifyUpdate(ctx, message, strlen(message)) != 1) {
        perror("Error updating verify context");
        EVP_MD_CTX_free(ctx);
        EVP_PKEY_free(pkey);
        return false;
    }

    int result = EVP_DigestVerifyFinal(ctx, signature, signatureLength);
    EVP_MD_CTX_free(ctx);
    EVP_PKEY_free(pkey);

    return (result == 1);
}

int main() {
    // 读取私钥
    const char* privateKeyFile = "private_key.pem";
    RSA* privateKey = readPrivateKey(privateKeyFile);
    if (!privateKey) {
        std::cerr << "Error loading private key" << std::endl;
        return 1;
    }

    // 待签名的消息
    const char* message = "Hello, RSA!";

    // 计算签名
    unsigned char signature[2048];  // 2048是RSA密钥长度
    unsigned int signatureLength;

    if (signMessage(message, privateKey, signature, &signatureLength)) {
        std::cout << "Signature created successfully" << std::endl;
    } else {
        std::cerr << "Error creating signature" << std::endl;
        RSA_free(privateKey);
        return 1;
    }

    // 读取公钥
    const char* publicKeyFile = "public_key.pem";
    RSA* publicKey = readPrivateKey(publicKeyFile);
    if (!publicKey) {
        std::cerr << "Error loading public key" << std::endl;
        RSA_free(privateKey);
        return 1;
    }

    // 验证签名
    if (verifySignature(message, publicKey, signature, signatureLength)) {
        std::cout << "Signature verified successfully" << std::endl;
    } else {
        std::cerr << "Error verifying signature" << std::endl;
    }

    // 释放资源
    RSA_free(privateKey);
    RSA_free(publicKey);

    return 0;
}

确保替换 private_key.pempublic_key.pem 为实际的私钥和公钥文件。这个示例中包含了签名和验证两个步骤。签名的结果可以被验证,以确保消息的完整性和真实性。

  • 21
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
你可以使用以下步骤进行Hash RSA签名,不需要调用OpenSSL库: 1. 选择一个适当的哈希算法,例如SHA-256。 2. 对待签名数据进行哈希,产生哈希值。 3. 使用私钥对哈希值进行RSA加密,产生签名。 下面是一个简单的示例代码: ```c #include <openssl/rsa.h> #include <openssl/sha.h> // 待签名数据 const char* data = "hello world"; // RSA私钥 const char* private_key = "-----BEGIN PRIVATE KEY-----\n" "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJbEJqrsJ4dRXtUQ\n" "jY5vqjBEyB+OQeZwKz3pU5F9Ml9LgJ0q9EJv+3q7KmDy2l0FqZRvLYJzXVp0y5Po\n" "Xnfd6J8G7z6Ko0kWESWlF7n6P5Wz4U7R2lJZu7PcK3umxu6z3j6iE4zX8pJZu1h6\n" "3YQqLdK7QG/kLXC5M+e9U2bEYKjFAgMBAAECgYBv2c0f1nIiPZv0eQ0ae+9z9lG\n" "RTI3T+mRJyj9VgGp3/9x2KkQzKkbK+Z9Q5JgJ06E5XaY7HbF9g0CkqDLv0Rg6W0L\n" "KsC9a42zsS5kZE9sF6OZwKvOwH+Y2H6uJj2cP8jVfH1ulEJv7UdZ8vJgvlgf7H3T\n" "ZJ5WVYQzJX3F4nF2uQJBAPuLZx4aXrWbmPl2BxLWg3YU3J0c7i+VZI3tVwzC3Zyh\n" "f7kW+H5QJnKp3zNRiV+9s2iXHwIrVP9Zw8v6TAZMj0kCQQCzSd9jNzSeEH+Y5fU/\n" "0yS8OSjN5f+3S3Q3L3zTbV9NnkZM4iFfVH7yQ3G4wrCoTtY0wPN2bHkWYjP0aMky\n" "R9pFAkEAzlrMxZmU8z8r8sWJ5sofEhm7Cj3Q3SRhUggdVZ+O3HDsJf8g3eM0K6WJ\n" "W8Rb5zDvJQzC4KdD2W9yA7OuS5IqkwJAL+Cd2Gd0K4e1WJkDgBqFHT0f/4lF5pP6\n" "z2sOgFLK5r8KZ6C5dGjA0tLr1Dn7Jx2tUj8LxhR1FFZ4XVx8D6kxKQJBAKvXg5xM\n" "E2KQ5fDdR7rYkWJ2R1eaF7fKzqj3XZVv5r/5j+2oTf4f7TEGc5GnH0hE9Ff2ZB4U\n" "aB7d+Pm8UwUZx7s=\n" "-----END PRIVATE KEY-----\n"; int main() { // 计算哈希值 unsigned char hash[SHA256_DIGEST_LENGTH]; SHA256_CTX sha256; SHA256_Init(&sha256); SHA256_Update(&sha256, data, strlen(data)); SHA256_Final(hash, &sha256); // 使用私钥进行RSA加密 RSA* rsa = RSA_new(); BIO* bio = BIO_new_mem_buf((void*)private_key, strlen(private_key)); rsa = PEM_read_bio_RSAPrivateKey(bio, &rsa, NULL, NULL); unsigned char* sign = (unsigned char*)malloc(RSA_size(rsa)); int len = RSA_private_encrypt(SHA256_DIGEST_LENGTH, hash, sign, rsa, RSA_PKCS1_PADDING); // 输出签名 for (int i = 0; i < len; i++) { printf("%02x", sign[i]); } printf("\n"); RSA_free(rsa); BIO_free_all(bio); free(sign); return 0; } ``` 这段代码使用SHA-256对待签名数据进行哈希,然后使用RSA私钥对哈希值进行加密,得到签名。你需要将`private_key`替换为自己的RSA私钥。注意,这段代码并没有进行任何错误处理和异常情况处理,你需要自己添加这些部分。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

N阶二进制

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值