C#自带加密库在System.Security.Cryptography中,但是其自带的加密功能比较简单,只有一些基础的加密功能,一些高级加密方法如Aead加密,在最新版本中也只支持AesGcm96。
而基于C#的比较全面的第三方加密库如BouncyCastle.NET功能虽然比较全面,但是执行效率比较差,一般比用C语言实现的加密库要慢2-3倍。
基于C语言的libsodium是功能强大而且执行效率也很高的加密库,其内部API组织比较合理,使用起来非常简单,但是不支持C#直接调用,不过由于其使用的C函数封装,而且函数参数都是比较简单的原始数据类型,所以通过C#的Native Invoke,能比较方便的调用这些函数,只需要注意数据类型的转换和启用编译器的不安全代码(Unsafe)支持即可。
下面通过哈希计算和Aead加密,演示libsodium的调用方法。
Sha256哈希计算:
[DllImport(dll, CallingConvention = CallingConvention.Cdecl)] static unsafe extern int crypto_hash_sha256 ( byte* dst, byte* src, long srcLen ); public static unsafe void sha256(byte[] src, byte[] dst) { fixed (byte* srcPtr = src, dstPtr = dst) { crypto_hash_sha256 ( dstPtr, srcPtr, src.Length ); } } public static unsafe byte[] sha256(byte[] src) { byte[] dst = new byte[32]; sha256(src, dst); return dst; }
Argon2密码哈希:
[DllImport(dll, CallingConvention = CallingConvention.Cdecl)] public static unsafe extern int crypto_pwhash_argon2id( byte* key, long keyLen, byte* pwd, long pwdLen, byte* salt, long cpu, int mem, int alg);
Aead加密模式的chacha20poly1305和gcm:
[DllImport(Sodium.dll, CallingConvention = CallingConvention.Cdecl)] public static unsafe extern int crypto_aead_chacha20poly1305_ietf_encrypt( byte* cipher, out ulong cipherLen, byte* data, ulong dataLen, byte* aad, ulong aadLen, byte* nsec, byte* nonce, byte* key); [DllImport(Sodium.dll, CallingConvention = CallingConvention.Cdecl)] public static unsafe extern int crypto_aead_chacha20poly1305_ietf_decrypt( byte* data, out ulong dataLen, byte* nsec, byte* cipher, ulong cipherLen, byte* aad, ulong aadLen, byte* nonce, byte* key); [DllImport(Sodium.dll, CallingConvention = CallingConvention.Cdecl)] public static unsafe extern int crypto_aead_aes256gcm_encrypt( byte* cipher, out ulong cipherLen, byte* data, ulong dataLen, byte* aad, ulong aadLen, byte* nsec, byte* nonce, byte* key); [DllImport(Sodium.dll, CallingConvention = CallingConvention.Cdecl)] public static unsafe extern int crypto_aead_aes256gcm_decrypt( byte* data, out ulong dataLen, byte* nsec, byte* cipher, ulong cipherLen, byte* aad, ulong aadLen, byte* nonce, byte* key);
Argon2id类的封装:
public class Argon2id : KeyGen { public Argon2id() => Sodium.checkLib(); public const int SaltSize = 16; public byte[] salt; public long cpu = 32; public int mem = 64.mb(); public override byte[] genKey(byte[] pwd, int keySize) => Sodium.argon2id(pwd, salt, cpu, mem, keySize); }
Aead模式的类的封装:
public abstract class SodiumAeadCrypt : AeadCrypt { public SodiumAeadCrypt() => Sodium.checkLib(); public override unsafe void encrypt(byte[] data, int dataOff, int dataLen, byte[] nonce, byte[] cipher, int cipherOff = 0, byte[] aad = null) { fixed (byte* cipherPtr = cipher) fixed (byte* dataPtr = data) fixed (byte* noncePtr = nonce) fixed (byte* keyPtr = Key) fixed (byte* aadPtr = aad) { encFunc ( cipherPtr + cipherOff, out var cipherLen, dataPtr + dataOff, (ulong)dataLen, aadPtr, (ulong)(aad?.Length ?? 0), null, noncePtr, keyPtr ); } } public override unsafe bool decrypt(byte[] cipher, int cipherOff, int cipherLen, byte[] nonce, byte[] data, int dataOff = 0, byte[] aad = null) { fixed (byte* cipherPtr = cipher) fixed (byte* dataPtr = data) fixed (byte* noncePtr = nonce) fixed (byte* keyPtr = Key) fixed (byte* aadPtr = aad) { return decFunc ( dataPtr + dataOff, out var dataLen, null, cipherPtr + cipherOff, (ulong)cipherLen, aadPtr, (ulong)(aad?.Length ?? 0), noncePtr, keyPtr ) == 0; } } protected abstract DecryptFunc decFunc { get; } protected abstract EncryptFunc encFunc { get; } protected unsafe delegate int EncryptFunc( byte* cipher, out ulong cipherLen, byte* data, ulong dataLen, byte* aad, ulong aadLen, byte* nsec, byte* nonce, byte* key); protected unsafe delegate int DecryptFunc( byte* data, out ulong dataLen, byte* nsec, byte* cipher, ulong cipherLen, byte* aad, ulong aadLen, byte* nonce, byte* key); }
其他libsodium的API都可以通过类似的方法进行调用。
Github:
https://github.com/bsmith-zhao/vfs/tree/main/util/crypt/sodium
标签:libsodium,加密,ulong,aad,C#,unsafe,int,byte,public From: https://www.cnblogs.com/bsmith/p/17766763.html