牧羊人nacy
对于它的价值,我最终使用 Portable.BouncyCastle NuGet 包和一些 UWP API 的组合来解决这个问题。我所做的一些示例(伪)代码如下:// Asymmetric key pairRsaKeyPairGenerator keyPairGenerator = new RsaKeyPairGenerator();keyPairGenerator.Init( new KeyGenerationParameters( new SecureRandom(new CryptoApiRandomGenerator()), 2048));AsymmetricCipherKeyPair keyPair = keyPairGenerator.GenerateKeyPair();// Create certificateX509V3CertificateGenerator generator = new X509V3CertificateGenerator();generator.SetSubjectDN("foo");generator.SetIssuerDN("foo");generator.SetSerialNumber(new BigInteger("12345").Abs());generator.SetNotBefore(DateTime.UtcNow);generator.SetNotAfter(DateTime.UtcNow + TimeSpan.FromYears(1));generator.SetPublicKey(keyPair.Public);BouncyCastleX509Certificate certificate = generator.Generate( new Asn1SignatureFactory("SHA1WithRSA", keyPair.Private));// Create PKCS12 certificate bytes.Pkcs12Store store = new Pkcs12Store();X509CertificateEntry certificateEntry = new X509CertificateEntry(certificate);string friendlyName = "Friendly Name";string password = "password";store.SetCertificateEntry(friendlyName, certificateEntry);store.SetKeyEntry( friendlyName, new AsymmetricKeyEntry(keyPair.Private), new X509CertificateEntry[] { certificateEntry });string pfxData;using (MemoryStream memoryStream = new MemoryStream(512)){ store.Save(memoryStream, password.ToCharArray(), this.SecureRandom); pfxData = CryptographicBuffer.EncodeToBase64String(memoryStream.ToArray().AsBuffer());}// Add the certificate to the cert storeawait CertificateEnrollmentManager.ImportPfxDataAsync( pfxData, password, ExportOption.NotExportable, KeyProtectionLevel.NoConsent, InstallOptions.DeleteExpired, friendlyName);// Read the UWP cert from the cert storeCertificate uwpCertificate = (await CertificateStores.FindAllAsync( new CertificateQuery { FriendlyName = friendlyName }))[0];// Create the UWP HTTP client.HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName);filter.ClientCertificate = uwpCertificate;HttpClient httpClient = new HttpClient(filter);// Profit!