// Converts a libsodium secret key into a key blob. internal virtual int ExportKey( SecureMemoryHandle keyHandle, KeyBlobFormat format, Span <byte> blob) { throw Error.NotSupported_ExportKey(); }
internal static unsafe extern int crypto_generichash_blake2b( byte * @out, UIntPtr outlen, byte * @in, ulong inlen, SecureMemoryHandle key, UIntPtr keylen);
internal override bool TryImportKey( ReadOnlySpan <byte> blob, KeyBlobFormat format, out SecureMemoryHandle keyHandle, out byte[] publicKeyBytes) { if (format != KeyBlobFormat.RawSymmetricKey) { throw Error.Argument_FormatNotSupported(nameof(format), format.ToString()); } if (blob.Length < MinKeySize) { keyHandle = null; publicKeyBytes = null; return(false); } if (blob.Length > SHA256MessageBlockSize) { publicKeyBytes = null; SecureMemoryHandle.Alloc(crypto_hash_sha256_BYTES, out keyHandle); crypto_hash_sha256_init(out crypto_hash_sha256_state state); crypto_hash_sha256_update(ref state, ref blob.DangerousGetPinnableReference(), (ulong)blob.Length); crypto_hash_sha256_final(ref state, keyHandle); } else { publicKeyBytes = null; SecureMemoryHandle.Alloc(blob.Length, out keyHandle); keyHandle.Import(blob); } return(true); }
public static bool TryImport( Algorithm algorithm, ReadOnlySpan <byte> blob, KeyBlobFormat format, KeyFlags flags, out Key result) { if (algorithm == null) { throw Error.ArgumentNull_Algorithm(nameof(algorithm)); } SecureMemoryHandle keyHandle = null; byte[] publicKeyBytes = null; bool success = false; try { success = algorithm.TryImportKey(blob, format, out keyHandle, out publicKeyBytes); } finally { if (!success && keyHandle != null) { keyHandle.Dispose(); } } result = success ? new Key(algorithm, flags, keyHandle, publicKeyBytes) : null; return(success); }
// Creates a new libsodium secret key from a seed. internal virtual void CreateKey( ReadOnlySpan <byte> seed, out SecureMemoryHandle keyHandle, out byte[] publicKeyBytes) { throw Error.NotSupported_CreateKey(); }
internal static unsafe extern int crypto_stream_chacha20_ietf_xor_ic( byte *c, byte *m, ulong mlen, NSec.Cryptography.Nonce *n, uint ic, SecureMemoryHandle k);
internal override bool TryVerifyCore( SecureMemoryHandle keyHandle, ReadOnlySpan <byte> data, ReadOnlySpan <byte> mac) { Debug.Assert(keyHandle != null); Debug.Assert(mac.Length <= crypto_auth_hmacsha256_BYTES); // crypto_auth_hmacsha256_verify does not support truncated HMACs, // so we calculate the MAC ourselves and call sodium_memcmp to // compare the expected MAC with the actual MAC. Span <byte> temp; try { unsafe { byte *pointer = stackalloc byte[crypto_auth_hmacsha256_BYTES]; temp = new Span <byte>(pointer, crypto_auth_hmacsha256_BYTES); } crypto_auth_hmacsha256_init(out crypto_auth_hmacsha256_state state, keyHandle, (UIntPtr)keyHandle.Length); crypto_auth_hmacsha256_update(ref state, ref data.DangerousGetPinnableReference(), (ulong)data.Length); crypto_auth_hmacsha256_final(ref state, ref temp.DangerousGetPinnableReference()); int result = sodium_memcmp(ref temp.DangerousGetPinnableReference(), ref mac.DangerousGetPinnableReference(), (UIntPtr)mac.Length); return(result == 0); } finally { sodium_memzero(ref temp.DangerousGetPinnableReference(), (UIntPtr)temp.Length); } }
public bool TryExportText( SecureMemoryHandle keyHandle, Span <byte> blob, out int blobSize) { Debug.Assert(keyHandle != null); blobSize = _blobTextSize; if (blob.Length < blobSize) { return(false); } Span <byte> temp = stackalloc byte[_blobSize]; try { _blobHeader.CopyTo(temp); Serialize(keyHandle, temp.Slice(_blobHeader.Length)); Armor.EncodeToUtf8(temp, s_beginLabel, s_endLabel, blob); return(true); } finally { sodium_memzero(ref MemoryMarshal.GetReference(temp), (UIntPtr)temp.Length); } }
public static void Alloc(int length, out SecureMemoryHandle handle) { Debug.Assert(length >= 0); handle = sodium_malloc((UIntPtr)length); handle._length = length; }
public static SharedSecret Import( ReadOnlySpan <byte> sharedSecret) { if (sharedSecret.Length > 128) { throw Error.Argument_SharedSecretLength(nameof(sharedSecret), 128.ToString()); } Sodium.Initialize(); SecureMemoryHandle sharedSecretHandle = null; bool success = false; try { SecureMemoryHandle.Import(sharedSecret, out sharedSecretHandle); success = true; } finally { if (!success && sharedSecretHandle != null) { sharedSecretHandle.Dispose(); } } return(new SharedSecret(sharedSecretHandle)); }
public bool TryExportText( SecureMemoryHandle keyHandle, Span <byte> blob, out int blobSize) { Debug.Assert(keyHandle != null); blobSize = _blobTextSize; if (blob.Length < blobSize) { return(false); } Span <byte> temp; try { unsafe { byte *pointer = stackalloc byte[_blobSize]; temp = new Span <byte>(pointer, _blobSize); } _blobHeader.CopyTo(temp); Serialize(keyHandle, temp.Slice(_blobHeader.Length)); Armor.Encode(temp, s_beginLabel, s_endLabel, blob); return(true); } finally { sodium_memzero(ref temp.DangerousGetPinnableReference(), (UIntPtr)temp.Length); } }
private protected override bool TryVerifyCore( SecureMemoryHandle keyHandle, ReadOnlySpan <byte> data, ReadOnlySpan <byte> mac) { Debug.Assert(keyHandle != null); Debug.Assert(keyHandle.Length >= crypto_generichash_blake2b_KEYBYTES_MIN); Debug.Assert(keyHandle.Length <= crypto_generichash_blake2b_KEYBYTES_MAX); Debug.Assert(mac.Length >= crypto_generichash_blake2b_BYTES_MIN); Debug.Assert(mac.Length <= crypto_generichash_blake2b_BYTES_MAX); Span <byte> temp = stackalloc byte[mac.Length]; try { crypto_generichash_blake2b_init(out crypto_generichash_blake2b_state state, keyHandle, (UIntPtr)keyHandle.Length, (UIntPtr)temp.Length); crypto_generichash_blake2b_update(ref state, ref data.DangerousGetPinnableReference(), (ulong)data.Length); crypto_generichash_blake2b_final(ref state, ref temp.DangerousGetPinnableReference(), (UIntPtr)temp.Length); int result = sodium_memcmp(ref temp.DangerousGetPinnableReference(), ref mac.DangerousGetPinnableReference(), (UIntPtr)mac.Length); return(result == 0); } finally { sodium_memzero(ref temp.DangerousGetPinnableReference(), (UIntPtr)temp.Length); } }
private static bool TryVerifyCore( SecureMemoryHandle keyHandle, ReadOnlySpan <byte> data, ReadOnlySpan <byte> hash) { Debug.Assert(keyHandle != null); Debug.Assert(keyHandle.Length >= crypto_generichash_blake2b_KEYBYTES_MIN); Debug.Assert(keyHandle.Length <= crypto_generichash_blake2b_KEYBYTES_MAX); Debug.Assert(hash.Length >= crypto_generichash_blake2b_BYTES_MIN); Debug.Assert(hash.Length <= crypto_generichash_blake2b_BYTES_MAX); Span <byte> temp; try { unsafe { byte *pointer = stackalloc byte[hash.Length]; temp = new Span <byte>(pointer, hash.Length); } crypto_generichash_blake2b_init(out crypto_generichash_blake2b_state state, keyHandle, (UIntPtr)keyHandle.Length, (UIntPtr)temp.Length); crypto_generichash_blake2b_update(ref state, ref data.DangerousGetPinnableReference(), (ulong)data.Length); crypto_generichash_blake2b_final(ref state, ref temp.DangerousGetPinnableReference(), (UIntPtr)temp.Length); int result = sodium_memcmp(ref temp.DangerousGetPinnableReference(), ref hash.DangerousGetPinnableReference(), (UIntPtr)hash.Length); return(result == 0); } finally { sodium_memzero(ref temp.DangerousGetPinnableReference(), (UIntPtr)temp.Length); } }
public static void Import( ReadOnlySpan <byte> span, out SecureMemoryHandle handle) { Alloc(span.Length, out handle); handle.Import(span); }
private protected override void MacCore( SecureMemoryHandle keyHandle, ReadOnlySpan <byte> data, Span <byte> mac) { Debug.Assert(keyHandle != null); Debug.Assert(mac.Length <= crypto_auth_hmacsha256_BYTES); // crypto_auth_hmacsha256 requires a key with a length of exactly // crypto_auth_hmacsha256_KEYBYTES. crypto_auth_hmacsha256_init // accepts a key of arbitrary length. So we use _init here. // crypto_auth_hmacsha256_init hashes the key if it is larger than // the block size. crypto_auth_hmacsha256_init(out crypto_auth_hmacsha256_state state, keyHandle, (UIntPtr)keyHandle.Length); crypto_auth_hmacsha256_update(ref state, in MemoryMarshal.GetReference(data), (ulong)data.Length); // crypto_auth_hmacsha256_final expects an output buffer with a size // of exactly crypto_auth_hmacsha256_BYTES, so we need to copy when // a truncated output is requested. if (mac.Length == crypto_auth_hmacsha256_BYTES) { crypto_auth_hmacsha256_final(ref state, ref MemoryMarshal.GetReference(mac)); } else { Span <byte> temp = stackalloc byte[crypto_auth_hmacsha256_BYTES]; crypto_auth_hmacsha256_final(ref state, ref MemoryMarshal.GetReference(temp)); temp.Slice(0, mac.Length).CopyTo(mac); } }
public int ExportText( SecureMemoryHandle keyHandle, Span <byte> blob) { if (blob.Length < _blobTextSize) { throw new ArgumentException(Error.ArgumentExceptionMessage, nameof(blob)); } Debug.Assert(keyHandle != null); Span <byte> temp; try { unsafe { byte *pointer = stackalloc byte[_blobSize]; temp = new Span <byte>(pointer, _blobSize); } new ReadOnlySpan <byte>(_blobHeader).CopyTo(temp); Serialize(keyHandle, temp.Slice(_blobHeader.Length)); Armor.Encode(temp, s_beginLabel, s_endLabel, blob.Slice(0, _blobTextSize)); return(_blobTextSize); } finally { sodium_memzero(ref temp.DangerousGetPinnableReference(), (UIntPtr)temp.Length); } }
public static Key Import( Algorithm algorithm, ReadOnlySpan <byte> blob, KeyBlobFormat format, KeyExportPolicies exportPolicy = KeyExportPolicies.None) { if (algorithm == null) { throw Error.ArgumentNull_Algorithm(nameof(algorithm)); } SecureMemoryHandle keyHandle = null; byte[] publicKeyBytes = null; bool success = false; try { success = algorithm.TryImportKey(blob, format, out keyHandle, out publicKeyBytes); } finally { if (!success && keyHandle != null) { keyHandle.Dispose(); } } if (!success) { throw Error.Format_InvalidBlob(); } return(new Key(algorithm, exportPolicy, keyHandle, publicKeyBytes)); }
internal override void CreateKey( SecureMemoryHandle keyHandle, out byte[] publicKeyBytes) { publicKeyBytes = new byte[crypto_scalarmult_curve25519_SCALARBYTES]; crypto_scalarmult_curve25519_base(publicKeyBytes, keyHandle); }
public bool TryImportText( ReadOnlySpan <byte> blob, out SecureMemoryHandle keyHandle, out byte[] publicKeyBytes) { Span <byte> temp; try { unsafe { byte *pointer = stackalloc byte[_blobSize]; temp = new Span <byte>(pointer, _blobSize); } if (!Armor.TryDecode(blob, s_beginLabel, s_endLabel, temp)) { keyHandle = null; publicKeyBytes = null; return(false); } return(TryImport(temp, out keyHandle, out publicKeyBytes)); } finally { sodium_memzero(ref temp.DangerousGetPinnableReference(), (UIntPtr)temp.Length); } }
public bool TryExportText( SecureMemoryHandle keyHandle, Span <byte> blob, out int blobSize) { blobSize = _blobTextSize; if (blob.Length < blobSize) { return(false); } Span <byte> temp = stackalloc byte[_blobSize]; try { _blobHeader.CopyTo(temp); Serialize(keyHandle, temp.Slice(_blobHeader.Length)); Armor.EncodeToUtf8(temp, s_beginLabel, s_endLabel, blob.Slice(0, _blobTextSize)); return(true); } finally { CryptographicOperations.ZeroMemory(temp); } }
internal override void EncryptCore( SecureMemoryHandle keyHandle, ReadOnlySpan <byte> nonce, ReadOnlySpan <byte> associatedData, ReadOnlySpan <byte> plaintext, Span <byte> ciphertext) { Debug.Assert(keyHandle != null); Debug.Assert(keyHandle.Length == crypto_aead_aes256gcm_KEYBYTES); Debug.Assert(nonce.Length == crypto_aead_aes256gcm_NPUBBYTES); Debug.Assert(ciphertext.Length == plaintext.Length + crypto_aead_aes256gcm_ABYTES); crypto_aead_aes256gcm_encrypt( ref ciphertext.DangerousGetPinnableReference(), out ulong ciphertextLength, ref plaintext.DangerousGetPinnableReference(), (ulong)plaintext.Length, ref associatedData.DangerousGetPinnableReference(), (ulong)associatedData.Length, IntPtr.Zero, ref nonce.DangerousGetPinnableReference(), keyHandle); Debug.Assert((ulong)ciphertext.Length == ciphertextLength); }
internal override bool TryDecryptCore( SecureMemoryHandle keyHandle, ReadOnlySpan <byte> nonce, ReadOnlySpan <byte> associatedData, ReadOnlySpan <byte> ciphertext, Span <byte> plaintext) { Debug.Assert(keyHandle != null); Debug.Assert(keyHandle.Length == crypto_aead_aes256gcm_KEYBYTES); Debug.Assert(nonce.Length == crypto_aead_aes256gcm_NPUBBYTES); Debug.Assert(plaintext.Length == ciphertext.Length - crypto_aead_aes256gcm_ABYTES); int error = crypto_aead_aes256gcm_decrypt( ref plaintext.DangerousGetPinnableReference(), out ulong plaintextLength, IntPtr.Zero, ref ciphertext.DangerousGetPinnableReference(), (ulong)ciphertext.Length, ref associatedData.DangerousGetPinnableReference(), (ulong)associatedData.Length, ref nonce.DangerousGetPinnableReference(), keyHandle); // libsodium clears the plaintext if decryption fails. Debug.Assert(error != 0 || (ulong)plaintext.Length == plaintextLength); return(error == 0); }
// Converts a key blob into a libsodium secret key. internal virtual bool TryImportKey( ReadOnlySpan <byte> blob, KeyBlobFormat format, out SecureMemoryHandle keyHandle, out byte[] publicKeyBytes) { throw Error.NotSupported_ImportKey(); }
internal override void CreateKey( ReadOnlySpan <byte> seed, out SecureMemoryHandle keyHandle, out PublicKey?publicKey) { publicKey = null; keyHandle = SecureMemoryHandle.CreateFrom(seed); }
internal override void CreateKey( ReadOnlySpan <byte> seed, out SecureMemoryHandle keyHandle, out byte[] publicKeyBytes) { publicKeyBytes = null; SecureMemoryHandle.Import(seed, out keyHandle); }
// Converts a libsodium secret key into a key blob. internal virtual bool TryExportKey( SecureMemoryHandle keyHandle, KeyBlobFormat format, Span <byte> blob, out int blobSize) { throw Error.NotSupported_ExportKey(); }
public Key DeriveKey( SharedSecret sharedSecret, ReadOnlySpan <byte> salt, ReadOnlySpan <byte> info, Algorithm algorithm, KeyExportPolicies exportPolicy = KeyExportPolicies.None) { if (sharedSecret == null) { throw Error.ArgumentNull_SharedSecret(nameof(sharedSecret)); } if (!_supportsSalt && !salt.IsEmpty) { throw Error.Argument_SaltNotSupported(nameof(salt)); } if (algorithm == null) { throw Error.ArgumentNull_Algorithm(nameof(algorithm)); } int seedSize = algorithm.GetDefaultSeedSize(); if (seedSize > MaxOutputSize) { throw Error.NotSupported_CreateKey(); } Debug.Assert(seedSize <= 64); SecureMemoryHandle keyHandle = null; byte[] publicKeyBytes = null; bool success = false; try { Span <byte> seed = stackalloc byte[seedSize]; try { DeriveBytesCore(sharedSecret.Handle, salt, info, seed); algorithm.CreateKey(seed, out keyHandle, out publicKeyBytes); success = true; } finally { sodium_memzero(ref seed.DangerousGetPinnableReference(), (UIntPtr)seed.Length); } } finally { if (!success && keyHandle != null) { keyHandle.Dispose(); } } return(new Key(algorithm, exportPolicy, keyHandle, publicKeyBytes)); }
protected override void Serialize( SecureMemoryHandle keyHandle, Span <byte> span) { Debug.Assert(keyHandle.Size == crypto_scalarmult_curve25519_SCALARBYTES); Debug.Assert(span.Length == crypto_scalarmult_curve25519_SCALARBYTES); keyHandle.CopyTo(span); }
internal SharedSecret( SecureMemoryHandle sharedSecretHandle) { Debug.Assert(sharedSecretHandle != null); sharedSecretHandle.MakeReadOnly(); _handle = sharedSecretHandle; }
internal override void CreateKey( ReadOnlySpan <byte> seed, out SecureMemoryHandle keyHandle, out PublicKey?publicKey) { Debug.Assert(seed.Length == crypto_aead_chacha20poly1305_ietf_KEYBYTES); publicKey = null; keyHandle = SecureMemoryHandle.CreateFrom(seed); }