learncrypto/source/actions.d

140 lines
3 KiB
D
Raw Normal View History

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;
enum base64ChunkSize = 57;
2016-02-14 11:00:28 +01:00
enum string randomDeviceName = "/dev/random";
void encrypt(string keyFileName, Cipher cipher, bool armor)
{
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
{
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
{
buf[counter] = b;
++counter;
if (counter == 57)
2016-02-14 11:00:28 +01:00
{
Base64.encode(buf, buf2[]);
stdout.writeln(buf2);
counter = 0;
2016-02-14 11:00:28 +01: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-02-14 11:00:28 +01:00
}
else
{
ubyte[chunkSize] buf;
int counter;
2016-02-28 14:25:58 +01:00
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)
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)
{
import std.range : inputRangeObject, InputRange;
2016-08-01 01:42:29 +02:00
immutable key = loadKey(keyFileName, armor);
immutable ubyte[8] nonce;
ubyte[chunkSize] buf;
int counter;
InputRange!ubyte r;
2016-02-28 14:25:58 +01:00
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)
2016-02-14 11:00:28 +01:00
{
buf[counter] = b;
++counter;
if (counter == 4096)
2016-02-14 11:00:28 +01: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);
}
}
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;
ubyte[33] temp;
2016-02-28 14:25:58 +01:00
if (armor)
2016-02-14 11:00:28 +01:00
{
import std.string : chomp;
2016-08-01 01:42:29 +02:00
key = Base64.decode(keyFile.readln.chomp, temp[]);
2016-02-14 11:00:28 +01:00
}
else
{
keyFile.rawRead(key);
}
return key;
}