打算开发一个软件使用rsa加密的东西,所以有用到数字证书这块,最近遇到些问题,
问题一:使用如下代码添加数字证书后,在证书管理器的当前用户和本地计算机下都找不到这张证书。
1 using (X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser)) 2 { 3 store.Open(OpenFlags.MaxAllowed); 4 5 string documentsPath = Windows.Storage.ApplicationData.Current.LocalFolder.Path; 6 var path = Path.Combine(documentsPath, @"Mytestcer.pfx");//Mytestcer.pfx 7 X509Certificate2 myX509Certificate2 = new X509Certificate2( 8 path, //证书路径 9 "1111111111", //证书的私钥保护密码 10 X509KeyStorageFlags.Exportable|X509KeyStorageFlags.UserKeySet | X509KeyStorageFlags.PersistKeySet//表示此证书的私钥以后还可以导出 11 ); 12 store.Add(myX509Certificate2); 13 14 }
问题二:如上面代码添加完数字证书后,使用下列代码却可以看查到我导入的数字证书。
1 using (X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser)) 2 { 3 store.Open(OpenFlags.ReadOnly); 4 foreach (var item in store.Certificates) 5 { 6 if (item.SerialNumber == "22307124FFF203CD55109BB") 7 { 8 X509Certificate2 cert = new X509Certificate2(item.RawData,"", X509KeyStorageFlags.UserKeySet|X509KeyStorageFlags.Exportable|X509KeyStorageFlags.PersistKeySet); 9 var s = item.Export(X509ContentType.Pkcs12); 10 result = item.Export(X509ContentType.Pfx, "1111111111"); 11 break; 12 } 13 } 14 }
问题三,我直接点击证书,安装后在证书管理器上可以看到这张证书,在使用问题二去取证书的时候,发现有两张一样的证书,且其中一张可以用item.Export(X509ContentType.Pfx, "1111111111");取到密钥,其中一张报错:拒绝访问。
问题四,在添加一个应用,使用问题二的方式访问数字证书,可以取到一张证书,但是取私钥时报错:拒绝访问。
推断是安装时有权限问题,应用程序自己安装的证书只能自己去调用,且证书管理器看不见,为应用程序私有的证书,安装的证书其他程序找不到。
尝试过下列方式:
方式一:设置下列两个属性为true,尝试结果:失败,在xamarin uwp环境下不存在下面的设置,及没有下面命名空间的设置字段。
System.Security.Cryptography.RSACryptoServiceProvider.UseMachineKeyStore=true;
System.Security.Cryptography.DSACryptoServiceProvider.UseMachineKeyStore=true;
方式二:如何使用System.Security.Cryptography命名空间,尝试结果:解决,在早期版本中不存在上面的命名空间,需升级到最新版本,
Microsoft.NETCore.UniversalWindowsPlatform 版本5.2.2
方式三:设置下列文件的权限,C:Documents and SettingsAll UsersApplication DataMicrosoftCryptoRSA)的“完全控制”权限设置为“允许”。尝试结果:设置后无效果。
方式四:证书管理器->本地计算机->证书->所有任务->管理私钥,添加权限。尝试结果:未能解决问题三。
方式五:使用下列方式插入数字证书,
1 FileOpenPicker picker = new FileOpenPicker(); 2 picker.FileTypeFilter.Add(".pfx"); 3 StorageFile pfxFile = await picker.PickSingleFileAsync(); 4 if (pfxFile != null) 5 { 6 // 将证书内容转为base64字符串 7 IBuffer buffer = await FileIO.ReadBufferAsync(pfxFile); 8 string cerB64 = CryptographicBuffer.EncodeToBase64String(buffer); 9 // 密码 10 string password = "11111111111"; 11 // 导入证书 12 // 导入到当前用户存储 13 await CertificateEnrollmentManager.UserCertificateEnrollmentManager.ImportPfxDataAsync(cerB64, password, ExportOption.Exportable, KeyProtectionLevel.NoConsent, InstallOptions.DeleteExpired, "GoodBoy"); 14 // 导入到当前应用存储 15 //await CertificateEnrollmentManager.ImportPfxDataAsync(cerB64, password, ExportOption.Exportable, KeyProtectionLevel.ConsentOnly, InstallOptions.DeleteExpired, "GoodBoy"); 16 }
尝试结果:导入的证书可以正常显示了,也可以隐藏,解释如下:系统为每个APP创建一个独立的证书存储区,在应用安装时创建,在应用卸载时被删除。因此,每个应用的证书只能自己使用,不能访问其他应用的证书。如果希望让其他应用也能使用证书,就要用“共享用户证书”,被共享的证书会导入到当前系统的用户证书存储区中,所以,其他应用都可以访问,当然了,为了防止别有用心的人乱来,应用只有导入和读取的权限,不能写入和删除证书。
感谢园区东邪独孤提供的文档,我是搬运工。
方式六:使用方式五导入证书时,如果选择
CertificateEnrollmentManager.UserCertificateEnrollmentManager.ImportPfxDataAsync导入证书,那证书可见,但是使用问题二方法去取私钥时会提示拒绝访问,使用
CertificateEnrollmentManager.ImportPfxDataAsync导入证书,证书只单独应用可用,证书不可见,使用问题二方式访问私钥正常使用。尝试结果:问题解决。
遗留问题:当为共享证书的时候,拒绝访问私钥。