RT,在C#中实现,依赖.netFramework2.0

BouncyCastle中提供了PKCS12Store,Pkcs12StoreBuilder,AsymmetricKeyEntry,X509CertificateEntry等接口

其中Pkcs12StoreBuilder建立一个PKCS12Store对象,PKCS12Store对象来产生一个pfx/p12格式的证书,该证书符合PKCS#12规范

PKCS#12的ref,见RSA给出的文档:PKCS #12: Personal Information Exchange Syntax Standard

PKCS12Store中方法load()和save(),加载和保存证书,其中的实现比较复杂,处理过程主要是对PKCS12证书内容的一组SafeBag进行判断和解包。一个PKCS12结构分析的文档:http://cid-780607117452312e.office.live.com/self.aspx/.Public/PKCS%5E3l2%E7%BB%93%E6%9E%84%E5%88%86%E6%9E%90.pdf

AsymmetricKeyEntry中封装了私钥,支持属性包的附加,attributeBag,可以方便获得私钥或封装私钥

类似的,X509CertificateEntry封装了公钥证书,支持属性包的附加和x509certificateV3的扩展,可以从中方便获得公钥等

这样,就可以通过产生一个pfx证书,保存CA的密钥对。这里pfx的certBag中证书采用的是x509certificateV1格式,因为没有用到v3格式证书的扩展

思路如下:

1、产生一对密钥对,其产生方法和保存方法之前有说过

产生密钥对:用Bouncy Castle的C#版API产生公钥和私钥

保存方法:在C#中保存Bouncy Castle生成的密钥对

2、配置自定义的x509Name对象,BouncyCastle中采用HashTable这种结构。

3、X509CertificateEntry封装公钥证书时,添加一个该公钥证书的alias。在测试过程(测试2)中,我导入该pfx证书到电脑的当前用户my证书存储区中,用微软的接口去读取时,用FriendlyName(就是该alias)来查找比较方便。另外(测试1),在store.Aliases这个属性去查找相匹配的alias,然后通过该alias从store中获取AsymmetricKeyEntry和X509CertificateEntry,从而获取私钥和公钥。

属性包FriendlyName,RSA的pkcs#9文档中提到过,不过不详细。链接:PKCS #9: Selected Attribute Types

另外,上面提到的属性包attributeBag和SafeBag,BouncyCastle中的PkcsObjectIdentifiers这个源代码中全部定义,可以参考下,其命名空间为:Org.BouncyCastle.Asn1.Pkcs.PkcsObjectIdentifiers(根据该命名空间的命名方式,可以在源代码中快速定位到该源文件)

生成的代码:

  1. char[] passwd = "123456".ToCharArray();   //pfx密码
  2. IAsymmetricCipherKeyPairGenerator keyGen = GeneratorUtilities.GetKeyPairGenerator("RSA");
  3. RsaKeyGenerationParameters genPar = new RsaKeyGenerationParameters(
  4. BigInteger.ValueOf(0x10001), new SecureRandom(), 2048, 25);
  5. keyGen.Init(genPar);
  6. AsymmetricCipherKeyPair keypair = keyGen.GenerateKeyPair();
  7. RsaKeyParameters pubKey = (RsaKeyParameters)keypair.Public; //CA公钥
  8. RsaKeyParameters priKey = (RsaKeyParameters)keypair.Private;    //CA私钥
  9. Hashtable attrs = new Hashtable();
  10. ArrayList order = new ArrayList();
  11. attrs.Add(X509Name.C, "CN");    //country code
  12. //attrs.Add(X509Name.ST, "Guangdong province");   //province name
  13. //attrs.Add(X509Name.L, "Guangzhou city");    //locality name
  14. attrs.Add(X509Name.O, "South China Normal University"); //organization
  15. attrs.Add(X509Name.OU, "South China Normal University");    //organizational unit name
  16. attrs.Add(X509Name.CN, "CAcert");   //common name
  17. attrs.Add(X509Name.E, "popozhude@qq.com");
  18. order.Add(X509Name.C);
  19. //order.Add(X509Name.ST);
  20. //order.Add(X509Name.L);
  21. order.Add(X509Name.O);
  22. order.Add(X509Name.OU);
  23. order.Add(X509Name.CN);
  24. order.Add(X509Name.E);
  25. X509Name issuerDN = new X509Name(order, attrs);
  26. X509Name subjectDN = issuerDN;  //自签证书,两者一样
  27. X509V1CertificateGenerator v1certGen = new X509V1CertificateGenerator();
  28. v1certGen.SetSerialNumber(new BigInteger(128, new Random()));   //128位
  29. v1certGen.SetIssuerDN(issuerDN);
  30. v1certGen.SetNotBefore(DateTime.UtcNow.AddDays(-1));
  31. v1certGen.SetNotAfter(DateTime.UtcNow.AddDays(365));
  32. v1certGen.SetSubjectDN(subjectDN);
  33. v1certGen.SetPublicKey(pubKey); //公钥
  34. v1certGen.SetSignatureAlgorithm("SHA1WithRSAEncryption");
  35. Org.BouncyCastle.X509.X509Certificate CAcert = v1certGen.Generate(priKey);
  36. CAcert.CheckValidity();
  37. CAcert.Verify(pubKey);
  38. //属性包
  39. /*
  40. Hashtable bagAttr = new Hashtable();
  41. bagAttr.Add(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id,
  42. new DerBmpString("CA's Primary Certificate"));
  43. bagAttr.Add(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Id,
  44. new SubjectKeyIdentifierStructure(pubKey));
  45. X509CertificateEntry certEntry = new X509CertificateEntry(CAcert,bagAttr);
  46. */
  47. X509CertificateEntry certEntry = new X509CertificateEntry(CAcert);
  48. Pkcs12Store store = new Pkcs12StoreBuilder().Build();
  49. store.SetCertificateEntry("CA's Primary Certificate", certEntry);   //设置证书
  50. X509CertificateEntry[] chain = new X509CertificateEntry[1];
  51. chain[0] = certEntry;
  52. store.SetKeyEntry("CA's Primary Certificate", new AsymmetricKeyEntry(priKey), chain);   //设置私钥
  53. FileStream fout = File.Create("CA.pfx");
  54. store.Save(fout, passwd, new SecureRandom());   //保存
  55. fout.Close();

测试1 ,把生成的pfx证书导入到计算机的证书store中,用微软提供的api去查找该证书。怎么通过MMC的证书管理单元对证书存储区进行管理:在MMC的证书管理单元中对证书存储区进行管理

  1. X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
  2. store.Open(OpenFlags.ReadOnly);
  3. X509Certificate2Collection storeCollection = (X509Certificate2Collection)store.Certificates;
  4. X509Certificate2 x509cert = null;
  5. foreach (X509Certificate2 cert in storeCollection)
  6. {
  7. //if(cert.Subject==" E = popozhude@qq.com, CN = CAcert, OU = South China Normal University, O = South China Normal University, C = CN")
  8. if (cert.FriendlyName == "CA's Primary Certificate")
  9. {
  10. x509cert = cert;
  11. //break;
  12. }
  13. }
  14. store.Close();
  15. if (x509cert == null)
  16. {
  17. Console.WriteLine("找不到指定的证书");
  18. }
  19. Console.WriteLine(x509cert.ToString());
  20. Console.ReadLine();

测试2 :读取本地的pfx证书,获取其公钥和私钥,这里主要用BouncyCastle的API,然后又把公钥证书转换成byte数组,再用微软的证书类api读取,成功。

  1. FileStream fs = File.OpenRead("CA.pfx");      //debug文件夹下的证书
  2. char[] passwd = "123456".ToCharArray();
  3. Pkcs12Store store = new Pkcs12StoreBuilder().Build();
  4. store.Load(fs, passwd); //加载证书
  5. string alias = null;
  6. foreach (string str in store.Aliases)
  7. {
  8. if (store.IsKeyEntry(str))
  9. alias = str;
  10. }
  11. if (alias == null)
  12. {
  13. Console.WriteLine("alias 为空");
  14. }
  15. else
  16. Console.WriteLine(alias);
  17. AsymmetricKeyEntry keyEntry = store.GetKey(alias);
  18. RsaKeyParameters priKey = (RsaKeyParameters)keyEntry.Key;   //取得私钥
  19. X509CertificateEntry certEntry = store.GetCertificate(alias);
  20. Org.BouncyCastle.X509.X509Certificate x509cert = certEntry.Certificate;
  21. RsaKeyParameters pubKey = (RsaKeyParameters)x509cert.GetPublicKey();    //取得公钥
  22. x509cert.Verify(pubKey);    //test ok
  23. byte[] certByte = x509cert.GetEncoded();    //把该证书转换成字节数组
  24. X509Certificate2 cert2 = new X509Certificate2(certByte);    //微软的类X509Certificate2
  25. Console.WriteLine(cert2.ToString());    //显示正常,说明可以把BouncyCastle产生的数字v3证书,转换成X509Certificate2处理的证
  26. Console.Read();

 

BouncyCastle产生一个PKCS#12规范的PFX/p12证书的更多相关文章

  1. C#使用BouncyCastle生成PKCS#12数字证书

    背景 生成数字证书用于PDF文档数字签名 数字证书需要考虑环境兼容性,如linux.windows 网上资料不全或版本多样 本文章主要介绍了在C#中使用BouncyCastle生成PKCS#12个人信 ...

  2. PKCS#12

    http://blog.csdn.net/cuiran/article/details/7816696 数字证书介绍 一.什么是数字证书 数字证书就是互联网通讯中标志通讯各方身份信息的一系列数据,提供 ...

  3. .NET Core加解密实战系列之——使用BouncyCastle制作p12(.pfx)数字证书

    简介 加解密现状,编写此系列文章的背景: 需要考虑系统环境兼容性问题(Linux.Windows) 语言互通问题(如C#.Java等)(加解密本质上没有语言之分,所以原则上不存在互通性问题) 网上资料 ...

  4. JKS和PKCS#12

    今天来点实际工作中的硬通货! 与计费系统打交道,少不了用到加密/解密实现.为了安全起见,通过非对称加密交换对称加密密钥更是不可或缺.那么需要通过什么载体传递非对称算法公钥/私钥信息?数字证书是公钥的载 ...

  5. RSA私钥和公钥文件格式 (pkcs#1, pkcs#8, pkcs#12, pem)

    RSA私钥和公钥文件格式 (pkcs#1, pkcs#8, pkcs#12, pem) 2018年03月07日 11:57:22 阅读数:674 Format Name Description PKC ...

  6. 一步一步实现一个Promise A+规范的 Promise

    2015年6月,ES2015(即ES6)正式发布后受到了非常多的关注.其中很重要的一点是 Promise 被列为了正式规范. 在此之前很多库都对异步编程/回调地狱实现了类 Promise 的应对方案, ...

  7. java-信息安全(十七)-*.PFX(*.p12)&个人信息交换文件

    原文地址 http://snowolf.iteye.com/blog/735294 与计费系统打交道,少不了用到加密/解密实现.为了安全起见,通过非对称加密交换对称加密密钥更是不可或缺.那么需要通过什 ...

  8. 【转载】OpenSSL 提取 pfx 数字证书公钥与私钥

    转自https://www.cnblogs.com/Irving/p/9551110.html OpenSSL 提取 pfx 数字证书公钥与私钥   由于之前生产环境已经使用了 Identityser ...

  9. PKCS#1规范阅读笔记2--------公私钥ASN.1结构

    PKCS#1种介绍了哈希算法的OID等的ASN.1结构,因为使用ASN.1的解码工具(比如:ASN1View)时,会自动显示出各OID的含义,所以这里就不说明了.下面就只简单摘抄一下RSA公私钥的AS ...

随机推荐

  1. 前端学习资源(js)

    JavaScript JavaScript | MDN JavaScript 秘密花园 JavaScript 标准参考教程(alpha) 给 JavaScript 初心者的 ES2015 实战 Col ...

  2. GO简易聊天系统后台源码分享

    本人是搞移动客户端开发的,业余时间接触到golang这么个可爱的囊地鼠,于是就写了这么个测试项目:简易版的聊天系统,功能包括注册,登陆,群聊和单聊,无需使用mysql,数据都存在了文本里.本人纯粹兴趣 ...

  3. 四 GPU 并行编程的存储系统架构

    前言 在用 CUDA 对 GPU 进行并行编程的过程中,除了需要对线程架构要有深刻的认识外,也需要对存储系统架构有深入的了解. 这两个部分是 GPU 编程中最为基础,也是最为重要的部分,需要花时间去理 ...

  4. 跟开涛老师学shiro -- 身份验证

    身份验证,即在应用中谁能证明他就是他本人.一般提供如他们的身份ID一些标识信息来表明他就是他本人,如提供身份证,用户名/密码来证明. 在shiro中,用户需要提供principals (身份)和cre ...

  5. iOS7中如何去除UINavigationbar下边的那条黑线

    做项目过程中遇到要去掉导航栏下面的一条黑线,从网上找到的一个方法 默认UINavigationbar样式 准备用于替换的背景 替换后的效果 if ([self.navigationController ...

  6. Codeforces Round #367 (Div. 2) A B C 暴力 二分 dp(字符串的反转)

    A. Beru-taxi time limit per test 1 second memory limit per test 256 megabytes input standard input o ...

  7. 图像质量评价指标之Matlab实现

    在图像处理算法研究中,很多时候需要有客观评价指标来对算法的性能进行评价. 比如,在图像复原.图像滤波算法研究中,需要采用客观评价指标来定量的来测试算法恢复出的图像相对于参考图像的好坏程度. 本文介绍文 ...

  8. 本文使用springMVC和ajax,实现将JSON对象返回到页面

    一.引言 本文使用springMVC和ajax做的一个小小的demo,实现将JSON对象返回到页面,没有什么技术含量,纯粹是因为最近项目中引入了springMVC框架. 二.入门例子 ①. 建立工程, ...

  9. hihoCoder #1033 : 交错和 (数位Dp)

    题目大意: 给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0, a1, ..., an - 1,定义交错和函数: f(x) = a0 - a1 + a2 - ... + ( - 1)n - ...

  10. vimium 使用心得

    首先,建议记住chrom自己的支持的快捷键 https://support.google.com/chrome/answer/157179?hl=zh-Hans&hlrm=en-GB& ...