Secret Key Cryptography _Encrypted streams and file encryption - Chewhern/ASodium GitHub Wiki

For this section of the functions which describes the wrapper functions based on libsodium library..

Although the code is working but there's a lot of concerns from my side as I don't know whether I have implemented this securely and properly.

Use this at your own risks..

Initial Functions

public static int GetABytesLength()
public static int GetKeyLength()
public static Byte GetTagMessageByte()
public static Byte GetTagPushByte()
public static Byte GetTagRekeyByte()
public static Byte GetTagFinalByte()
public static Byte[] KeyGen()
public static long GetMessageBytesMaxLength()
public static int GetStateBytesLength()
public static int GetHeaderBytesLength()
public static SecretStreamInitPushBox SecretStreamInitPush(Byte[] KeyByte,Boolean IsClearKey=false)
public static SecretStreamPushBox SecretStreamPush(Byte[] StateByte, Byte[] Message,Byte[] AdditionalData, long AdditionalDataLength, Byte Tag)
public static Byte[] SecretStreamInitPull(Byte[] HeaderByte,Byte[] KeyByte)
public static SecretStreamPullBox SecretStreamPull(Byte[] StateByte, Byte TagByte, Byte[] CipheredText, Byte[] AdditionalData,long AdditionalDataLength)
public static Byte[] SecretStreamReKey(Byte[] StateByte)

Stream encryption and decryption

Example code

Byte[] SecretStreamKey = SodiumSecretStream.KeyGen();
String Message1 = "Arbitrary data to encrypt";
Byte[] Message1Byte = Encoding.UTF8.GetBytes(Message1);
Byte[] CipherText1 = new Byte[SodiumSecretStream.GetABytesLength() + Message1Byte.Length];
String Message2 = "split into";
Byte[] Message2Byte = Encoding.UTF8.GetBytes(Message2);
Byte[] CipherText2 = new Byte[SodiumSecretStream.GetABytesLength() + Message2Byte.Length];
String Message3 = "three messages";
Byte[] Message3Byte = Encoding.UTF8.GetBytes(Message3);
Byte[] CipherText3 = new Byte[SodiumSecretStream.GetABytesLength() + Message3Byte.Length];
SecretStreamInitPushBox MyInitPushBoxStream = new SecretStreamInitPushBox();
MyInitPushBoxStream = SodiumSecretStream.SecretStreamInitPush(SecretStreamKey);
SecretStreamPushBox MyPushBox1 = new SecretStreamPushBox();
SecretStreamPushBox MyPushBox2 = new SecretStreamPushBox();
SecretStreamPushBox MyPushBox3 = new SecretStreamPushBox();
MyPushBox1 = SodiumSecretStream.SecretStreamPush(MyInitPushBoxStream.StateByte, Message1Byte, null, 0, SodiumSecretStream.GetTagMessageByte());
MyPushBox2 = SodiumSecretStream.SecretStreamPush(MyPushBox1.StateByte, Message2Byte, null, 0, SodiumSecretStream.GetTagMessageByte());
MyPushBox3 = SodiumSecretStream.SecretStreamPush(MyPushBox2.StateByte, Message3Byte, null, 0, SodiumSecretStream.GetTagFinalByte());
Byte[] StateByte = SodiumSecretStream.SecretStreamInitPull(MyInitPushBoxStream.HeaderByte,SecretStreamKey);
Byte TagByte=0;
SecretStreamPullBox MyPullBox1 = new SecretStreamPullBox();
SecretStreamPullBox MyPullBox2 = new SecretStreamPullBox();
SecretStreamPullBox MyPullBox3 = new SecretStreamPullBox();
MyPullBox1 = SodiumSecretStream.SecretStreamPull(StateByte, TagByte, MyPushBox1.CipherText, null, 0);
MyPullBox2 = SodiumSecretStream.SecretStreamPull(MyPullBox1.StateByte, MyPullBox1.TagByte, MyPushBox2.CipherText, null, 0);
MyPullBox3 = SodiumSecretStream.SecretStreamPull(MyPullBox2.StateByte, MyPullBox2.TagByte, MyPushBox3.CipherText, null, 0);

File encryption and decryption

Example code (Encryption)

Byte[] SecretStreamKey = SodiumSecretStream.KeyGen();
Byte[] MessageByte = new Byte[] { };
Byte SampleTag = 0;
FileStream MessageFileStream = File.OpenRead(Application.StartupPath + "\\Message.txt");
long MessageFileLengthInBytes = MessageFileStream.Length;
long CurrentCount = 128;
int LoopCount = 1;
int EndOfFile = 0;
FileStream CipherTextFileStream = File.OpenWrite(Application.StartupPath + "\\CipherText.txt");
SecretStreamInitPushBox MyInitPushBox = new SecretStreamInitPushBox();
MyInitPushBox = SodiumSecretStream.SecretStreamInitPush(SecretStreamKey);
SecretStreamPushBox MyPushBox = new SecretStreamPushBox();
CipherTextFileStream.Write(MyInitPushBox.HeaderByte, 0, MyInitPushBox.HeaderByte.Length);
while (CurrentCount <= MessageFileLengthInBytes) 
{
    MessageByte = new Byte[128];
    EndOfFile = MessageFileStream.Read(MessageByte, 0, 128);

    if(CurrentCount == MessageFileLengthInBytes) 
    {
        SampleTag = SodiumSecretStream.GetTagFinalByte();
        if (LoopCount == 1) 
        {
            MyPushBox = SodiumSecretStream.SecretStreamPush(MyInitPushBox.StateByte, MessageByte, null, 0, SampleTag);
            CipherTextFileStream.Write(MyPushBox.CipherText, 0, MyPushBox.CipherText.Length);
        }
        else 
        {
            MyPushBox = SodiumSecretStream.SecretStreamPush(MyPushBox.StateByte, MessageByte, null, 0, SampleTag);
            CipherTextFileStream.Write(MyPushBox.CipherText, 0, MyPushBox.CipherText.Length);
        }
        break;
    }
    else 
    {
        if (LoopCount == 1)
        {
            MyPushBox = SodiumSecretStream.SecretStreamPush(MyInitPushBox.StateByte, MessageByte, null, 0, SodiumSecretStream.GetTagMessageByte());
            CipherTextFileStream.Write(MyPushBox.CipherText, 0, MyPushBox.CipherText.Length);
        }
        else
        {
            MyPushBox = SodiumSecretStream.SecretStreamPush(MyPushBox.StateByte, MessageByte, null, 0, SodiumSecretStream.GetTagMessageByte());
            CipherTextFileStream.Write(MyPushBox.CipherText, 0, MyPushBox.CipherText.Length);
        }
    }
    LoopCount += 1;
    CurrentCount *= 2;
}
File.WriteAllBytes(Application.StartupPath + "\\Key.txt",SecretStreamKey);
MessageFileStream.Close();
CipherTextFileStream.Close();

Example code(Decryption)

Byte[] SecretStreamKey = File.ReadAllBytes(Application.StartupPath + "\\Key.txt");
Byte[] SecretStreamHeader = new Byte[SodiumSecretStream.GetHeaderBytesLength()];
Byte[] StateByte = new Byte[] { };
Byte[] CipherText = new Byte[128 + SodiumSecretStream.GetABytesLength()];
Byte SampleTag = SodiumSecretStream.GetTagMessageByte();
FileStream CipherTextFileStream = File.OpenRead(Application.StartupPath + "\\CipherText.txt");
long TotalCipherText = 0;
long CurrentCount = 128 + SodiumSecretStream.GetABytesLength();
int LoopCount = 1;
FileStream PlainTextFileStream = File.OpenWrite(Application.StartupPath + "\\PlainText.txt");
SecretStreamPullBox MyPullBox = new SecretStreamPullBox();
CipherTextFileStream.Read(SecretStreamHeader, 0, SodiumSecretStream.GetHeaderBytesLength());
StateByte = SodiumSecretStream.SecretStreamInitPull(SecretStreamHeader, SecretStreamKey);
TotalCipherText = CipherTextFileStream.Length - SecretStreamHeader.Length;
do
{
    CipherText = new Byte[128 + SodiumSecretStream.GetABytesLength()];
    CipherTextFileStream.Read(CipherText, 0, CipherText.Length);
    if (CurrentCount==TotalCipherText) 
    {
        if (LoopCount == 1) 
        {
            MyPullBox = SodiumSecretStream.SecretStreamPull(StateByte, SampleTag, CipherText, null, 0);
            PlainTextFileStream.Write(MyPullBox.MessageByte, 0, MyPullBox.MessageByte.Length);
        }
        else 
        {
            MyPullBox = SodiumSecretStream.SecretStreamPull(MyPullBox.StateByte, SampleTag, CipherText, null, 0);
            PlainTextFileStream.Write(MyPullBox.MessageByte, 0, MyPullBox.MessageByte.Length);
        }
    }
    else 
    {
        if (LoopCount == 1)
        {
            MyPullBox = SodiumSecretStream.SecretStreamPull(StateByte, SampleTag, CipherText, null, 0);
            PlainTextFileStream.Write(MyPullBox.MessageByte, 0, MyPullBox.MessageByte.Length);
        }
        else
        {
            MyPullBox = SodiumSecretStream.SecretStreamPull(MyPullBox.StateByte, SampleTag, CipherText, null, 0);
            PlainTextFileStream.Write(MyPullBox.MessageByte, 0, MyPullBox.MessageByte.Length);
        }
    }

    CurrentCount *= 2;
    LoopCount += 1;
}
while (CurrentCount<=TotalCipherText);
PlainTextFileStream.Close();
CipherTextFileStream.Close();