CryptographyUtilsTest.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. using System.Security;
  2. using System.Security.Cryptography;
  3. namespace MeloongCore.Tests;
  4. public class CryptographyUtilsTest : TestBase {
  5. #region 对称加密
  6. [Test]
  7. [Arguments("")]
  8. [Arguments("PCL")]
  9. [Arguments("中文内容 Test 123 !@#$%^&*()")]
  10. public async Task 对称加密_往返(string sourceString) {
  11. string encryptedString = CryptographyUtils.AesEncrypt(sourceString, "PCL-Key-中文");
  12. if (!string.IsNullOrEmpty(sourceString))
  13. await Assert.That(encryptedString != sourceString).IsTrue();
  14. await Assert.That(CryptographyUtils.AesDecrypt(encryptedString, "PCL-Key-中文")).IsEqualTo(sourceString);
  15. }
  16. [Test]
  17. public async Task 对称加密_随机化()
  18. => await Assert.That(CryptographyUtils.AesEncrypt("same source", "same key") != CryptographyUtils.AesEncrypt("same source", "same key")).IsTrue();
  19. [Test]
  20. public void 对称加密_篡改失败() {
  21. byte[] encryptedBytes = Convert.FromBase64String(CryptographyUtils.AesEncrypt("source", "key"));
  22. encryptedBytes[encryptedBytes.Length - 1] ^= 1;
  23. Assert.Throws<CryptographicException>(() => CryptographyUtils.AesDecrypt(Convert.ToBase64String(encryptedBytes), "key"));
  24. }
  25. [Test]
  26. public void AesDecrypt_TamperedIvFails() {
  27. byte[] encryptedBytes = Convert.FromBase64String(CryptographyUtils.AesEncrypt("source", "key"));
  28. encryptedBytes[1] ^= 1;
  29. Assert.Throws<CryptographicException>(() => CryptographyUtils.AesDecrypt(Convert.ToBase64String(encryptedBytes), "key"));
  30. }
  31. [Test]
  32. public void 对称加密_错误密钥失败() {
  33. Assert.Throws<CryptographicException>(() => CryptographyUtils.AesDecrypt(CryptographyUtils.AesEncrypt("source", "key"), "bad key"));
  34. }
  35. [Test]
  36. public void 对称加密_格式错误失败()
  37. => Assert.Throws<CryptographicException>(() => CryptographyUtils.AesDecrypt("not base64", "key"));
  38. #endregion
  39. #region ECDSA 签名
  40. [Test]
  41. public async Task ECDSA_字符串与标准API互通() {
  42. using CngKey key = CngKey.Create(CngAlgorithm.ECDsaP256, null, new CngKeyCreationParameters {ExportPolicy = CngExportPolicies.AllowPlaintextExport});
  43. string publicKey = Convert.ToBase64String(key.Export(CngKeyBlobFormat.EccPublicBlob));
  44. string privateKey = Convert.ToBase64String(key.Export(CngKeyBlobFormat.EccPrivateBlob));
  45. const string text = "土豆码 / 配置签名 中文\r\n";
  46. byte[] data = Encoding.UTF8.GetBytes(text);
  47. string signature = CryptographyUtils.EcdsaSign(text, privateKey);
  48. using ECDsaCng ecdsa = new(key) {HashAlgorithm = CngAlgorithm.Sha256};
  49. await Assert.That(Convert.FromBase64String(signature).Length).IsEqualTo(64);
  50. await Assert.That(ecdsa.VerifyData(data, Convert.FromBase64String(signature))).IsTrue();
  51. CryptographyUtils.EcdsaVerify(text, Convert.ToBase64String(ecdsa.SignData(data)), publicKey);
  52. Assert.Throws<SecurityException>(() => CryptographyUtils.EcdsaVerify(text.Replace("\r\n", "\n"), signature, publicKey));
  53. }
  54. [Test]
  55. [Arguments(0)]
  56. [Arguments(63)]
  57. [Arguments(65)]
  58. public async Task ECDSA_错误签名长度被拒绝(int length) {
  59. using CngKey key = CngKey.Create(CngAlgorithm.ECDsaP256);
  60. string publicKey = Convert.ToBase64String(key.Export(CngKeyBlobFormat.EccPublicBlob));
  61. Exception? error = null;
  62. try {
  63. CryptographyUtils.EcdsaVerify("test", Convert.ToBase64String(new byte[length]), publicKey);
  64. } catch (Exception ex) {
  65. error = ex;
  66. }
  67. await Assert.That(error).IsNotNull();
  68. }
  69. #endregion
  70. }