Innovenergy_trunk/csharp/app/OpenVpnCertificatesServer/PKI/CertificateAuthority.cs

141 lines
6.3 KiB
C#

using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Operators;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
namespace InnovEnergy.OpenVpnCertificatesServer.PKI;
public static class CertificateAuthority
{
private const Int32 KeySize = 2048;
private const Double DaysPerYear = 365.25;
private static X509Certificate CaCertificate { get; } = Pem.Decode<X509Certificate>(CaCertificatePem);
private static RsaKeyPairGenerator KeyGenerator { get; } = new RsaKeyPairGenerator();
private static SecureRandom Rng { get; } = new SecureRandom();
static CertificateAuthority()
{
var parameters = new KeyGenerationParameters(Rng, KeySize);
KeyGenerator.Init(parameters);
}
public static AsymmetricCipherKeyPair CreateKeyPair()
{
Console.WriteLine("Creating key pair");
return KeyGenerator.GenerateKeyPair();
}
public static X509Certificate CreateCertificate(String subjectName, AsymmetricCipherKeyPair subjKeyPair)
{
Console.WriteLine($"issuing certificate for {subjectName}");
var caKey = Pem.Decode<AsymmetricCipherKeyPair>(CaKeyPem, "max helfried harald ursin");
if (caKey == null)
throw new Exception("Failed to decode the CA key!");
var subjectDn = new X509Name("CN=" + subjectName);
var issuerDn = CaCertificate.IssuerDN;
var notBefore = DateTime.UtcNow;
var notAfter = notBefore.Add(TimeSpan.FromDays(DaysPerYear*100));
var serialNo = BigInteger.ValueOf(Rng.Next());
var cg = new X509V3CertificateGenerator();
cg.SetIssuerDN(issuerDn);
cg.SetSubjectDN(subjectDn);
cg.SetSerialNumber(serialNo);
cg.SetNotAfter(notAfter);
cg.SetNotBefore(notBefore);
cg.SetPublicKey(subjKeyPair.Public);
var algorithm = PkcsObjectIdentifiers.Sha256WithRsaEncryption.ToString();
var sign = new Asn1SignatureFactory(algorithm, caKey.Private);
var subjCert = cg.Generate(sign);
if (!Validate(subjCert, caKey.Public))
throw new Exception("Failed to validate newly created certificate!");
return subjCert;
}
private static Boolean Validate(X509Certificate cert, ICipherParameters pubKey)
{
cert.CheckValidity(DateTime.UtcNow);
var tbsCert = cert.GetTbsCertificate(); // To Be Signed
var sig = cert.GetSignature();
var signer = SignerUtilities.GetSigner(cert.SigAlgName);
signer.Init(forSigning: false,
parameters: pubKey);
signer.BlockUpdate(input: tbsCert,
inOff: 0, // offset
length: tbsCert.Length);
return signer.VerifySignature(sig);
}
private const String CaKeyPem =
@"-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,C0B37765BDFC7D269C7057A3A463AB63
gSajHtV+qhJHBONKDktf3XoGS2Vwp0dHpk9sr1dRIThxLf6D7O1dYcTjIXJ/Iz+M
DkV7vnyigADH//9Hv7BwEyJCnie44ChTVxfIGLIwtxlp2oKBVuNmOJRtl+VFgKeG
zzzPxhMpgZJjpRm/jmdLp2YII374+P0fix+ZCTlzWDE5nbjnuumfK5+f+xtQMC4l
F1QoiZSe6k80Li7e/9Qd+e7i8nMNwCrS7jA6ayGIr7/vLWDjMtEjLF6YGAzGGHzQ
3JHb8rsmUX1I6KApYjlZVYHsdnqtN34TZen9zcWyqijSJS6S+hQLf0i+F8hY0Z/J
Y5fHk6br61n/6ZeEY7ijklVUeesbpc+JbjWAhYsg8wyVFTEQGVlLy7D0okO0x6J7
ej/aYUd9Fo2Jnl1I5BZYLXgg9WDsL4hu8u8EqbM4j4oIFxg6wlClMb4gS4iIl26v
36gisNzUY0xNVffLGKyAHsfi6pU8NSbh4Oil/TJcYR9jYu6GhB9Yvpnunc2/ae0W
1uRz6LP+RV9KWme2Diz3Kw1A049eiRC4qCJCsCGAJZzrKq6Anc7Ia47FDEC9J2yC
+5vaPPv6j+pWJJv3wbopl8AStm0hTjg26HAyju3BYFqawP/XcjmVsO+y675vclaH
g+Anr8gi3K4YNzOOLSOl2Fe/IK1BnMpHvabKy4Jo+NYfEIHUnWW1YBRAL6lWE2j2
wuZ5u+mhBYGkdQvhRCpJbe9GmXORjy5GJF/Pkyh27KHU/BxsnceY5OW12wk7nGBf
HUajeFI5G9DyftJvVJ/WyACe5915JoujVIgSnYM3z/kg3VzOB8OdvUYkNBj+Xj3i
Bwd1k3Due1HSlPnrW4JlCkMGQV2uhoOSZhHgxkUw/JRmBNBll6qyyqdyeRFFFIMD
KaELfoCSpjlh6uA6zgS2MO1KdilINgTevyrSeMMqPY7YlH9YyEknyqSpwXNqyDfb
itHs03n9lrksPgKQGstG9yrbKBan6dDn5rXnbvWrkEIUfrer/1YteCy1IYG49uZZ
/jo82FEO/h7fyApevk/CHWMBt52EgXzAzAqz9okRNp93aGoc6jWFvfdAxp/vxIOp
NGNN3LMvFwROr2y1d7VFKe45skCjFsYSGKqjnMZfUGHyFJSKV7LiOj9N32Mt9pj8
6nN8JFW2NmhOOPJd1CK7r1zXv4UWwnFFNlqzQkLujTNUUmhJhrqPCsbWOcVT9kqp
6GyyE4XO0u02ORpcA9WdniJmua5lTVF25BVZ8lwErJ5hlYaOPYpTbIlJGNZo9e1A
73ZfmANg/5TO4FqI0NJrUJN7ZIwwUPU8qH1wZcsTrnhSqaEKES+xqP6GfORMgIaE
J3aLMd7BRVPWC05/6ki98LJz8+/ZURS9oGVNKwy4S7rCi0me2Vi/shzmEk6cRH4R
uthELMaGMFCUjjKGclIdsT8MfMHPZ3VvzTEZANTMWSljdVat4UUcEj+MAQr5Q9uL
VcaAe/AweVaVI3hmXORzph3Uv4o8Im0eWss+IHUziE1uqwOrLhXIljNUNztrD2hP
kF20s1oGUKZ/V+lC/az7V7aZP8PreYV0P5mvP+v8gNepx62yCPLcyks9+IINz349
-----END RSA PRIVATE KEY-----";
public const String CaCertificatePem =
@"-----BEGIN CERTIFICATE-----
MIIDNDCCAhygAwIBAgIJAOtFlqoxtDSsMA0GCSqGSIb3DQEBCwUAMBUxEzARBgNV
BAMMCjQ4VEwyMDBfY2EwIBcNMTgxMTE5MTUxMjQ5WhgPMjExODExMjAxNTEyNDla
MBUxEzARBgNVBAMMCjQ4VEwyMDBfY2EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQCyPY+iqCVOwIEulgIwKktMA4RpGPwHxDXKBak+M2/uG2skW1DnoaaK
taWxcGBJrxsRJQEoAKkYDZAmleBwRcd7oaVK/NcRtyA83y7GJ4y77HxvVKYxwBMB
37EgkUXnBUcnUedrITVDZ6Fr+JYzRzfTb5M0x06W3RZvkTfyirq27CdnZ9SJXHC1
cgeyqnJzlPqH7etmxdUnqPeuRMa6g1lsGGjz0p03Fqbu5rjkB+TXGSkUqPbAho4b
Qg+7XFR1El5MP0u83rmRyID+6k5yt2KLPlr6VH0xUL/EQzezNmEgwuFv5AWt33HT
/VCpo5TDXkZBvgjxlBvoeoswuKYv9wR7AgMBAAGjgYQwgYEwHQYDVR0OBBYEFKtA
pTzAM02NhCrCtEuuw+x9S08gMEUGA1UdIwQ+MDyAFKtApTzAM02NhCrCtEuuw+x9
S08goRmkFzAVMRMwEQYDVQQDDAo0OFRMMjAwX2NhggkA60WWqjG0NKwwDAYDVR0T
BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAJPK22mlvUA2
yKnNJKC+91AVtclwuVB+862RyGb1d1RwI2+fB7KkqyBUXaIqvDS3c5R/gXksx2Nj
nDZT0wUZpuSK8jCS6vaibQZOeucq1hYdTJUuPW34LWVUQs8LD4kaF9CNbiWMtuUg
UOKul0yD2xVhbR+ZfBqdp836gYQmR44SRNRd7IwZJsuopciQKnoVPZPXk6isyusK
hvx12IpeWtmc0n2ubOhDKhiK8kVU6QKQvCcuhiNqPKc7FvUyHrVBUhUuHluxXy2T
TltkEV+VSpv5sA/c25zp8hGyLtV+LirphEMUZgBG3cE2dX2O0PUFDBTVJUDUTCQw
aO2cAFGrouw=
-----END CERTIFICATE-----";
}