Skip to content

Instantly share code, notes, and snippets.

@Pzixel
Last active April 19, 2019 09:28
Show Gist options
  • Select an option

  • Save Pzixel/7514f8b4a7588256bebf7250e239c90d to your computer and use it in GitHub Desktop.

Select an option

Save Pzixel/7514f8b4a7588256bebf7250e239c90d to your computer and use it in GitHub Desktop.
using System;
using System.Linq;
using Org.BouncyCastle.Crypto.Digests;
namespace XXX
{
public static class OneTimePad
{
public static byte[] Encrypt(byte[] data, byte[] masterKey, uint index) =>
Encrypt(data, masterKey.Concat(GetSolidityUint256(index)).ToArray());
public static byte[] Encrypt(byte[] data, byte[] key)
{
var result = new byte[data.Length];
for (int i = 0; i < data.Length; i += 32)
{
var hash = GetHash(key, (uint) i);
var chunk = GetChunk(data, i);
Xor(chunk, hash, new Span<byte>(result, i, chunk.Length));
}
return result;
}
private static byte[] GetHash(byte[] key, uint i)
{
var iBytes = GetSolidityUint256(i);
var packedBytes = key.Concat(iBytes).ToArray();
var hash = Keccak256(packedBytes);
return hash;
}
private static ReadOnlySpan<byte> GetChunk(byte[] data, int index) => new ReadOnlySpan<byte>(data, index, Math.Min(32, data.Length - index));
private static void Xor(ReadOnlySpan<byte> a, byte[] b, Span<byte> result)
{
for (int i = 0; i < a.Length; i++)
{
result[i] = (byte) (a[i] ^ b[i]);
}
}
private static byte[] Keccak256(byte[] bytes)
{
var sha = new KeccakDigest(256);
sha.BlockUpdate(bytes, 0, bytes.Length);
byte[] result = new byte[sha.GetDigestSize()];
sha.DoFinal(result, 0);
return result;
}
private static byte[] GetSolidityUint256(uint value)
{
return new byte[32]
{
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
(byte)((value >> 24) & 0xFF),
(byte)((value >> 16) & 0xFF),
(byte)((value >> 8) & 0xFF),
(byte)value,
};
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment