3

I'm trying to protect a 2048-bit RSA private key (confidentiality & availability). I have been looking around for more information on how to do that and I'm thinking of using a secret sharing scheme (Shamir's Secret Sharing would be fine).

Is it the best option ? Does anyone know a GNU/GPL software implementation in order to accomplish this ?

I look at "ssss" (http://point-at-infinity.org/ssss/), but secret need to be at most 128 ASCII characters and it's too short for a 2048-bit RSA private key.

Thanks for your help.

cashel
  • 31
  • 1
  • 1
    Back up a couple of steps. What are you really trying to do? The whole point of public key cryptography, like RSA, is to avoid having to share private keys. There's probably a more sensible way to achieve your underlying goal here, whatever that is. – Neil Forrester Jan 08 '14 at 17:47
  • I'm trying to avoid to store the private key of a root CA. This key is very rarely used but most of the time, I need a very effective way to protect it. – cashel Jan 08 '14 at 21:49
  • Not a programming question, so off topic here. – Maarten Bodewes Jan 08 '14 at 23:03

2 Answers2

3

Just as with public-key cryptography, you occasionally need to use a hybrid scheme when the data exceeds a certain size - you can encrypt the private key using a normal symmetric algorithm with a random key, and then split the symmetric key using a secret-splitting algorithm of choice.

I believe that the implementation here: https://github.com/moserware/SecretSplitter uses this method to split data that exceeds the size limit of the underlying splitting algorithm.

Iridium
  • 23,323
  • 6
  • 52
  • 74
  • Look under "Notes" in the ssss documentation. Same answer, just different words + an example: http://point-at-infinity.org/ssss/ssss.1.html – Raine Revere Nov 16 '16 at 23:42
0

Is it the best option ? Does anyone know a GNU/GPL software implementation in order to accomplish this ?

Crypto++ offers the functionality. But the license is Public Domain (individual source files) or Boost Software 1.0 (library as a whole). Its not GNU/GPL.

Here's the code to do it from Crypto++. It was taken from test.cpp:

Splitting

void SecretShareFile(int threshold, int nShares, const char *filename, const char *seed)
{
    RandomPool rng;
    rng.IncorporateEntropy((byte *)seed, strlen(seed));

    ChannelSwitch *channelSwitch;
    FileSource source(filename, false, new SecretSharing(rng,
        threshold, nShares, channelSwitch = new ChannelSwitch));

    vector_member_ptrs<FileSink> fileSinks(nShares);
    string channel;
    for (int i=0; i<nShares; i++)
    {
        char extension[5] = ".000";
        extension[1]='0'+byte(i/100);
        extension[2]='0'+byte((i/10)%10);
        extension[3]='0'+byte(i%10);
        fileSinks[i].reset(new FileSink((string(filename)+extension).c_str()));

        channel = WordToString<word32>(i);
        fileSinks[i]->Put((byte *)channel.data(), 4);
        channelSwitch->AddRoute(channel, *fileSinks[i], DEFAULT_CHANNEL);
    }

    source.PumpAll();
}

Combining

void SecretRecoverFile(int threshold, const char *outFilename, char *const *inFilenames)
{
    SecretRecovery recovery(threshold, new FileSink(outFilename));

    vector_member_ptrs<FileSource> fileSources(threshold);
    SecByteBlock channel(4);
    int i;
    for (i=0; i<threshold; i++)
    {
        fileSources[i].reset(new FileSource(inFilenames[i], false));
        fileSources[i]->Pump(4);
        fileSources[i]->Get(channel, 4);
        fileSources[i]->Attach(new ChannelSwitch(recovery, string((char *)channel.begin(), 4)));
    }

    while (fileSources[0]->Pump(256))
        for (i=1; i<threshold; i++)
            fileSources[i]->Pump(256);

    for (i=0; i<threshold; i++)
        fileSources[i]->PumpAll();
}
jww
  • 97,681
  • 90
  • 411
  • 885