-
Notifications
You must be signed in to change notification settings - Fork 550
Add support for Alipay certificate signing #1131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
AigioL
wants to merge
5
commits into
aspnet-contrib:dev
Choose a base branch
from
AigioL:dev
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+239
−2
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
acc2fe0
Add support for Alipay certificate signing
AigioL eabb122
Merge branch 'aspnet-contrib:dev' into dev
AigioL e54d133
Improve naming conventions and documentation comments
AigioL db212e0
Streamline code
AigioL 872164d
Corrected Annotations
AigioL File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
45 changes: 45 additions & 0 deletions
45
src/AspNet.Security.OAuth.Alipay/AlipayAuthenticationOptionsExtensions.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| /* | ||
| * 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 AspNet.Security.OAuth.Alipay; | ||
| using Microsoft.Extensions.FileProviders; | ||
|
|
||
| namespace Microsoft.Extensions.DependencyInjection; | ||
|
|
||
| /// <summary> | ||
| /// Extension methods to configure Sign in with Alipay authentication capabilities for an HTTP application pipeline. | ||
| /// </summary> | ||
| public static class AlipayAuthenticationOptionsExtensions | ||
| { | ||
| /// <summary> | ||
| /// Configures the application to use a specified private key to generate a client secret for the provider. | ||
| /// </summary> | ||
| /// <param name="options">The Apple authentication options to configure.</param> | ||
| /// <param name="privateKeyFile"> | ||
| /// A delegate to a method to return the <see cref="IFileInfo"/> for the private | ||
| /// key which is passed the value of <see cref="AlipayAuthenticationOptions.ApplicationCertificateSnKeyId"/> or <see cref="AlipayAuthenticationOptions.RootCertificateSnKeyId"/>. | ||
| /// </param> | ||
| /// <returns> | ||
| /// The value of the <paramref name="options"/> argument. | ||
| /// </returns> | ||
| public static AlipayAuthenticationOptions UsePrivateKey( | ||
| [NotNull] this AlipayAuthenticationOptions options, | ||
| [NotNull] Func<string, IFileInfo> privateKeyFile) | ||
| { | ||
| options.UseCertificateSignatures = true; | ||
| options.PrivateKey = async (keyId, cancellationToken) => | ||
| { | ||
| var fileInfo = privateKeyFile(keyId); | ||
|
|
||
| using var stream = fileInfo.CreateReadStream(); | ||
| using var reader = new StreamReader(stream); | ||
|
|
||
| return (await reader.ReadToEndAsync(cancellationToken)).AsMemory(); | ||
| }; | ||
|
|
||
| return options; | ||
| } | ||
| } |
105 changes: 105 additions & 0 deletions
105
src/AspNet.Security.OAuth.Alipay/AlipayCertificationUtil.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,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); | ||
| } | ||
| } | ||
| } | ||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.