CertificateGenerator.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. using MediaBrowser.Model.Logging;
  2. using System;
  3. using System.Collections;
  4. using System.Security.Cryptography;
  5. using System.Xml;
  6. namespace Emby.Server.Core.Cryptography
  7. {
  8. public class CertificateGenerator
  9. {
  10. private const string MonoTestRootAgency = "<RSAKeyValue><Modulus>v/4nALBxCE+9JgEC0LnDUvKh6e96PwTpN4Rj+vWnqKT7IAp1iK/JjuqvAg6DQ2vTfv0dTlqffmHH51OyioprcT5nzxcSTsZb/9jcHScG0s3/FRIWnXeLk/fgm7mSYhjUaHNI0m1/NTTktipicjKxo71hGIg9qucCWnDum+Krh/k=</Modulus><Exponent>AQAB</Exponent><P>9jbKxMXEruW2CfZrzhxtull4O8P47+mNsEL+9gf9QsRO1jJ77C+jmzfU6zbzjf8+ViK+q62tCMdC1ZzulwdpXQ==</P><Q>x5+p198l1PkK0Ga2mRh0SIYSykENpY2aLXoyZD/iUpKYAvATm0/wvKNrE4dKJyPCA+y3hfTdgVag+SP9avvDTQ==</Q><DP>ISSjCvXsUfbOGG05eddN1gXxL2pj+jegQRfjpk7RAsnWKvNExzhqd5x+ZuNQyc6QH5wxun54inP4RTUI0P/IaQ==</DP><DQ>R815VQmR3RIbPqzDXzv5j6CSH6fYlcTiQRtkBsUnzhWmkd/y3XmamO+a8zJFjOCCx9CcjpVuGziivBqi65lVPQ==</DQ><InverseQ>iYiu0KwMWI/dyqN3RJYUzuuLj02/oTD1pYpwo2rvNCXU1Q5VscOeu2DpNg1gWqI+1RrRCsEoaTNzXB1xtKNlSw==</InverseQ><D>nIfh1LYF8fjRBgMdAH/zt9UKHWiaCnc+jXzq5tkR8HVSKTVdzitD8bl1JgAfFQD8VjSXiCJqluexy/B5SGrCXQ49c78NIQj0hD+J13Y8/E0fUbW1QYbhj6Ff7oHyhaYe1WOQfkp2t/h+llHOdt1HRf7bt7dUknYp7m8bQKGxoYE=</D></RSAKeyValue>";
  11. public static void CreateSelfSignCertificatePfx(
  12. string fileName,
  13. string hostname,
  14. string password,
  15. ILogger logger)
  16. {
  17. if (string.IsNullOrWhiteSpace(fileName))
  18. {
  19. throw new ArgumentNullException("fileName");
  20. }
  21. byte[] sn = Guid.NewGuid().ToByteArray();
  22. string subject = string.Format("CN={0}", hostname);
  23. string issuer = subject;
  24. DateTime notBefore = DateTime.Now.AddDays(-2);
  25. DateTime notAfter = DateTime.Now.AddYears(10);
  26. RSA issuerKey = RSA.Create();
  27. #if NET46
  28. issuerKey.FromXmlString(MonoTestRootAgency);
  29. #else
  30. RSACryptoServiceProviderExtensions.FromXmlString(issuerKey, MonoTestRootAgency);
  31. #endif
  32. RSA subjectKey = RSA.Create();
  33. // serial number MUST be positive
  34. if ((sn[0] & 0x80) == 0x80)
  35. sn[0] -= 0x80;
  36. issuer = subject;
  37. issuerKey = subjectKey;
  38. X509CertificateBuilder cb = new X509CertificateBuilder(3);
  39. cb.SerialNumber = sn;
  40. cb.IssuerName = issuer;
  41. cb.NotBefore = notBefore;
  42. cb.NotAfter = notAfter;
  43. cb.SubjectName = subject;
  44. cb.SubjectPublicKey = subjectKey;
  45. // signature
  46. cb.Hash = "SHA256";
  47. byte[] rawcert = cb.Sign(issuerKey);
  48. PKCS12 p12 = new PKCS12();
  49. ArrayList list = new ArrayList();
  50. // we use a fixed array to avoid endianess issues
  51. // (in case some tools requires the ID to be 1).
  52. list.Add(new byte[4] { 1, 0, 0, 0 });
  53. Hashtable attributes = new Hashtable(1);
  54. attributes.Add(PKCS9.localKeyId, list);
  55. p12.AddCertificate(new X509Certificate(rawcert), attributes);
  56. p12.Password = password;
  57. p12.AddPkcs8ShroudedKeyBag(subjectKey, attributes);
  58. p12.SaveToFile(fileName);
  59. }
  60. }
  61. public static class RSACryptoServiceProviderExtensions
  62. {
  63. public static void FromXmlString(RSA rsa, string xmlString)
  64. {
  65. RSAParameters parameters = new RSAParameters();
  66. XmlDocument xmlDoc = new XmlDocument();
  67. xmlDoc.LoadXml(xmlString);
  68. if (xmlDoc.DocumentElement.Name.Equals("RSAKeyValue"))
  69. {
  70. foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes)
  71. {
  72. switch (node.Name)
  73. {
  74. case "Modulus": parameters.Modulus = Convert.FromBase64String(node.InnerText); break;
  75. case "Exponent": parameters.Exponent = Convert.FromBase64String(node.InnerText); break;
  76. case "P": parameters.P = Convert.FromBase64String(node.InnerText); break;
  77. case "Q": parameters.Q = Convert.FromBase64String(node.InnerText); break;
  78. case "DP": parameters.DP = Convert.FromBase64String(node.InnerText); break;
  79. case "DQ": parameters.DQ = Convert.FromBase64String(node.InnerText); break;
  80. case "InverseQ": parameters.InverseQ = Convert.FromBase64String(node.InnerText); break;
  81. case "D": parameters.D = Convert.FromBase64String(node.InnerText); break;
  82. }
  83. }
  84. }
  85. else
  86. {
  87. throw new Exception("Invalid XML RSA key.");
  88. }
  89. rsa.ImportParameters(parameters);
  90. }
  91. }
  92. }