-
Notifications
You must be signed in to change notification settings - Fork 549
Expand file tree
/
Copy pathAlipayCertificationUtil.cs
More file actions
105 lines (92 loc) · 3.87 KB
/
AlipayCertificationUtil.cs
File metadata and controls
105 lines (92 loc) · 3.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/*
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
* See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers
* for more information concerning the license and the contributors participating to this project.
*/
using System.Buffers;
using System.Globalization;
using System.Numerics;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
namespace AspNet.Security.OAuth.Alipay;
/// <summary>
/// https://github.com/alipay/alipay-sdk-net-all/blob/b482d75d322e740760f9230d2a3859090af642a7/v2/AlipaySDKNet.Standard/Util/AntCertificationUtil.cs
/// </summary>
internal static class AlipayCertificationUtil
{
public static string GetCertSN(ReadOnlySpan<char> certContent)
{
using var cert = X509Certificate2.CreateFromPem(certContent);
return GetCertSN(cert);
}
public static string GetCertSN(X509Certificate2 cert)
{
var issuerDN = cert.Issuer.Replace(", ", ",", StringComparison.InvariantCulture);
var serialNumber = new BigInteger(cert.GetSerialNumber()).ToString(CultureInfo.InvariantCulture);
if (issuerDN.StartsWith("CN", StringComparison.InvariantCulture))
{
return CalculateMd5(issuerDN + serialNumber);
}
var attributes = issuerDN.Split(',');
Array.Reverse(attributes);
return CalculateMd5(string.Join(',', attributes) + serialNumber);
}
public static string GetRootCertSN(ReadOnlySpan<char> rootCertContent, string signType = "RSA2")
{
var rootCertSN = string.Join('_', GetRootCertSNCore(rootCertContent, signType));
return rootCertSN;
}
private static IEnumerable<string> GetRootCertSNCore(X509Certificate2Collection x509Certificates, string signType)
{
foreach (X509Certificate2 cert in x509Certificates)
{
var signatureAlgorithm = cert.SignatureAlgorithm.Value;
if (signatureAlgorithm != null)
{
if ((signType.StartsWith("RSA", StringComparison.InvariantCultureIgnoreCase) &&
signatureAlgorithm.StartsWith("1.2.840.113549.1.1", StringComparison.InvariantCultureIgnoreCase)) ||
(signType.StartsWith("SM2", StringComparison.InvariantCultureIgnoreCase) &&
signatureAlgorithm.StartsWith("1.2.156.10197.1.501", StringComparison.InvariantCultureIgnoreCase)))
{
yield return GetCertSN(cert);
}
}
}
}
private static IEnumerable<string> GetRootCertSNCore(ReadOnlySpan<char> rootCertContent, string signType)
{
X509Certificate2Collection x509Certificates = [];
x509Certificates.ImportFromPem(rootCertContent);
return GetRootCertSNCore(x509Certificates, signType);
}
/// <summary>
/// https://github.com/dotnet/runtime/blob/v9.0.8/src/libraries/System.Text.Json/Common/JsonConstants.cs#L12
/// </summary>
private const int StackallocByteThreshold = 256;
private static string CalculateMd5(ReadOnlySpan<char> chars)
{
var lenU8 = Encoding.UTF8.GetMaxByteCount(chars.Length);
byte[]? array = null;
Span<byte> bytes = lenU8 <= StackallocByteThreshold ?
stackalloc byte[StackallocByteThreshold] :
(array = ArrayPool<byte>.Shared.Rent(lenU8));
try
{
Encoding.UTF8.TryGetBytes(chars, bytes, out var bytesWritten);
bytes = bytes[..bytesWritten];
Span<byte> hash = stackalloc byte[MD5.HashSizeInBytes];
#pragma warning disable CA5351
MD5.HashData(bytes, hash);
#pragma warning restore CA5351
return Convert.ToHexStringLower(hash);
}
finally
{
if (array != null)
{
ArrayPool<byte>.Shared.Return(array);
}
}
}
}