Как подписать файл через Crypto ++ и RSA - PullRequest
1 голос
/ 21 октября 2019

Я пытаюсь подписать файл своим закрытым ключом, используя следующую функцию:

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));
}

В результате мой целевой файл перезаписывается подписью. Почему это происходит? Очевидно, я бы хотел добавить его в файл, поэтому я также добавил дополнительный параметр «true» для «putMessage».

1 Ответ

1 голос
/ 22 октября 2019
FileSource ss1(file.c_str(), true,
    new SignerFilter(rng, signer,
        new FileSink(file.c_str(), true), true));

Я [лично] никогда не видел, чтобы кто-то использовал один и тот же файл в качестве источника и приемника. Обычно данные файла и подпись разделяются, как с отдельной подписью.

Похоже, один файл / два потока определяется реализацией: C ++ читает и записывает в один и тот же файл, используя разные потоки . Полагаю, вам следует ожидать, казалось бы, случайных результатов на разных платформах.

В результате мой целевой файл будет перезаписан подписью. Почему это происходит?

FileSink открывается с std::ios_base::tunc. Также см. FileSink на вики-сайте Crypto ++.

Возможно, вам следует сделать что-то подобное. Сохраняет подпись в промежуточном 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;
}

Не вылетает и добавляет сообщение, как и ожидалось:

$ ./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{......|

Я не смог заставить это работать. Я почти уверен, что это тупик.

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));

Очевидно, я бы хотел добавить его в файл, поэтому ...

Кроме того, поскольку вы используете PSSR, вам не нужно исходное сообщение. PSSR является «вероятностной схемой подписи с восстановлением» . Сообщение включается в подпись с помощью функции маски.

Вам понадобится исходное сообщение со схемой SSA. SSA "схема подписи с приложением" . В схеме SSA вам необходимо предоставить как исходное сообщение, так и подпись.


(из комментариев) Вот пример, в котором используется Схема подписи с Приложением (SSA). Он также использует std::iftream и std::ofstream напрямую, поэтому FileSource и FileSink работают, как вы ожидаете. 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;
}

А затем:

$ ./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|

...