2016-02-14 11:00:28 +01:00
|
|
|
module actions;
|
|
|
|
|
2016-02-28 14:25:58 +01:00
|
|
|
import std.stdio : File, stdin, stdout, writeln;
|
|
|
|
import std.base64 : Base64;
|
2016-02-14 11:00:28 +01:00
|
|
|
import std.random : Random, uniform;
|
|
|
|
import std.algorithm : joiner;
|
|
|
|
|
|
|
|
import cipher;
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
enum chunkSize = 4096;
|
2016-07-04 15:00:52 +02:00
|
|
|
enum base64ChunkSize = 57;
|
2016-02-14 11:00:28 +01:00
|
|
|
|
|
|
|
enum string randomDeviceName = "/dev/random";
|
|
|
|
|
|
|
|
void encrypt(string keyFileName, Cipher cipher, bool armor)
|
|
|
|
{
|
2016-07-06 02:00:03 +02:00
|
|
|
immutable key = loadKey(keyFileName, armor);
|
|
|
|
immutable ubyte[8] nonce;
|
2016-02-28 14:25:58 +01:00
|
|
|
if (armor)
|
2016-02-14 11:00:28 +01:00
|
|
|
{
|
2016-07-04 15:00:52 +02:00
|
|
|
ubyte[base64ChunkSize] buf;
|
|
|
|
char[Base64.encodeLength(base64ChunkSize)] buf2;
|
|
|
|
int counter;
|
2016-02-28 14:25:58 +01:00
|
|
|
foreach (b; stdin.byChunk(chunkSize).joiner.cipherFunction(key, nonce, cipher))
|
2016-02-14 11:00:28 +01:00
|
|
|
{
|
2016-07-04 15:00:52 +02:00
|
|
|
buf[counter] = b;
|
|
|
|
++counter;
|
|
|
|
if (counter == 57)
|
2016-02-14 11:00:28 +01:00
|
|
|
{
|
2016-07-04 15:00:52 +02:00
|
|
|
Base64.encode(buf, buf2[]);
|
|
|
|
stdout.writeln(buf2);
|
|
|
|
counter = 0;
|
2016-02-14 11:00:28 +01:00
|
|
|
}
|
|
|
|
}
|
2016-07-04 15:00:52 +02:00
|
|
|
if (counter > 0)
|
|
|
|
{
|
2016-08-01 01:42:29 +02:00
|
|
|
Base64.encode(buf[0 .. counter], buf2[]);
|
|
|
|
stdout.writeln(buf2[0 .. Base64.encodeLength(counter)]);
|
2016-07-04 15:00:52 +02:00
|
|
|
}
|
2016-02-14 11:00:28 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-07-04 15:00:52 +02:00
|
|
|
ubyte[chunkSize] buf;
|
|
|
|
int counter;
|
2016-02-28 14:25:58 +01:00
|
|
|
foreach (b; stdin.byChunk(chunkSize).joiner.cipherFunction(key, nonce, cipher))
|
2016-07-04 15:00:52 +02:00
|
|
|
{
|
|
|
|
buf[counter] = b;
|
|
|
|
++counter;
|
|
|
|
if (counter == chunkSize)
|
|
|
|
{
|
|
|
|
stdout.rawWrite(buf);
|
|
|
|
counter = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (counter > 0)
|
2016-08-01 01:42:29 +02:00
|
|
|
stdout.rawWrite(buf[0 .. counter]);
|
2016-02-14 11:00:28 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void decrypt(string keyFileName, Cipher cipher, bool armor)
|
|
|
|
{
|
2016-07-06 02:00:03 +02:00
|
|
|
import std.range : inputRangeObject, InputRange;
|
2016-08-01 01:42:29 +02:00
|
|
|
|
2016-07-06 02:00:03 +02:00
|
|
|
immutable key = loadKey(keyFileName, armor);
|
|
|
|
immutable ubyte[8] nonce;
|
2016-07-04 15:00:52 +02:00
|
|
|
ubyte[chunkSize] buf;
|
|
|
|
int counter;
|
|
|
|
InputRange!ubyte r;
|
2016-02-28 14:25:58 +01:00
|
|
|
if (armor)
|
2016-07-04 15:00:52 +02:00
|
|
|
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)
|
2016-02-14 11:00:28 +01:00
|
|
|
{
|
2016-07-04 15:00:52 +02:00
|
|
|
buf[counter] = b;
|
|
|
|
++counter;
|
|
|
|
if (counter == 4096)
|
2016-02-14 11:00:28 +01:00
|
|
|
{
|
2016-07-04 15:00:52 +02:00
|
|
|
stdout.rawWrite(buf);
|
|
|
|
counter = 0;
|
2016-02-14 11:00:28 +01:00
|
|
|
}
|
|
|
|
}
|
2016-08-01 01:42:29 +02:00
|
|
|
if (counter > 0)
|
|
|
|
stdout.rawWrite(buf[0 .. counter]);
|
2016-02-14 11:00:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void generateKey(bool armor)
|
|
|
|
{
|
|
|
|
auto rng = Random();
|
|
|
|
auto randomDevice = File(randomDeviceName, "r");
|
2016-02-28 14:25:58 +01:00
|
|
|
scope (exit)
|
|
|
|
randomDevice.close();
|
2016-02-14 11:00:28 +01:00
|
|
|
uint[1] seed;
|
|
|
|
randomDevice.rawRead(seed);
|
|
|
|
rng.seed(seed[0]);
|
|
|
|
|
|
|
|
ubyte[32] key;
|
|
|
|
foreach (ref b; key)
|
|
|
|
b = uniform!ubyte(rng);
|
|
|
|
|
2016-02-28 14:25:58 +01:00
|
|
|
if (armor)
|
2016-02-14 11:00:28 +01:00
|
|
|
{
|
|
|
|
writeln(Base64.encode(key));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
stdout.rawWrite(key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-06 02:00:03 +02:00
|
|
|
void bench()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-02-14 11:00:28 +01:00
|
|
|
private:
|
|
|
|
|
|
|
|
ubyte[32] loadKey(string filename, bool armor)
|
|
|
|
{
|
|
|
|
auto keyFile = File(filename, "r");
|
2016-02-28 14:25:58 +01:00
|
|
|
scope (exit)
|
|
|
|
keyFile.close();
|
2016-02-14 11:00:28 +01:00
|
|
|
ubyte[32] key;
|
2016-07-04 15:00:52 +02:00
|
|
|
ubyte[33] temp;
|
2016-02-28 14:25:58 +01:00
|
|
|
if (armor)
|
2016-02-14 11:00:28 +01:00
|
|
|
{
|
2016-07-04 15:00:52 +02:00
|
|
|
import std.string : chomp;
|
2016-08-01 01:42:29 +02:00
|
|
|
|
2016-07-04 15:00:52 +02:00
|
|
|
key = Base64.decode(keyFile.readln.chomp, temp[]);
|
2016-02-14 11:00:28 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
keyFile.rawRead(key);
|
|
|
|
}
|
|
|
|
return key;
|
|
|
|
}
|