【问题标题】:BouncyCastle undefined length ASN1BouncyCastle 未定义长度 ASN1
【发布时间】:2017-10-28 12:44:30
【问题描述】:

我尝试从 BountyCastle X509Certificate 和 PKCS12 获取 X509Certificate2。我使用以下代码:

 certificate = new X509Certificate2(rawData, password, storageFlags);

我生成 rawData,如下所示:

using (MemoryStream pfxData = new MemoryStream())
{
   X509CertificateEntry[] chain = new X509CertificateEntry[1];

   chain[0] = new X509CertificateEntry(x509);
   pkcsStore.SetKeyEntry(applicationName, new AsymmetricKeyEntry(subjectKeyPair.Private), chain);
   pkcsStore.Save(pfxData, passcode.ToCharArray(), random);
   var rawData = pfx.ToArray();
}

问题是,我得到以下异常:

经过几天的研究,我发现问题出在 ASN1 的 Mono 实现上。此实现不允许“未定义长度编码”。如果我在 Windows 上使用代码,效果会很好。

我的问题

有什么方法可以将 pfxData 流转换为有效的 ASN1 结构?

我已经用下面的代码试过了:

Asn1InputStream asn1InputStream = new Asn1InputStream(pfxData);
var asn1Object = asn1InputStream.ReadObject();

MemoryStream memoryStream = new MemoryStream();
new Asn1OutputStream((Stream)memoryStream).WriteObject(asn1Object);
var asn1ByteArray = memoryStream.ToArray();

certificate = new X509Certificate2(asn1ByteArray);

但是使用这段代码,我得到以下异常:

“索引超出范围。必须为非负数且小于集合的大小。\n参数名称:startIndex”

我将 Xamarin PCL 与 .NET Standard 1.3 一起使用,我只能使用“Portable.BouncyCastle”Nuget 包。

更新异常堆栈跟踪(将 BER 转换为 DER):

05-28 15:19:54.895 D/Mono    ( 3808): Assembly Ref addref Mono.Security[0x9b4fe080] -> System[0xac8de400]: 17
05-28 15:19:54.957 I/mono-stdout( 3808): System.AggregateException: One or more errors occurred. ---> System.Security.Cryptography.CryptographicException: Unable to decode certificate. ---> System.Security.Cryptography.CryptographicException: Input data cannot be coded as a valid certificate. ---> System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
System.AggregateException: One or more errors occurred. ---> System.Security.Cryptography.CryptographicException: Unable to decode certificate. ---> System.Security.Cryptography.CryptographicException: Input data cannot be coded as a valid certificate. ---> System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: startIndex
  at System.String.IndexOf (System.String value, System.Int32 startIndex, System.Int32 count, System.StringComparison comparisonType) [0x0002a] in <d18287e1d683419a8ec3216fd78947b9>:0 
  at System.String.IndexOf (System.String value, System.Int32 startIndex, System.StringComparison comparisonType) [0x00009] in <d18287e1d683419a8ec3216fd78947b9>:0 
  at System.String.IndexOf (System.String value, System.Int32 startIndex) [0x00000] in <d18287e1d683419a8ec3216fd78947b9>:0 
  at Mono.Security.X509.X509Certificate.PEM (System.String type, System.Byte[] data) [0x00030] in <2940be14d5a1446694e2193e9029b558>:0 
  at Mono.Security.X509.X509Certificate..ctor (System.Byte[] data) [0x00014] in <2940be14d5a1446694e2193e9029b558>:0 
   --- End of inner exception stack trace ---
  at Mono.Security.X509.X509Certificate..ctor (System.Byte[] data) [0x0002f] in <2940be14d5a1446694e2193e9029b558>:0 
05-28 15:19:54.958 I/mono-stdout( 3808): Parameter name: startIndex
  at System.Security.Cryptography.X509Certificates.X509Certificate2ImplMono.Import (System.Byte[] rawData, System.String password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) [0x0000b] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
   --- End of inner exception stack trace ---
  at System.Security.Cryptography.X509Certificates.X509Certificate2ImplMono.Import (System.Byte[] rawData, System.String password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) [0x00031] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
  at System.Security.Cryptography.X509Certificates.X509Helper2.Import (System.Byte[] rawData, System.String password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags, System.Boolean disableProvider) [0x00020] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
  at System.Security.Cryptography.X509Certificates.X509Certificate2.Import (System.Byte[] rawData, System.String password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) [0x00000] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
  at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor (System.Byte[] rawData) [0x00011] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
05-28 15:19:54.958 I/mono-stdout( 3808):   at System.String.IndexOf (System.String value, System.Int32 startIndex, System.Int32 count, System.StringComparison comparisonType) [0x0002a] in <d18287e1d683419a8ec3216fd78947b9>:0 
  at APP.Models.Services.ACommunicationService.CreateCertificate (System.String storeType, System.String storePath, System.String password, System.String applicationUri, System.String applicationName, System.String subjectName, System.Collections.Generic.IList`1[T] domainNames, System.UInt16 keySize, System.DateTime startTime, System.UInt16 lifetimeInMonths, System.UInt16 hashSizeInBits, System.Boolean isCA, System.Security.Cryptography.X509Certificates.X509Certificate2 issuerCAKeyCert) [0x003b5] in C:\projects\APP - Kopie\APP_XamarinApplication\APP\APP\APP\Models\Services\ACommunicationService.cs:517 
05-28 15:19:54.958 I/mono-stdout( 3808):   at System.String.IndexOf (System.String value, System.Int32 startIndex, System.StringComparison comparisonType) [0x00009] in <d18287e1d683419a8ec3216fd78947b9>:0 
  at APP.Models.Services.ACommunicationService.CreateCertificate (System.String storeType, System.String storePath, System.String applicationUri, System.String applicationName, System.String subjectName, System.Collections.Generic.IList`1[T] serverDomainNames, System.UInt16 keySize, System.UInt16 lifetimeInMonths, System.UInt16 hashSizeInBits) [0x00001] in C:\projects\APP - Kopie\APP_XamarinApplication\APP\APP\APP\Models\Services\ACommunicationService.cs:318 
  at APP.Models.Services.ACommunicationService+<ACommunicationServiceAsync>d__18.MoveNext () [0x00972] in C:\projects\APP - Kopie\APP_XamarinApplication\APP\APP\APP\Models\Services\ACommunicationService.cs:214 
   --- End of inner exception stack trace ---
05-28 15:19:54.959 I/mono-stdout( 3808):   at System.String.IndexOf (System.String value, System.Int32 startIndex) [0x00000] in <d18287e1d683419a8ec3216fd78947b9>:0 
  at System.Threading.Tasks.Task.ThrowIfExceptional (System.Boolean includeTaskCanceledExceptions) [0x00011] in <d18287e1d683419a8ec3216fd78947b9>:0 
  at System.Threading.Tasks.Task.Wait (System.Int32 millisecondsTimeout, System.Threading.CancellationToken cancellationToken) [0x00043] in <d18287e1d683419a8ec3216fd78947b9>:0 
  at System.Threading.Tasks.Task.Wait () [0x00000] in <d18287e1d683419a8ec3216fd78947b9>:0 
  at APP.Models.Services.ACommunicationService..ctor (PCLStorage.IFolder rootFolder) [0x00010] in C:\projects\APP - Kopie\APP_XamarinApplication\APP\APP\APP\Models\Services\ACommunicationService.cs:46 
05-28 15:19:54.959 I/mono-stdout( 3808):   at Mono.Security.X509.X509Certificate.PEM (System.String type, System.Byte[] data) [0x00030] in <2940be14d5a1446694e2193e9029b558>:0 
05-28 15:19:54.959 I/mono-stdout( 3808):   at Mono.Security.X509.X509Certificate..ctor (System.Byte[] data) [0x00014] in <2940be14d5a1446694e2193e9029b558>:0 
05-28 15:19:54.959 I/mono-stdout( 3808):    --- End of inner exception stack trace ---
05-28 15:19:54.959 I/mono-stdout( 3808):   at Mono.Security.X509.X509Certificate..ctor (System.Byte[] data) [0x0002f] in <2940be14d5a1446694e2193e9029b558>:0 
05-28 15:19:54.959 I/mono-stdout( 3808):   at System.Security.Cryptography.X509Certificates.X509Certificate2ImplMono.Import (System.Byte[] rawData, System.String password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) [0x0000b] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
---> (Inner Exception #0) System.Security.Cryptography.CryptographicException: Unable to decode certificate. ---> System.Security.Cryptography.CryptographicException: Input data cannot be coded as a valid certificate. ---> System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
05-28 15:19:54.961 I/mono-stdout( 3808):    --- End of inner exception stack trace ---
05-28 15:19:54.961 I/mono-stdout( 3808):   at System.Security.Cryptography.X509Certificates.X509Certificate2ImplMono.Import (System.Byte[] rawData, System.String password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) [0x00031] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
05-28 15:19:54.961 I/mono-stdout( 3808):   at System.Security.Cryptography.X509Certificates.X509Helper2.Import (System.Byte[] rawData, System.String password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags, System.Boolean disableProvider) [0x00020] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
05-28 15:19:54.962 I/mono-stdout( 3808):   at System.Security.Cryptography.X509Certificates.X509Certificate2.Import (System.Byte[] rawData, System.String password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) [0x00000] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
05-28 15:19:54.962 I/mono-stdout( 3808):   at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor (System.Byte[] rawData) [0x00011] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
Parameter name: startIndex
05-28 15:19:54.963 I/mono-stdout( 3808):   at APP.Models.Services.ACommunicationService.CreateCertificate (System.String storeType, System.String storePath, System.String password, System.String applicationUri, System.String applicationName, System.String subjectName, System.Collections.Generic.IList`1[T] domainNames, System.UInt16 keySize, System.DateTime startTime, System.UInt16 lifetimeInMonths, System.UInt16 hashSizeInBits, System.Boolean isCA, System.Security.Cryptography.X509Certificates.X509Certificate2 issuerCAKeyCert) [0x003b5] in C:\projects\APP - Kopie\APP_XamarinApplication\APP\APP\APP\Models\Services\ACommunicationService.cs:517 
05-28 15:19:54.963 I/mono-stdout( 3808):   at APP.Models.Services.ACommunicationService.CreateCertificate (System.String storeType, System.String storePath, System.String applicationUri, System.String applicationName, System.String subjectName, System.Collections.Generic.IList`1[T] serverDomainNames, System.UInt16 keySize, System.UInt16 lifetimeInMonths, System.UInt16 hashSizeInBits) [0x00001] in C:\projects\APP - Kopie\APP_XamarinApplication\APP\APP\APP\Models\Services\ACommunicationService.cs:318 
05-28 15:19:54.964 I/mono-stdout( 3808):   at APP.Models.Services.ACommunicationService+<ACommunicationServiceAsync>d__18.MoveNext () [0x00972] in C:\projects\APP - Kopie\APP_XamarinApplication\APP\APP\APP\Models\Services\ACommunicationService.cs:214 
05-28 15:19:54.964 I/mono-stdout( 3808):    --- End of inner exception stack trace ---
05-28 15:19:54.965 I/mono-stdout( 3808):   at System.Threading.Tasks.Task.ThrowIfExceptional (System.Boolean includeTaskCanceledExceptions) [0x00011] in <d18287e1d683419a8ec3216fd78947b9>:0 
05-28 15:19:54.965 I/mono-stdout( 3808):   at System.Threading.Tasks.Task.Wait (System.Int32 millisecondsTimeout, System.Threading.CancellationToken cancellationToken) [0x00043] in <d18287e1d683419a8ec3216fd78947b9>:0 
05-28 15:19:54.965 I/mono-stdout( 3808):   at System.Threading.Tasks.Task.Wait () [0x00000] in <d18287e1d683419a8ec3216fd78947b9>:0 
  at System.String.IndexOf (System.String value, System.Int32 startIndex, System.Int32 count, System.StringComparison comparisonType) [0x0002a] in <d18287e1d683419a8ec3216fd78947b9>:0 
05-28 15:19:54.965 I/mono-stdout( 3808):   at APP.Models.Services.ACommunicationService..ctor (PCLStorage.IFolder rootFolder) [0x00010] in C:\projects\APP - Kopie\APP_XamarinApplication\APP\APP\APP\Models\Services\ACommunicationService.cs:46 
05-28 15:19:54.966 I/mono-stdout( 3808): ---> (Inner Exception #0) System.Security.Cryptography.CryptographicException: Unable to decode certificate. ---> System.Security.Cryptography.CryptographicException: Input data cannot be coded as a valid certificate. ---> System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
05-28 15:19:54.966 I/mono-stdout( 3808): Parameter name: startIndex
05-28 15:19:54.967 I/mono-stdout( 3808):   at System.String.IndexOf (System.String value, System.Int32 startIndex, System.Int32 count, System.StringComparison comparisonType) [0x0002a] in <d18287e1d683419a8ec3216fd78947b9>:0 
  at System.String.IndexOf (System.String value, System.Int32 startIndex, System.StringComparison comparisonType) [0x00009] in <d18287e1d683419a8ec3216fd78947b9>:0 
  at System.String.IndexOf (System.String value, System.Int32 startIndex) [0x00000] in <d18287e1d683419a8ec3216fd78947b9>:0 
  at Mono.Security.X509.X509Certificate.PEM (System.String type, System.Byte[] data) [0x00030] in <2940be14d5a1446694e2193e9029b558>:0 
  at Mono.Security.X509.X509Certificate..ctor (System.Byte[] data) [0x00014] in <2940be14d5a1446694e2193e9029b558>:0 
   --- End of inner exception stack trace ---
  at Mono.Security.X509.X509Certificate..ctor (System.Byte[] data) [0x0002f] in <2940be14d5a1446694e2193e9029b558>:0 
  at System.Security.Cryptography.X509Certificates.X509Certificate2ImplMono.Import (System.Byte[] rawData, System.String password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) [0x0000b] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
   --- End of inner exception stack trace ---
  at System.Security.Cryptography.X509Certificates.X509Certificate2ImplMono.Import (System.Byte[] rawData, System.String password, System.Security.Cryptography.X509Certif
icates.X509KeyStorageFlags keyStorageFlags) [0x00031] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
  at System.Security.Cryptography.X509Certificates.X509Helper2.Import (System.Byte[] rawData, System.String password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags, System.Boolean disableProvider) [0x00020] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
  at System.Security.Cryptography.X509Certificates.X509Certificate2.Import (System.Byte[] rawData, System.String password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) [0x00000] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
  at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor (System.Byte[] rawData) [0x00011] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
  at APP.Models.Services.ACommunicationService.CreateCertificate (System.String storeType, System.String storePath, System.String password, System.String applicationUri, System.String applicationName, System.String subjectName, System.Collections.Generic.IList`1[T] domainNames, System.UInt16 keySize, System.DateTime startTime, 
System.UInt16 lifetimeInMonths, System.UInt16 hashSizeInBits, System.Boolean isCA, System.Security.Cryptography.X509Certificates.X509Certificate2 issuerCAKeyCert) [0x003b5] in C:\projects\APP - Kopie\APP_XamarinApplication\APP\APP\APP\Models\Services\ACommunicationService.cs:517 
  at APP.Models.Services.ACommunicationService.CreateCertificate (System.String storeType, System.String storePath, System.String applicationUri, System.String applicationName, System.String subjectName, System.Collections.Generic.IList`1[T] serverDomainNames, System.UInt16 keySize, System.UInt16 lifetimeInMonths, System.UInt16 hashSizeInBits) [0x00001] in C:\projects\APP - Kopie\APP_XamarinApplication\APP\APP\APP\Models\Services\ACommunicationService.cs:318 
  at APP.Models.Services.ACommunicationService+<ACommunicationServiceAsync>d__18.MoveNext () [0x00972] in C:\projects\APP - Kopie\APP_XamarinApplication\APP\APP\APP\Models\Services\ACommunicationService.cs:214 <---
05-28 15:19:54.968 I/mono-stdout( 3808):   at System.String.IndexOf (System.String value, System.Int32 startIndex, System.StringComparison comparisonType) [0x00009] in <d18287e1d683419a8ec3216fd78947b9>:0 
05-28 15:19:54.969 I/mono-stdout( 3808):   at System.String.IndexOf (System.String value, System.Int32 startIndex) [0x00000] in <d18287e1d683419a8ec3216fd78947b9>:0 
05-28 15:19:54.969 I/mono-stdout( 3808):   at Mono.Security.X509.X509Certificate.PEM (System.String type, System.Byte[] data) [0x00030] in <2940be14d5a1446694e2193e9029b558>:0 
05-28 15:19:54.969 I/mono-stdout( 3808):   at Mono.Security.X509.X509Certificate..ctor (System.Byte[] data) [0x00014] in <2940be14d5a1446694e2193e9029b558>:0 
05-28 15:19:54.969 I/mono-stdout( 3808):    --- End of inner exception stack trace ---
05-28 15:19:54.969 I/mono-stdout( 3808):   at Mono.Security.X509.X509Certificate..ctor (System.Byte[] data) [0x0002f] in <2940be14d5a1446694e2193e9029b558>:0 
05-28 15:19:54.969 I/mono-stdout( 3808):   at System.Security.Cryptography.X509Certificates.X509Certificate2ImplMono.Import (System.Byte[] rawData, System.String password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) [0x0000b] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
05-28 15:19:54.969 I/mono-stdout( 3808):    --- End of inner exception stack trace ---
05-28 15:19:54.969 I/mono-stdout( 3808):   at System.Security.Cryptography.X509Certificates.X509Certificate2ImplMono.Import (System.Byte[] rawData, System.String password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) [0x00031] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
05-28 15:19:54.970 I/mono-stdout( 3808):   at System.Security.Cryptography.X509Certificates.X509Helper2.Import (System.Byte[] rawData, System.String password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags, System.Boolean disableProvider) [0x00020] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
05-28 15:19:54.970 I/mono-stdout( 3808):   at System.Security.Cryptography.X509Certificates.X509Certificate2.Import (System.Byte[] rawData, System.String password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) [0x00000] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
05-28 15:19:54.970 I/mono-stdout( 3808):   at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor (System.Byte[] rawData) [0x00011] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
05-28 15:19:54.970 I/mono-stdout( 3808):   at APP.Models.Services.ACommunicationService.CreateCertificate (System.String storeType, System.String storePath, System.String password, System.String applicationUri, System.String applicationName, System.String subjectName, System.Collections.Generic.IList`1[T] domainNames, System.UInt16 keySize, System.DateTime startTime, System.UInt16 lifetimeInMonths, System.UInt16 hashSizeInBits, System.Boolean isCA, System.Security.Cryptography.X509Certificates.X509Certificate2 issuerCAKeyCert) [0x003b5] in C:\projects\APP - Kopie\APP_XamarinApplication\APP\APP\APP\Models\Services\ACommunicationService.cs:517 
05-28 15:19:54.971 I/mono-stdout( 3808):   at APP.Models.Services.ACommunicationService.CreateCertificate (System.String storeType, System.String storePath, System.String applicationUri, System.String applicationName, System.String subjectName, System.Collections.Generic.IList`1[T] serverDomainNames, System.UInt16 keySize, System.UInt16 lifetimeInMonths, System.UInt16 hashSizeInBits) [0x00001] in C:\projects\APP - Kopie\APP_XamarinApplication\APP\APP\APP\Models\Services\ACommunicationService.cs:318 
05-28 15:19:54.971 I/mono-stdout( 3808):   at APP.Models.Services.ACommunicationService+<ACommunicationServiceAsync>d__18.MoveNext () [0x00972] in C:\projects\APP - Kopie\APP_XamarinApplication\APP\APP\APP\Models\Services\ACommunicationService.cs:214 <---

编辑:我在 BouncyCastle GitHub 上发布了同样的问题:BouncyCastle GitHub

编辑 2: 我已测试保存 PKCS 并使用字符串构造函数创建 X509Certificate2,如下所示:

var pkcsPath = pkcsStorePath + "/pkcs.p12";
File.WriteAllBytes(pkcsPath, pfxData.ToArray());

// Exception is thrown on this line (Undefined length):
certificate = new X509Certificate2(pkcsPath, string.Empty);

编辑 3: 我在 BouncyCastle 库中找到了方法 var util = Pkcs12Utilities.ConvertToDefiniteLength(pfxData.ToArray(), certPassword.ToCharArray());,如果我在 File.WriteAllBytes(pkcsPath, util); 行之前使用此方法,则会出现“未定义长度编码”异常。离开了。但是现在,我得到了以下异常:

06-01 21:05:54.903 I/mono-stdout(31001): System.Security.Cryptography.CryptographicException: Input data cannot be coded as a valid certificate. ---> System.Security.Cryptography.CryptographicException: Input data cannot be coded as a valid certificate.
System.Security.Cryptography.CryptographicException: Input data cannot be coded as a valid certificate. ---> System.Security.Cryptography.CryptographicException: Input data cannot be coded as a valid certificate.
  at Mono.Security.X509.X509Certificate.Parse (System.Byte[] data) [0x0003b] in <2940be14d5a1446694e2193e9029b558>:0 
   --- End of inner exception stack trace ---
  at Mono.Security.X509.X509Certificate.Parse (System.Byte[] data) [0x00322] in <2940be14d5a1446694e2193e9029b558>:0 
  at Mono.Security.X509.X509Certificate..ctor (System.Byte[] data) [0x00030] in <2940be14d5a1446694e2193e9029b558>:0 
06-01 21:05:54.905 I/mono-stdout(31001):   at Mono.Security.X509.X509Certificate.Parse (System.Byte[] data) [0x0003b] in <2940be14d5a1446694e2193e9029b558>:0 
  at System.Security.Cryptography.X509Certificates.X509Certificate2ImplMono.Import (System.Byte[] rawData, System.String password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) [0x00041] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
  at System.Security.Cryptography.X509Certificates.X509Helper2.Import (System.Byte[] rawData, System.String password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags, System.Boolean disableProvider) [0x00020] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
  at System.Security.Cryptography.X509Certificates.X509Certificate2.Import (System.Byte[] rawData, System.String password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) [0x00000] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
  at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor (System.Byte[] rawData, System.String password) [0x00011] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
  at Pkcs12TestProject.MyClass.CreateCertific
ate (System.String storeType, System.String storePath, System.String password, System.String applicationUri, System.String applicationName, System.String subjectName, System.Collections.Generic.IList`1[T] domainNames, System.UInt16 keySize, System.DateTime startTime, System.UInt16 lifetimeInMonths, System.UInt16 hashSizeInBits, System.Boolean isCA, System.Security.Cryptography.X509Certificates.X509Certificate2 issuerCAKeyCert, System.String pkcsStorePath) [0x00377] in C:\OneDrive\VS\Pkcs12TestProject\Pkcs12TestProject\Pkcs12TestProject\MyClass.cs:223 
06-01 21:05:54.906 I/mono-stdout(31001):    --- End of inner exception stack trace ---
06-01 21:05:54.906 I/mono-stdout(31001):   at Mono.Security.X509.X509Certificate.Parse (System.Byte[] data) [0x00322] in <2940be14d5a1446694e2193e9029b558>:0 
06-01 21:05:54.906 I/mono-stdout(31001):   at Mono.Security.X509.X509Certificate..ctor (System.Byte[] data) [0x00030] in <2940be14d5a1446694e2193e9029b558>:0 
06-01 21:05:54.906 I/mono-stdout(31001):   at System.Security.Cryptography.X509Certificates.X509Certificate2ImplMono.Import (System.Byte[] rawData, System.String password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) [0x00041] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
06-01 21:05:54.906 I/mono-stdout(31001):   at System.Security.Cryptography.X509Certificates.X509Helper2.Import (System.Byte[] rawData, System.String password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags, System.Boolean disableProvider) [0x00020] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
06-01 21:05:54.906 I/mono-stdout(31001):   at System.Security.Cryptography.X509Certificates.X509Certificate2.Import (System.Byte[] rawData, System.String password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) [0x00000] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
06-01 21:05:54.907 I/mono-stdout(31001):   at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor (System.Byte[] rawData, System.String password) [0x00011] in <1a27f8ea09e3480db932cbde0eaedfb2>:0 
06-01 21:05:54.907 I/mono-stdout(31001):   at Pkcs12TestProject.MyClass.CreateCertificate (System.String storeType, System.String storePath, System.String password, System.String applicationUri, System.String applicationName, System.String subjectName, System.Collections.Generic.IList`1[T] domainNames, System.UInt16 keySize, System.DateTime startTime, System.UInt16 lifetimeInMonths, System.UInt16 hashSizeInBits, System.Boolean isCA, System.Security.Cryptography.X509Certificates.X509Certificate2 issuerCAKeyCert, System.String pkcsStorePath) [0x00377] in C:\OneDrive\VS\Pkcs12TestProject\Pkcs12TestProject\Pkcs12TestProject\MyClass.cs:223 

编辑 4: 如果我在 X509Certificate2 方法中使用来自 BountyCastle 的 X509 证书作为原始数据,效果很好!但它没有私钥..

【问题讨论】:

  • DER 中不允许有无限长度(DER 是 BER 的更受限制的子集)。
  • 谢谢,但我如何在 c# 中使用您的提示?
  • 您有来自 Bouncy Castle 的 DotNetUtilities 类吗?它可以将 bouncy cert 转换为 .Net cert,而不是您可以使用 .Net cert 来创建 X509Certificate2
  • 我无法使用 DotNetUtilities。但是,如果我尝试从 BC X509Certificate 创建 X509Certificate2,效果会很好。仅当我添加包含私钥和 X509 证书的 PKCS 流时,我才会收到此错误。
  • 如果可能的话,使用 DotNetUtilities,然后我可以创建一个 .Net 证书并将其添加到 Mono.Security PKCS12。因为如果我使用 Mono PKCS12,它会很好用。但问题是,我有 BC X509 证书。

标签: c# xamarin mono portable-class-library x509


【解决方案1】:

我发现了一些关于您的问题的错误报告,其中列出了可能的解决方法。我自己没有合适的环境来测试这个 - 抱歉。但从历史看来,它似乎并没有真正得到解决:

  1. Bugreport:

正如您所经历的那样,这明确说明了 BouncyCastle 的问题。 Sebastian Pouliot 在comment3 中发布了一个示例代码,他认为可以使用(或其中的一部分)来解决使用mono.security.dll 的问题。我不知道您的用例是否允许使用它。它与 MonoDroid 一起提供。
他在comment 中详细介绍,并在 github 上链接了示例代码:https://github.com/mono/mono/blob/master/mcs/tools/security/makecert.cs

  1. 还有其他人发布了这个问题。 BouncyCastle 没有明确提及:http://lists.ximian.com/pipermail/mono-bugs/2010-October/104908.html

他在帖子末尾的解决方法:
[一旦你有正确的 PKCS#12] 引用:

将 byte[] PKCS#12 写入一个临时文件并用字符串加载它 构造函数。


更新 cmets 中提供的源代码

希望我的系统正常运行,因为它需要几个小时才能运行。但后来我得到了以下工作。

解决办法是把StoreBuilder的UseDEREncoding改为true

前面的小错误修复
发现:您输入了 string.empty 作为密码,但使用密码保护了证书。我认为这是不正确的。如果我输入密码,我会再次收到第一个错误 CryptographicException Certificate cannot becoded to valid certificate。

所以首先我改变了这个:

certificate = new X509Certificate2(pkcsPath, string.Empty);

到

certificate = new X509Certificate2(pkcsPath, certPassword);

修复
现在我不知道这是否是你想要的,但在改变它之后,我没有得到一个例外,而是一个证书对象。

“使用内存流”块的完整变化最终看起来是这样的:

using (MemoryStream pfxData = new MemoryStream())
{
    // **Change 1**: The DER Encoding is enabled on the
    // store builder
    Pkcs12StoreBuilder builder = new Pkcs12StoreBuilder();
    builder.SetUseDerEncoding(true);
    Pkcs12Store pkcsStore = builder.Build();
    // change - end

    X509CertificateEntry[] chain = new X509CertificateEntry[1];
    string certPassword = Guid.NewGuid().ToString();
    chain[0] = new X509CertificateEntry(x509);
    pkcsStore.SetKeyEntry(applicationName, new AsymmetricKeyEntry(subjectKeyPair.Private), chain);
    pkcsStore.Save(pfxData, certPassword.ToCharArray(), random);

    var pkcsPath = pkcsStorePath + "/pkcs.p12";

    File.WriteAllBytes(pkcsPath, pfxData.ToArray());

    // **Change 2**: Use certificate password
    certificate = new X509Certificate2(pkcsPath, certPassword);
    // **Change 3**: Possible to use array instead of filename
    // works as well. Just uncomment
    //certificate = new X509Certificate2(pfxData.ToArray(), certPassword);

}

【讨论】:

  • 感谢您的回答。 1.我尝试使用makecert.cs的一些代码,但无法编译。问题是,X509CertificateBuilder 有一些不可用的属性。例如:X509CertificateBuilder.SubjectPublicKey(错误:对类型“AsymmetricAlgorithm”的引用声称它是在“mscorlib”中定义的,但找不到) 2. 它对我不起作用。也许,PKCS#12 不正确!?我用保存文件的代码更新了我的问题,并创建了一个测试项目:1drv.ms/u/s!Aq2x4hOwAC2nl5J9ZzkHXyB-2-DObw
  • @SeanStayn 看起来我需要一台 Mac 来解决这个问题?和一个VS2017?不能让它运行,因为我没有这两个。但是来自代码阅读的一个问题:就在异常行(215)之前,您创建了一个 certPassword 但您在 ctor 中使用了 string.empty?那不需要是 certPassword(你的 newGuid)吗?
  • 你不需要mac,但你需要android sdk,xamarin等等。你是对的,在正常情况下我输入certPassword,但是为了尝试,我改变了它到 string.Empty.
  • @SeanStayn 更新了我的答案。如果您因某种原因无法使用此解决方案或无法使用,请告诉我。
  • 你应该把你的名字改成英雄!谢谢! :) 它完美地工作!!!!!! :) 关键是你的第一个改变。您应该在答案中提示“builder.SetUseDerEncoding(true);”是问题所在。 :)
【解决方案2】:

部分问题似乎在于 Mono 的 X509Certificate2 byte[] 构造函数与 .NET Framework 的 X509Certificate2 byte[] 构造函数的行为不同。

浏览mono source 看起来X509Certificate2(byte[]) 将尝试加载为X.509(个人)证书,然后加载为带有null(相对于空)密码的PFX。

我对你的调用堆栈最困惑的地方是它尝试了 PEM 解码......这应该只在第一个字节不是 0x30 (per the source) 而是 0x30 时发生也应该是 PFX 的第一个字节。 (然后是他们没有找到-----BEGIN CERTIFICATE----- 的错误处理导致ArgumentOutOfRangeException 让我走上了一条糟糕的道路。哦,好吧。)

new X509Certificate2(byte[]) 的 .NET Framework 实现更加灵活:

  • X.509 DER
  • X.509 PEM
  • PFX 空密码
  • PFX 空密码
  • PKCS#7 SignedCms 签名者证书
  • AuthentiCode 签名者证书

(所以 Mono 只尝试了 .NET Framework / .NET Core 的一半)

根据 cmets,您似乎正在使用密码为空的 PFX,因此更改您的后 DER 规范化调用

new X509Certificate2(asn1ByteArray)

到

new X509Certificate2(asn1ByteArray, string.Empty)

应该解决问题的这个特定方面。

【讨论】:

  • 感谢您的回答。我正在使用带有真实密码的密码参数,并且我已经尝试使用 string.Empty,但异常仍然存在。我用代码创建了一个测试项目。代码在 MyClass.cs 的 PCL 中:1drv.ms/u/s!Aq2x4hOwAC2nl5J9ZzkHXyB-2-DObw
猜你喜欢
  • 2014-04-26
  • 2016-12-11
  • 1970-01-01
  • 2018-05-04
  • 1970-01-01
  • 1970-01-01
  • 2012-10-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多