From a596c525ad3ca86226cdb8094b91a578b23c1dae Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 9 Feb 2015 15:09:39 +0100 Subject: [PATCH] Add base64 encoder/decoder --- src/libutil/util.cc | 59 ++++++++++++++++++++++++++++++++++++++ src/libutil/util.hh | 5 ++++ src/nix-store/nix-store.cc | 10 ++----- 3 files changed, 66 insertions(+), 8 deletions(-) diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 4f3010880..be0a9bf31 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -1208,4 +1208,63 @@ string filterANSIEscapes(const string & s, bool nixOnly) } +static char base64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + +string base64Encode(const string & s) +{ + string res; + int data = 0, nbits = 0; + + for (char c : s) { + data = data << 8 | (unsigned char) c; + nbits += 8; + while (nbits >= 6) { + nbits -= 6; + res.push_back(base64Chars[data >> nbits & 0x3f]); + } + } + + if (nbits) res.push_back(base64Chars[data << (6 - nbits) & 0x3f]); + while (res.size() % 4) res.push_back('='); + + return res; +} + + +string base64Decode(const string & s) +{ + bool init = false; + char decode[256]; + if (!init) { + // FIXME: not thread-safe. + memset(decode, -1, sizeof(decode)); + for (int i = 0; i < 64; i++) + decode[(int) base64Chars[i]] = i; + init = true; + } + + string res; + unsigned int d = 0, bits = 0; + + for (char c : s) { + if (c == '=') break; + if (c == '\n') continue; + + char digit = decode[(unsigned char) c]; + if (digit == -1) + throw Error("invalid character in Base64 string"); + + bits += 6; + d = d << 6 | digit; + if (bits >= 8) { + res.push_back(d >> (bits - 8) & 0xff); + bits -= 8; + } + } + + return res; +} + + } diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 1a2dda527..20330fb76 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -398,4 +398,9 @@ void ignoreException(); string filterANSIEscapes(const string & s, bool nixOnly = false); +/* Base64 encoding/decoding. */ +string base64Encode(const string & s); +string base64Decode(const string & s); + + } diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index 187397368..c59eb21fb 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -1023,14 +1023,8 @@ static void opGenerateBinaryCacheKey(Strings opFlags, Strings opArgs) if (crypto_sign_keypair(pk, sk) != 0) throw Error("key generation failed"); - // FIXME: super ugly way to do base64 encoding. - auto args = Strings({"-MMIME::Base64", "-0777", "-ne", "print encode_base64($_, '')"}); - - string pk64 = runProgram("perl", true, args, string((char *) pk, crypto_sign_PUBLICKEYBYTES)); - std::cout << keyName << ":" << pk64 << std::endl; - - string sk64 = runProgram("perl", true, args, string((char *) sk, crypto_sign_SECRETKEYBYTES)); - std::cout << keyName << ":" << sk64 << std::endl; + std::cout << keyName << ":" << base64Encode(string((char *) pk, crypto_sign_PUBLICKEYBYTES)) << std::endl; + std::cout << keyName << ":" << base64Encode(string((char *) sk, crypto_sign_SECRETKEYBYTES)) << std::endl; }