Public Key Cryptography _Public Key Digital Signatures - Chewhern/ASodium GitHub Wiki

For detail documentation, kindly refer to official libsodium.

Key Pair Generation

There're 2 types of key pair in this wrapper library.

For details about the structure of different key pair types, kindly refer to these 2 links.

(https://github.com/Chewhern/ASodium/blob/main/Source/KeyPair.cs)

(https://github.com/Chewhern/ASodium/blob/main/Source/RevampedKeyPair.cs)

Revamped Key Pair Generation (Closest to the maintenance mode libsodium-core binding's keypair)

Initial Functions

public static RevampedKeyPair GenerateRevampedKeyPair()

Example Code

RevampedKeyPair MyRevampedKeyPair = SodiumPublicKeyBox.GenerateRevampedKeyPair();
//Uses libsodium secure memory to clear  the sensitive key materials
MyRevampedKeyPair.Clear();

Key Pair Generation (New Object which uses both C#'s IntPtr and Sodium Guarded Heap Allocations)

I am kinda an amateur when I first created my own binding.., the Key Pair structure which originally resides in libsodium-core has a memory protect function/method in which I couldn't recreate due to different environments and languages..

The libsodium's guarded heap allocations is not an immediate fix to the issue I faced but at the least.., it is better than having no protections on sensitive cryptography data..

Initial Functions

public static KeyPair GenerateKeyPair()

Example Code

SodiumInit.Init();
KeyPair MyNewKeyPair = SodiumPublicKeyAuth.GenerateKeyPair();
IntPtr SecretKeyIntPtr = MyNewKeyPair.GetPrivateKey();
Byte[] SecretKey = new Byte[SodiumPublicKeyAuth.GetSecretKeyBytesLength()];
Marshal.Copy(SecretKeyIntPtr, SecretKey, 0, SodiumPublicKeyAuth.GetSecretKeyBytesLength());
MyNewKeyPair.ProtectPrivateKey();

Combined mode signing and verification

In public key cryptography's authenticated encryption, the ciphertext had been appended with MAC computed by Poly1305. Combined mode signing and verification refers to the signature computed had been appended in front of message.

Initial Functions

public static Byte[] Sign(Byte[] Message,Byte[] SecretKey, Boolean ClearKey = false)
public static Byte[] Verify(Byte[] SignatureMessage,Byte[] PublicKey)

Example Code

//Revamped KeyPair
RevampedKeyPair MyKeyPair = SodiumPublicKeyAuth.GenerateRevampedKeyPair();
Byte[] Message = SodiumRNG.GetRandomBytes(128);
Byte[] SignatureMessage = SodiumPublicKeyAuth.Sign(Message, MyKeyPair.PrivateKey);
Byte[] VerifiedMessage = SodiumPublicKeyAuth.Verify(SignatureMessage, MyKeyPair.PublicKey);
//KeyPair
KeyPair MyNewKeyPair = SodiumPublicKeyAuth.GenerateKeyPair();
IntPtr SecretKeyIntPtr = MyNewKeyPair.GetPrivateKey();
Byte[] SecretKey = new Byte[SodiumPublicKeyAuth.GetSecretKeyBytesLength()];
Marshal.Copy(SecretKeyIntPtr, SecretKey, 0, SodiumPublicKeyAuth.GetSecretKeyBytesLength());
MyNewKeyPair.ProtectPrivateKey();
SignatureMessage = SodiumPublicKeyAuth.Sign(Message, SecretKey);
VerifiedMessage = SodiumPublicKeyAuth.Verify(SignatureMessage, MyNewKeyPair.GetPublicKey());

Detached signing and verification

Initial Functions

public static Byte[] SignDetached(Byte[] Message, Byte[] SecretKey, Boolean ClearKey = false)
public static Boolean VerifyDetached(Byte[] Signature, Byte[] Message, Byte[] PublicKey)

Example Code

//Revamped KeyPair
RevampedKeyPair MyKeyPair = SodiumPublicKeyAuth.GenerateRevampedKeyPair();
Byte[] Message = SodiumRNG.GetRandomBytes(128);
Byte[] Signature = SodiumPublicKeyAuth.SignDetached(Message, MyKeyPair.PrivateKey);
Boolean Verified = SodiumPublicKeyAuth.VerifyDetached(Signature,Message , MyKeyPair.PublicKey);
if (Verified) 
{
    MessageBox.Show("Signature and Message Matched");
}
//KeyPair
KeyPair MyNewKeyPair = SodiumPublicKeyAuth.GenerateKeyPair();
IntPtr SecretKeyIntPtr = MyNewKeyPair.GetPrivateKey();
Byte[] SecretKey = new Byte[SodiumPublicKeyAuth.GetSecretKeyBytesLength()];
Marshal.Copy(SecretKeyIntPtr, SecretKey, 0, SodiumPublicKeyAuth.GetSecretKeyBytesLength());
MyNewKeyPair.ProtectPrivateKey();
Signature = SodiumPublicKeyAuth.SignDetached(Message, SecretKey);
Verified = SodiumPublicKeyAuth.VerifyDetached(Signature, Message, MyNewKeyPair.GetPublicKey());
if (Verified)
{
    MessageBox.Show("Signature and Message Matched");
}

Public Key Generation and Seed Extraction from a given private key

Initial Functions

public static Byte[] GeneratePublicKey(Byte[] SecretKey,Boolean ClearKey=false) 
public static Byte[] ExtractSeed(Byte[] SecretKey,Boolean ClearKey=false) 

Example Code (Public Key Generation)

RevampedKeyPair MyKeyPair = SodiumPublicKeyAuth.GenerateRevampedKeyPair();
Byte[] PublicKey = SodiumPublicKeyAuth.GeneratePublicKey(MyKeyPair.PrivateKey);
//This can be used not only for recovering lost public key
//It can also be used in creating your own keypair

Example Code (Seed Extraction)

RevampedKeyPair MyKeyPair = SodiumPublicKeyAuth.GenerateRevampedKeyPair();
Byte[] Seed = SodiumPublicKeyAuth.ExtractSeed(MyKeyPair.PrivateKey);

Custom made methods

Helper Functions

public static PublicKeyAuthSealBox SealedSign(Byte[] Message)
public static PublicKeyAuthDetachedSealBox SealedSignDetached(Byte[] Message)

Example Code (Sealed Sign, Sealed Sign Detached and verification)

Byte[] Message = SodiumRNG.GetRandomBytes(128);
PublicKeyAuthSealBox MyPublicKeyAuthSealBox = SodiumPublicKeyAuth.SealedSign(Message);
PublicKeyAuthDetachedSealBox MyPublicKeyAuthDetachedSealBox = SodiumPublicKeyAuth.SealedSignDetached(Message);
Byte[] VerifiedMessage = SodiumPublicKeyAuth.Verify(MyPublicKeyAuthSealBox.SignatureMessage, MyPublicKeyAuthSealBox.PublicKey);
Boolean Verified = SodiumPublicKeyAuth.VerifyDetached(MyPublicKeyAuthDetachedSealBox.Signature, Message, MyPublicKeyAuthDetachedSealBox.PublicKey);

Multi-part messages signing and verifying

Initial Functions

public static Byte[] InitializeState()
public static Byte[] UpdateState(Byte[] OldState,Byte[] Message)
public static Byte[] SignFinalState(Byte[] State,Byte[] SecretKey, Boolean ClearKey = false)
public static Boolean VerifySignedFinalState(Byte[] State, Byte[] Signature , Byte[] PublicKey)

Example Code

Byte[] Message1 = SodiumRNG.GetRandomBytes(128);
Byte[] Message2 = SodiumRNG.GetRandomBytes(128);
Byte[] Message3 = SodiumRNG.GetRandomBytes(128);
Byte[] StateByte = SodiumPublicKeyAuthMPM.InitializeState();
StateByte = SodiumPublicKeyAuthMPM.UpdateState(StateByte, Message1);
StateByte = SodiumPublicKeyAuthMPM.UpdateState(StateByte, Message2);
StateByte = SodiumPublicKeyAuthMPM.UpdateState(StateByte, Message3);
//Revamped KeyPair
RevampedKeyPair MyKeyPair = SodiumPublicKeyAuth.GenerateRevampedKeyPair();
Byte[] Signature = SodiumPublicKeyAuthMPM.SignFinalState(StateByte, MyKeyPair.PrivateKey);
StateByte = SodiumPublicKeyAuthMPM.InitializeState();
StateByte = SodiumPublicKeyAuthMPM.UpdateState(StateByte, Message1);
StateByte = SodiumPublicKeyAuthMPM.UpdateState(StateByte, Message2);
StateByte = SodiumPublicKeyAuthMPM.UpdateState(StateByte, Message3);
Boolean Verified = SodiumPublicKeyAuthMPM.VerifySignedFinalState(StateByte, Signature, MyKeyPair.PublicKey);
//KeyPair
KeyPair MyNewKeyPair = SodiumPublicKeyAuth.GenerateKeyPair();
IntPtr SecretKeyIntPtr = MyNewKeyPair.GetPrivateKey();
Byte[] SecretKey = new Byte[SodiumPublicKeyAuth.GetSecretKeyBytesLength()];
Marshal.Copy(SecretKeyIntPtr, SecretKey, 0, SodiumPublicKeyAuth.GetSecretKeyBytesLength());
MyNewKeyPair.ProtectPrivateKey();
StateByte = SodiumPublicKeyAuthMPM.InitializeState();
StateByte = SodiumPublicKeyAuthMPM.UpdateState(StateByte, Message1);
StateByte = SodiumPublicKeyAuthMPM.UpdateState(StateByte, Message2);
StateByte = SodiumPublicKeyAuthMPM.UpdateState(StateByte, Message3);
Signature = SodiumPublicKeyAuthMPM.SignFinalState(StateByte, SecretKey);
StateByte = SodiumPublicKeyAuthMPM.InitializeState();
StateByte = SodiumPublicKeyAuthMPM.UpdateState(StateByte, Message1);
StateByte = SodiumPublicKeyAuthMPM.UpdateState(StateByte, Message2);
StateByte = SodiumPublicKeyAuthMPM.UpdateState(StateByte, Message3);
Verified = SodiumPublicKeyAuthMPM.VerifySignedFinalState(StateByte, Signature, MyNewKeyPair.GetPublicKey());