diff options
author | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2015-02-09T14·09+0100 |
---|---|---|
committer | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2015-02-10T10·33+0100 |
commit | a596c525ad3ca86226cdb8094b91a578b23c1dae (patch) | |
tree | 04e09211da695cc2d2d72eac119be18dbd370c1c | |
parent | 70cae879e3c3f5c3fba906ba5ec220f84cff1d61 (diff) |
Add base64 encoder/decoder
-rw-r--r-- | src/libutil/util.cc | 59 | ||||
-rw-r--r-- | src/libutil/util.hh | 5 | ||||
-rw-r--r-- | 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 4f3010880286..be0a9bf317d1 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 1a2dda527121..20330fb7699e 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 18739736838e..c59eb21fb456 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; } |