如何使用CryptoPP通过公钥验证带签名PNG文件的正确性?
提取ECDSA签名并验证文件有效性的方法
核心逻辑
老师生成md5.png的规则是:原始hello.png的二进制数据直接拼接ECDSA<ECP,SHA1>签名数据。所以md5.png的前半段完全等于hello.png的内容,后半段就是签名。只需先确定原始文件的字节长度,就能拆分出签名并验证。
具体操作步骤
1. 获取原始文件的字节长度
先拿到hello.png的准确大小:
- Linux/macOS执行命令:
ls -l hello.png | awk '{print $5}' - Windows执行命令:
dir hello.png
记录下这个数值(比如假设为12345字节)。
2. 从md5.png中拆分出签名
用工具把md5.png的前N字节(N为原始文件长度)分离出来(可选,用于验证和原始文件一致),剩余部分就是签名:
- Linux/macOS用
dd命令:# 提取原始图片内容(可选验证用) dd if=md5.png of=extracted_hello.png bs=1 count=12345 # 提取签名数据到文件 dd if=md5.png of=signature.bin bs=1 skip=12345 - Windows用PowerShell:
$fileBytes = Get-Content md5.png -Raw -Encoding Byte $originalLen = 12345 # 提取签名并保存 $signatureBytes = $fileBytes[$originalLen..($fileBytes.Length-1)] Set-Content signature.bin -Value $signatureBytes -Encoding Byte
3. 用CryptoPP验证签名
编写C++代码,使用老师提供的公钥验证原始文件和签名的匹配性:
#include <iostream> #include <fstream> #include <cryptopp/eccrypto.h> #include <cryptopp/sha.h> #include <cryptopp/base64.h> #include <cryptopp/files.h> using namespace CryptoPP; int main(int argc, char* argv[]) { if (argc != 4) { std::cerr << "Usage: ./verify <public_key_file> <original_file> <signature_file>" << std::endl; return 1; } // 加载Base64编码的公钥 ECDSA<ECP, SHA1>::PublicKey publicKey; FileSource pubFile(argv[1], true, new Base64Decoder); publicKey.Load(pubFile); // 读取原始文件二进制内容 std::string originalData; FileSource origFile(argv[2], true, new StringSink(originalData)); // 读取签名二进制数据 std::string signature; FileSource sigFile(argv[3], true, new StringSink(signature)); // 执行签名验证 ECDSA<ECP, SHA1>::Verifier verifier(publicKey); bool isValid = verifier.VerifyMessage( reinterpret_cast<const byte*>(originalData.data()), originalData.size(), reinterpret_cast<const byte*>(signature.data()), signature.size() ); std::cout << (isValid ? "Signature is valid!" : "Signature is invalid!") << std::endl; return isValid ? 0 : 1; }
编译时链接CryptoPP库:
g++ verify.cpp -o verify -lcryptopp
对每个md5.png重复步骤2和3,找到验证输出Signature is valid!的文件即可。
注意事项
- 确保
hello.png未被修改,否则所有验证都会失败。 - ECDSA<ECP,SHA1>的签名长度固定(对应所选椭圆曲线的大小,比如P-256曲线签名为64字节),若拆分出的签名长度不符,说明原始文件长度取值错误。
内容的提问来源于stack exchange,提问作者abcd1211231
相关产品推荐
相关产品推荐

