RSA签名和验签

RSA(Rivest-Shamir-Adleman)是一种非对称加密算法,常用于数据的加密和数字签名。在C++中,可以使用OpenSSL库来实现RSA的签名和验签功能。以下是一个简单的示例代码,演示如何使用OpenSSL库进行RSA签名和验签:

示例代码:


```cpp
#include <iostream>
#include <string>
#include <vector>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>

// 生成RSA密钥对
RSA* generateRSAKey(int keyLength) {
    RSA* rsa = RSA_new();
    BIGNUM* bne = BN_new();
    unsigned long e = RSA_F4;

    if (BN_set_word(bne, e) != 1) {
        std::cerr << "Failed to set RSA exponent.\n";
        return nullptr;
    }

    if (RSA_generate_key_ex(rsa, keyLength, bne, NULL) != 1) {
        std::cerr << "Failed to generate RSA key pair.\n";
        RSA_free(rsa);
        BN_free(bne);
        return nullptr;
    }

    BN_free(bne);
    return rsa;
}

// RSA签名
std::string rsaSign(RSA* rsa, const std::vector<unsigned char>& data) {
    unsigned int siglen;
    unsigned char sigbuf[RSA_size(rsa)];
    
    if (RSA_sign(NID_sha256, data.data(), data.size(), sigbuf, &siglen, rsa) != 1) {
        std::cerr << "Failed to sign data.\n";
        return "";
    }

    return std::string(reinterpret_cast<char*>(sigbuf), siglen);
}

// RSA验签
bool rsaVerify(RSA* rsa, const std::vector<unsigned char>& data, const std::string& signature) {
    int ret = RSA_verify(NID_sha256, data.data(), data.size(), reinterpret_cast<const unsigned char*>(signature.c_str()), signature.length(), rsa);
    if (ret != 1) {
        std::cerr << "RSA verification failed.\n";
        return false;
    }
    return true;
}

int main() {
    // 生成RSA密钥对(实际应用中,应从文件或安全存储中加载)
    RSA* rsa = generateRSAKey(2048);
    if (!rsa) {
        std::cerr << "Failed to generate RSA key pair.\n";
        return 1;
    }

    // 要签名的数据
    std::string data = "Hello, RSA!";
    std::vector<unsigned char> dataVec(data.begin(), data.end());

    // RSA签名
    std::string signature = rsaSign(rsa, dataVec);
    if (signature.empty()) {
        RSA_free(rsa);
        return 1;
    }
    std::cout << "Signature: " << signature << std::endl;

    // RSA验签
    bool verified = rsaVerify(rsa, dataVec, signature);
    if (verified) {
        std::cout << "Signature verified successfully.\n";
    } else {
        std::cerr << "Signature verification failed.\n";
    }

    RSA_free(rsa);
    return 0;
}

注意事项:
安装 OpenSSL 库:确保系统中安装了 OpenSSL 库及其开发包。在 Ubuntu 中可以通过 sudo apt install libssl-dev 安装。

错误处理:示例中使用了简单的错误处理,实际应用中应根据情况增强错误检测和处理,特别是在处理加密和签名时。

密钥管理:在实际应用中,RSA 密钥对的生成和存储需要特别小心,通常会从安全的存储或密钥管理系统中加载和使用密钥。

签名算法:示例中使用了 SHA256 算法进行签名,可以根据需求选择其他哈希算法。

这段代码演示了RSA的基本签名和验签过程。在实际应用中,需要考虑到数据的安全传输、密钥的保护和管理,以及合理的错误处理机制。



不用OpenSSL :

如果你不想使用OpenSSL,完全可以自己实现RSA算法的签名和验签功能。RSA算法本身是公开的,关键在于理解其数学原理并正确地实现。下面我简要介绍一下如何用C++从头实现RSA签名和验签功能。

步骤概述:
生成RSA密钥对:使用大数运算库生成RSA公钥和私钥。
RSA签名:使用私钥对数据进行签名。
RSA验签:使用公钥对签名进行验证。
实现步骤:
1. 大数运算库选择
RSA涉及大数运算,需要使用支持大数的库。可以选择以下库之一:

GMP(GNU Multiple Precision Arithmetic Library)
Crypto++
这些库可以帮助处理大数运算,因为RSA算法中涉及到大整数的加密、解密、签名和验签操作。

2. 生成RSA密钥对
RSA密钥对由公钥和私钥组成。私钥用于签名,公钥用于验签。

```cpp
cpp
// 生成RSA密钥对
std::pair<BigInt, BigInt> generateRSAKeyPair(int keyLength) {
    BigInt p = generateLargePrime(keyLength / 2);   // 生成大素数 p
    BigInt q = generateLargePrime(keyLength / 2);   // 生成大素数 q

    BigInt n = p * q;                               // 计算 n = p * q
    BigInt phi = (p - 1) * (q - 1);                 // 计算 φ(n) = (p-1) * (q-1)

    BigInt e = generatePublicKeyExponent(phi);      // 生成公钥指数 e
    BigInt d = modularInverse(e, phi);              // 计算私钥 d,使得 (e * d) % phi == 1

    return std::make_pair(e, d);
}
3. RSA签名
使用私钥对数据进行签名。

cpp
// RSA签名
std::string rsaSign(const BigInt& privateKey, const std::vector<unsigned char>& data) {
    BigInt m = BigInt(data.data(), data.size());    // 将数据转换为大整数 m
    BigInt signature = modExp(m, privateKey, n);    // 计算签名 s = m^d mod n
    return signature.toString();                    // 返回签名的字符串表示
}
4. RSA验签
使用公钥对签名进行验证。

cpp
// RSA验签
bool rsaVerify(const BigInt& publicKey, const std::string& signatureStr, const std::vector<unsigned char>& data) {
    BigInt signature(signatureStr);                 // 将签名字符串转换为大整数
    BigInt m = BigInt(data.data(), data.size());    // 将数据转换为大整数 m
    BigInt decrypted = modExp(signature, publicKey, n);  // 计算解密后的值
    BigInt original(m);                             // 原始消息 m

    return decrypted == original;                   // 比较解密后的值与原始消息
}
  1. 大数运算函数实现
    你需要实现一些大数运算函数,如生成大素数、模幂运算(用于RSA的加密、解密和签名)、模逆运算等。这些函数通常是RSA算法实现的核心部分。

注意事项:
大数运算的精度:确保实现的大数运算库支持足够大的数值,以适应RSA算法的需求。
安全性考量:RSA算法的安全性依赖于生成安全的大素数和正确实现算法。
调试和测试:由于RSA算法涉及复杂的数学运算,调试和测试是非常重要的步骤。
总结
通过以上步骤,你可以开始从头实现RSA的签名和验签功能。这需要一定的数学和编程技能,但是理解了RSA的数学原理和正确实现后,你就可以不依赖外部库完整实现RSA功能

每次编译出可执行文件都需要签名可能并不必要,通常是在发布、部署或者升级时才进行签名。签名的目的是确保文件的完整性和来源可信。接下来我会给出一个简单的示例代码,展示如何在C++中使用 OpenSSL 库进行 RSA 数字签名和验证的过程。

签名过程示例(使用 OpenSSL 库):


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

// 函数声明
bool generateRSAKey(RSA *&rsa, int bits);
bool signData(const std::string &data, RSA *rsa, std::string &signature);
bool verifySignature(const std::string &data, const std::string &signature, RSA *rsa);

int main() {
    RSA *rsa = nullptr;
    std::string data = "Hello, world!";
    std::string signature;

    // 生成 RSA 密钥对
    if (!generateRSAKey(rsa, 2048)) {
        std::cerr << "Failed to generate RSA key pair." << std::endl;
        return 1;
    }

    // 签名数据
    if (!signData(data, rsa, signature)) {
        std::cerr << "Failed to sign data." << std::endl;
        RSA_free(rsa);
        return 1;
    }

    // 输出签名结果
    std::cout << "Signature: " << signature << std::endl;

    // 验证签名
    if (verifySignature(data, signature, rsa)) {
        std::cout << "Signature is valid." << std::endl;
    } else {
        std::cout << "Signature is invalid." << std::endl;
    }

    RSA_free(rsa);
    return 0;
}

bool generateRSAKey(RSA *&rsa, int bits) {
    BIGNUM *e = BN_new();
    RSA *temp_rsa = RSA_new();

    // 设置公钥指数 e
    if (!BN_set_word(e, RSA_F4)) {
        BN_free(e);
        return false;
    }

    // 生成 RSA 密钥对
    if (!RSA_generate_key_ex(temp_rsa, bits, e, nullptr)) {
        BN_free(e);
        RSA_free(temp_rsa);
        return false;
    }

    rsa = temp_rsa;
    BN_free(e);
    return true;
}

bool signData(const std::string &data, RSA *rsa, std::string &signature) {
    unsigned char hash[SHA256_DIGEST_LENGTH];
    SHA256(reinterpret_cast<const unsigned char *>(data.c_str()), data.length(), hash);

    unsigned int sig_len;
    unsigned char sig_out[RSA_size(rsa)];

    // 使用私钥签名
    if (!RSA_sign(NID_sha256, hash, SHA256_DIGEST_LENGTH, sig_out, &sig_len, rsa)) {
        return false;
    }

    // 将签名转换为字符串
    signature.assign(reinterpret_cast<const char *>(sig_out), sig_len);
    return true;
}

bool verifySignature(const std::string &data, const std::string &signature, RSA *rsa) {
    unsigned char hash[SHA256_DIGEST_LENGTH];
    SHA256(reinterpret_cast<const unsigned char *>(data.c_str()), data.length(), hash);

    // 将签名字符串转换为 unsigned char*
    const unsigned char *sig = reinterpret_cast<const unsigned char *>(signature.c_str());

    // 使用公钥验证签名
    int result = RSA_verify(NID_sha256, hash, SHA256_DIGEST_LENGTH, sig, signature.length(), rsa);

    if (result == 1) {
        return true; // 验证通过
    } else if (result == 0) {
        return false; // 签名不匹配
    } else {
        return false; // 出现错误
    }
}

示例解释:
generateRSAKey:生成 RSA 密钥对的函数。
signData:签名数据的函数,使用 SHA-256 哈希算法和 RSA 私钥。
verifySignature:验证签名的函数,使用 SHA-256 哈希算法和 RSA 公钥。
这段代码演示了如何使用 OpenSSL 库来进行 RSA 签名和验证操作。在实际应用中,你可以根据自己的需要进行调整和扩展,以适应你的具体场景和文件类型。
  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RSA数字签名的大致流程如下: 1. 首先需要生成RSA密钥对,包括公钥和私钥。 2. 对要签名的数据进行哈希处理。 3. 用私钥对哈希值进行加密,得到签名值。 4. 将签名值和原始数据一起发送给接收方。 5. 接收方用公钥对签名值进行解密,得到哈希值。 6. 对接收到的原始数据进行哈希处理,得到接收方计算出的哈希值。 7. 比较接收方计算出的哈希值和接收到的哈希值是否一致,如果一致,则表示签名验证成功。 下面是一个简单的RSA数字签名和验C++代码示例: ```c++ #include <iostream> #include <openssl/rsa.h> #include <openssl/pem.h> #include <openssl/err.h> #include <openssl/md5.h> using namespace std; // 生成RSA密钥对 RSA* generateRSAKey() { RSA* rsa = RSA_new(); BIGNUM* bne = BN_new(); BN_set_word(bne, RSA_F4); RSA_generate_key_ex(rsa, 2048, bne, NULL); return rsa; } // RSA数字签名 bool rsaSign(const char* data, size_t dataLen, RSA* rsa, unsigned char* sig, unsigned int* sigLen) { unsigned char md[MD5_DIGEST_LENGTH]; MD5((unsigned char*)data, dataLen, md); int ret = RSA_sign(NID_md5, md, MD5_DIGEST_LENGTH, sig, sigLen, rsa); return (ret == 1); } // RSA验签 bool rsaVerify(const char* data, size_t dataLen, RSA* rsa, unsigned char* sig, unsigned int sigLen) { unsigned char md[MD5_DIGEST_LENGTH]; MD5((unsigned char*)data, dataLen, md); int ret = RSA_verify(NID_md5, md, MD5_DIGEST_LENGTH, sig, sigLen, rsa); return (ret == 1); } int main() { // 生成RSA密钥对 RSA* rsa = generateRSAKey(); // 要签名的数据 char data[] = "Hello World!"; // RSA数字签名 unsigned char sig[1024]; unsigned int sigLen = 0; rsaSign(data, sizeof(data), rsa, sig, &sigLen); // RSA验签 bool result = rsaVerify(data, sizeof(data), rsa, sig, sigLen); if (result) { cout << "RSA verify success!" << endl; } else { cout << "RSA verify failed!" << endl; } RSA_free(rsa); return 0; } ``` 需要注意的是,本示例使用了OpenSSL库来实现RSA签名和验,使用前需要先安装OpenSSL库并链接到项目中。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值