简体   繁体   English

如何通过 Crypto++ 和 RSA 签署文件

[英]How to sign a file via Crypto++ and RSA

I'm trying to sign a file with my private key using the following function:我正在尝试使用以下 function 使用我的私钥签署文件:

void Signer::SignFile(const std::string& file)
{
    RSASS<PSSR, Whirlpool>::Signer signer(rsaPrivate);

    // Encrypt and write
    FileSource ss1(file.c_str(), true,
        new SignerFilter(rng, signer,
                new FileSink(file.c_str(), true)
            , true));
}

As an outcome my target file gets overwritten with the signature.结果,我的目标文件被签名覆盖。 Why does that happen?为什么会这样? Obviously I'd like to append it to the file, that's why I also added an extra "true" parameter for the "putMessage".显然我想将 append 放到文件中,这就是为什么我还为“putMessage”添加了一个额外的“true”参数。

FileSource ss1(file.c_str(), true, new SignerFilter(rng, signer, new FileSink(file.c_str(), true), true));

I [personally] have never seen someone use the same file as a source and sink.我[个人]从未见过有人使用相同的文件作为源和接收器。 Usually the file data and signature are separate like with a detached signature.通常文件数据和签名是分开的,就像分离的签名一样。

It looks like one file/two streams is implementation defined: C++ read and write to same file using different streams .看起来一个文件/两个流是实现定义的: C++ read and write to same file using different streams I guess you should expect seemingly random results on different platforms.我想您应该期望在不同平台上出现看似随机的结果。

As an outcome my target file gets overwritten with the signature.结果,我的目标文件被签名覆盖。 Why does that happen?为什么会这样?

The FileSink opens with std::ios_base::tunc . FileSink打开std::ios_base::tunc Also see FileSink on the Crypto++ wiki.另请参阅 Crypto++ wiki 上的FileSink

You should probably do something like this.你可能应该做这样的事情。 It saves the signature to an intermediate ByteQueue , and then writes the queue to the file once the file is closed.它将签名保存到中间ByteQueue ,然后在文件关闭后将队列写入文件。

#include "cryptlib.h"
#include "filters.h"
#include "osrng.h"
#include "files.h"
#include "pssr.h"
#include "rsa.h"
#include "whrlpool.h"

#include <iostream>
#include <fstream>
#include <string>

int main(int argc, char* argv[])
{
    using namespace CryptoPP;
    AutoSeededRandomPool prng;
    std::string fname("test.bin");

    ///// Create test message /////
    {
    std::string msg("Yoda said, Do or do not. There is no try.");
    std::ofstream out(fname.c_str());
    out.write(msg.data(), msg.size());
    }

    ///// Generate a key /////
    RSASS<PSSR, Whirlpool>::Signer signer;
    signer.AccessKey().GenerateRandomWithKeySize(prng, 2048);

    ///// Sign the message /////
    ByteQueue queue;
    {
    FileSource source(fname.c_str(), true,
        new SignerFilter(prng, signer,
            new Redirector(queue)));
    }

    ///// Append the signature /////
    {
    std::ofstream out(fname.c_str(), std::ios_base::out | std::ios_base::binary | std::ios_base::app);
    queue.TransferTo(FileSink(out).Ref());
    }

    ///// Create a verifier /////
    RSASS<PSSR, Whirlpool>::Verifier verifier(signer);

    ///// Verify the message /////
    {
    FileSource source(fname.c_str(), true,
        new SignatureVerificationFilter(verifier, NULLPTR,
            SignatureVerificationFilter::THROW_EXCEPTION));
    }

    std::cout << "Verified signature on message" << std::endl;

    return 0;
}

It does not crash and it appends the message as expected:它不会崩溃,它会按预期附加消息:

$ ./test.exe
Verified signature on message

$ hexdump -C test.bin
00000000  59 6f 64 61 20 73 61 69  64 2c 20 44 6f 20 6f 72  |Yoda said, Do or|
00000010  20 64 6f 20 6e 6f 74 2e  20 54 68 65 72 65 20 69  | do not. There i|
00000020  73 20 6e 6f 20 74 72 79  2e 19 f2 1c 8f f9 cb 2f  |s no try......./|
00000030  f2 38 9f a8 3b a9 0b 8b  62 25 56 a8 ea 81 7e 60  |.8..;...b%V...~`|
00000040  22 55 38 ce 79 7f 32 95  a5 1a 75 c1 80 ad b2 c2  |"U8.y.2...u.....|
00000050  6f ce a5 f7 bd 4b d3 3f  e4 b3 69 00 21 60 d7 09  |o....K.?..i.!`..|
00000060  a8 71 9b 5f 41 d6 66 b1  80 f1 de 00 26 19 34 01  |.q._A.f.....&.4.|
00000070  b3 65 1b 78 e2 32 71 be  bc 07 25 78 36 6b 56 4e  |.e.x.2q...%x6kVN|
00000080  26 4e 12 9e a8 bb 72 86  ee 0d 70 b2 f1 bd a3 2c  |&N....r...p....,|
00000090  14 fd 12 61 35 98 4a 80  9f ee 3c 31 d3 70 26 0f  |...a5.J...<1.p&.|
000000a0  73 a0 5d 36 ef 96 56 65  f8 ac 3a fb 44 c3 04 76  |s.]6..Ve..:.D..v|
000000b0  e5 2f ae 92 84 be 40 34  f6 4b b8 84 aa bd 67 74  |./....@4.K....gt|
000000c0  05 43 91 d2 e6 b1 50 dd  6d 64 47 cc 3e 3c 3a 9d  |.C....P.mdG.><:.|
000000d0  67 ff 4f 38 c1 a5 a6 d5  92 45 bc 2d ff 96 30 3a  |g.O8.....E.-..0:|
000000e0  1d 3a 42 4f 8c 13 2d 4c  3f e9 ad 08 a6 b3 5e fa  |.:BO..-L?.....^.|
000000f0  46 08 24 17 43 ce ed ec  f7 1a 38 62 e7 bf 42 93  |F.$.C.....8b..B.|
00000100  84 44 b6 05 22 9e e3 bd  80 a6 08 b0 34 d0 a4 89  |.D..".......4...|
00000110  78 48 20 7f 7b 33 1c 51  9d 48 b5 b7 f7 de 2f dd  |xH .{3.Q.H..../.|
00000120  d7 74 7b af 04 cd 92 fc  1c                       |.t{......|

I was not able to get this to work.我无法让它工作。 I'm pretty sure it is a dead end.我很确定这是一个死胡同。

std::fstream inout(fname.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary | std::ios_base::app);
FileSource fs(inout, true,
    new SignerFilter(prng, signer,
        new FileSink(inout), true));

Obviously I'd like to append it to the file, that's why...显然我想将 append 放到文件中,这就是为什么......

Also, because you are using PSSR, you don't need the original message.此外,因为您使用的是 PSSR,所以不需要原始消息。 PSSR is "probabilistic signature scheme with recovery" . PSSR 是“具有恢复的概率签名方案” The message is include in the signature with a mask function.该消息包含在带有掩码 function 的签名中。

You would need the original message with a SSA scheme.您需要带有 SSA 方案的原始消息。 SSA is "signature scheme with appendix" . SSA 是“带有附录的签名方案” In a SSA scheme you need to provide both the original message and the signature.在 SSA 方案中,您需要同时提供原始消息和签名。


(From the comments) Here is an example that uses a Signature Scheme with Appendix (SSA). (来自评论)这是一个使用带有附录(SSA)的签名方案的示例。 It also uses std::iftream and std::ofstream directly so FileSource and FileSink work as you expect.它还直接使用std::iftreamstd::ofstream ,因此FileSourceFileSink可以按预期工作。 std::ofstream includes std::ios_base::app so the signature is appended. std::ofstream包括std::ios_base::app因此附加签名。

#include "cryptlib.h"
#include "filters.h"
#include "osrng.h"
#include "files.h"
#include "oaep.h"
#include "rsa.h"
#include "sha.h"

#include <iostream>
#include <fstream>
#include <string>

int main(int argc, char* argv[])
{
    using namespace CryptoPP;
    AutoSeededRandomPool prng;
    std::string fname("test.bin");

    ///// Create test message /////
    {
    std::string msg("Yoda said, Do or do not. There is no try.");
    std::ofstream out(fname.c_str());
    out.write(msg.data(), msg.size());
    }

    ///// Generate a key /////
    RSASS<PKCS1v15, SHA256>::Signer signer;
    signer.AccessKey().GenerateRandomWithKeySize(prng, 2048);

    {
    ///// Create fstreams for input and output /////
    std::ifstream fin(fname.c_str(), std::ios_base::in | std::ios_base::binary);
    std::ofstream fout(fname.c_str(), std::ios_base::out | std::ios_base::binary | std::ios_base::app);

    ///// Sign the message /////
    FileSource source(fin, true,
        new SignerFilter(prng, signer,
            new FileSink(fout)));
    }

    ///// Create a verifier /////
    RSASS<PKCS1v15, SHA256>::Verifier verifier(signer);

    ///// Verify the message /////
    {
    FileSource source(fname.c_str(), true,
        new SignatureVerificationFilter(verifier, NULLPTR,
            SignatureVerificationFilter::THROW_EXCEPTION));
    }

    std::cout << "Verified signature on message" << std::endl;

    return 0;
}

And then:接着:

$ ./test.exe
Verified signature on message

$ hexdump -C test.bin
00000000  59 6f 64 61 20 73 61 69  64 2c 20 44 6f 20 6f 72  |Yoda said, Do or|
00000010  20 64 6f 20 6e 6f 74 2e  20 54 68 65 72 65 20 69  | do not. There i|
00000020  73 20 6e 6f 20 74 72 79  2e c7 b3 6f 84 1d fd bf  |s no try...o....|
00000030  c7 c8 38 7c 89 b1 f3 42  ee 5e f8 10 de a8 01 7f  |..8|...B.^......|
00000040  7f a5 24 3d 27 7e 55 16  bc 80 8b 21 21 75 3d ed  |..$='~U....!!u=.|
00000050  41 05 84 b1 3d bf d3 ae  3a 2f a8 81 7a e7 e4 ae  |A...=...:/..z...|
00000060  50 d7 9b 25 04 17 a6 a3  1d 12 e2 8e cd 7a 02 42  |P..%.........z.B|
00000070  91 c0 d7 fc 43 09 94 a2  66 d9 67 95 55 5e dc 8c  |....C...f.g.U^..|
00000080  eb bc 20 af e8 5c d4 63  05 d4 2c 48 57 6d f1 fe  |.. ..\.c..,HWm..|
00000090  26 16 80 c3 41 11 58 8e  8d b0 cb 48 95 b9 ed 94  |&...A.X....H....|
000000a0  84 cc 86 0f a4 7e a3 6a  ff 0d 0d 24 17 82 13 94  |.....~.j...$....|
000000b0  54 cb 8a ca 04 1e 65 18  c3 ab a2 3f 4d 44 de 42  |T.....e....?MD.B|
000000c0  32 07 29 e4 95 83 cc ff  39 85 08 bf d5 61 46 db  |2.).....9....aF.|
000000d0  e0 96 d6 69 25 b9 ce 1e  3e bc 63 81 e5 16 bd 12  |...i%...>.c.....|
000000e0  a0 78 02 19 60 96 80 36  7d a5 79 be 0f 45 54 f4  |.x..`..6}.y..ET.|
000000f0  92 af f0 d8 74 65 7d 45  98 c7 bb 7f 6e 9b e3 cd  |....te}E....n...|
00000100  c0 60 91 0f 78 aa 7c 77  a7 f5 4e 7d 6e ed e1 4c  |.`..x.|w..N}n..L|
00000110  8e 5e 96 ac cd 30 16 e0  2d be 9e 2d 68 d4 25 46  |.^...0..-..-h.%F|
00000120  86 77 87 be 68 ef 06 26  55                       |.w..h..&U|

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM