module actions; import std.stdio : File, stdin, stdout, writeln; import std.base64 : Base64; import std.random : Random, uniform; import std.algorithm : joiner; import cipher; public: enum chunkSize = 4096; enum base64ChunkSize = 57; enum string randomDeviceName = "/dev/random"; void encrypt(string keyFileName, Cipher cipher, bool armor) { auto key = loadKey(keyFileName, armor); ubyte[8] nonce; if (armor) { ubyte[base64ChunkSize] buf; char[Base64.encodeLength(base64ChunkSize)] buf2; int counter; foreach (b; stdin.byChunk(chunkSize).joiner.cipherFunction(key, nonce, cipher)) { buf[counter] = b; ++counter; if (counter == 57) { Base64.encode(buf, buf2[]); stdout.writeln(buf2); counter = 0; } } if (counter > 0) { Base64.encode(buf[0..counter], buf2[]); stdout.writeln(buf2[0..Base64.encodeLength(counter)]); } } else { ubyte[chunkSize] buf; int counter; foreach (b; stdin.byChunk(chunkSize).joiner.cipherFunction(key, nonce, cipher)) { buf[counter] = b; ++counter; if (counter == chunkSize) { stdout.rawWrite(buf); counter = 0; } } if (counter > 0) stdout.rawWrite(buf[0..counter]); } } void decrypt(string keyFileName, Cipher cipher, bool armor) { import std.range; auto key = loadKey(keyFileName, armor); ubyte[8] nonce; ubyte[chunkSize] buf; int counter; InputRange!ubyte r; if (armor) r = Base64.decoder(stdin.byLine).joiner.cipherFunction(key, nonce, cipher).inputRangeObject; else r = stdin.byChunk(chunkSize).joiner.cipherFunction(key, nonce, cipher).inputRangeObject; foreach (b; r) { buf[counter] = b; ++counter; if (counter == 4096) { stdout.rawWrite(buf); counter = 0; } } if(counter > 0) stdout.rawWrite(buf[0..counter]); } void generateKey(bool armor) { auto rng = Random(); auto randomDevice = File(randomDeviceName, "r"); scope (exit) randomDevice.close(); uint[1] seed; randomDevice.rawRead(seed); rng.seed(seed[0]); ubyte[32] key; foreach (ref b; key) b = uniform!ubyte(rng); if (armor) { writeln(Base64.encode(key)); } else { stdout.rawWrite(key); } } private: ubyte[32] loadKey(string filename, bool armor) { auto keyFile = File(filename, "r"); scope (exit) keyFile.close(); ubyte[32] key; ubyte[33] temp; if (armor) { import std.string : chomp; key = Base64.decode(keyFile.readln.chomp, temp[]); } else { keyFile.rawRead(key); } return key; }