public bool CertificateSigningRequest(string enrollment_url) {
OpenSSL.X509.X509Request CertificateRequest = null;
string sLocalCertFilename;
sLocalCertFilename = m_ReloadConfig.IMSI == "" ? "VNODE_" + m_ReloadConfig.ListenPort.ToString() : m_ReloadConfig.IMSI;
string cert_file = sLocalCertFilename + ".der";
string privateKey_file = sLocalCertFilename + ".key";
OpenSSL.Crypto.RSA rsa = null;
byte[] byteCSR = null;
byte[] privateKey = null;
if (byteCSR == null || byteCSR.Length == 0) {
try {
if (m_ReloadConfig.Logger != null)
m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_INFO, String.Format("Generate new Certificate Signing Request, please wait.."));
//new openssl certificate request
CertificateRequest = new OpenSSL.X509.X509Request();
/* private certificate configuration */
String CN = "reload:" + ReloadGlobals.IPAddressFromHost(m_ReloadConfig, ReloadGlobals.HostName).ToString() + ":" + m_ReloadConfig.ListenPort;
//String CN = TSystems.RELOAD.Enroll.EnrollmentSettings.Default.CN;
String Country = TSystems.RELOAD.Enroll.EnrollmentSettings.Default.Country;
String Locality = TSystems.RELOAD.Enroll.EnrollmentSettings.Default.Locality;
String State = TSystems.RELOAD.Enroll.EnrollmentSettings.Default.State;
String Organization = TSystems.RELOAD.Enroll.EnrollmentSettings.Default.Organization;
String Unit = TSystems.RELOAD.Enroll.EnrollmentSettings.Default.Unit;
CertificateRequest.Subject = new OpenSSL.X509.X509Name("/CN=" + CN + "/C=" + Country + "/L=" + Locality + "/ST=" + State + "/O=" + Organization + "/OU=" + Unit);
rsa = new OpenSSL.Crypto.RSA();
//TODO: remove 0x10021 ?
//rsa.GenerateKeys(2048, 0x10021, null, null); // why 0x10021?
// use 4th fermat number as public key exponent
rsa.GenerateKeys(2048, 0x10001, null, null);
CertificateRequest.PublicKey = OpenSSL.Crypto.CryptoKey.FromPublicKey(rsa.PublicKeyAsPEM, null);
OpenSSL.Crypto.CryptoKey privatKey = OpenSSL.Crypto.CryptoKey.FromPrivateKey(rsa.PrivateKeyAsPEM, null);
// signes REQ by using SHA1 and the private key
CertificateRequest.Sign(privatKey, OpenSSL.Crypto.MessageDigest.SHA1);
// Log for testing reasons in Wireshark
//File.WriteAllText("C:\\Users\\sleonhardt\\Desktop\\ServerPemKey.key", rsa.PrivateKeyAsPEM);
// PEM to DER workaround
string[] pemString = CertificateRequest.PEM.Split('\n');
string s = "";
for (int i = 1; i < pemString.Length - 2; i++)
s += pemString[i] + "\r\n";
byteCSR = Convert.FromBase64String(s);
pemString = rsa.PrivateKeyAsPEM.Split('\n');
s = "";
for (int i = 1; i < pemString.Length - 2; i++)
s += pemString[i] + "\r\n";
privateKey = Convert.FromBase64String(s);
//save Certificate Signing Request and private Key to disk - unsafe, do not use
//File.WriteAllBytes(cert_file, byteCSR);
//File.WriteAllBytes(privateKey_file, privateKey);
if (m_ReloadConfig.Logger != null)
m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_INFO, String.Format("... ready."));
}
catch (Exception ex) {
if (m_ReloadConfig.Logger != null)
m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR,
String.Format("Generation of CSR failed {0}", ex.ToString()));
}
}
try
{
if (enrollment_url != null)
{
HttpWebRequest httpWebPost;
httpWebPost = (HttpWebRequest)WebRequest.Create(new Uri(enrollment_url));
/* As of RELOAD draft, use POST */
httpWebPost.Method = "POST";
httpWebPost.Accept = "application/pkix-cert";
httpWebPost.ContentType = "application/pkcs10";
#if !WINDOWS_PHONE
// Additional HttpWebRequest parameters are not supported
httpWebPost.Timeout = ReloadGlobals.WEB_REQUEST_TIMEOUT;
//httpWebPost.AllowWriteStreamBuffering = true;
//httpWebPost.SendChunked = true;
httpWebPost.ContentLength = byteCSR.Length;
httpWebPost.ProtocolVersion = HttpVersion.Version10;
#endif
httpWebPost.UserAgent = "T-Systems RELOAD MDI Appl 1.0";
/*
this is a sample post request of Marcs Testformular at
https://reloadnet-reload.implementers.org/enrollment
-----------------------------265001916915724
Content-Disposition: form-data; name="username" Thomas
-----------------------------265001916915724
Content-Disposition: form-data; name="password" **********
-----------------------------265001916915724
Content-Disposition: form-data; name="nodeids" 1
-----------------------------265001916915724
Content-Disposition: form-data; name="csr"; filename="blob"
Content-Type: application/pkcs10
*/
/* private enrollment server configuration */
string username = TSystems.RELOAD.Enroll.EnrollmentSettings.Default.Username;
string password = TSystems.RELOAD.Enroll.EnrollmentSettings.Default.Password;
string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");
httpWebPost.ContentType = "multipart/form-data; boundary=" + boundary;
byte[] boundaryclosebytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
string formdataTemplate = "\r\n--" + boundary +
"\r\nContent-Disposition: form-data; name=\"username\"\r\n\r\n{0}\r\n--" + boundary +
"\r\nContent-Disposition: form-data; name=\"password\"\r\n\r\n{1}\r\n--" + boundary +
"\r\nContent-Disposition: form-data; name=\"nodeids\"\r\n\r\n1";
string formitem = string.Format(formdataTemplate, username, password);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
Stream memStream = new System.IO.MemoryStream();
BinaryWriter writer = new BinaryWriter(memStream);
// send CSR to Enrollment Server
writer.Write(formitembytes);
formitem = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"csr\"; filename=\"blob\"\r\nContent-Type: application/pkcs10\r\n\r\n";
formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
writer.Write(formitembytes);
writer.Write(byteCSR);
writer.Write(boundaryclosebytes);
httpWebPost.ContentLength = memStream.Length;
Stream requestStream = httpWebPost.GetRequestStream();
memStream.Position = 0;
memStream.CopyTo(requestStream);
//using (Stream file = File.OpenWrite("C:\\Windows\\Temp\\test.dat"))
//{
// memStream.Position = 0;
// memStream.CopyTo(file);
//}
writer.Close();
HttpWebResponse httpPostResponse = null;
//Send Web-Request and receive a Web-Response
try
{
httpPostResponse = (HttpWebResponse)httpWebPost.GetResponse();
}
catch (WebException ex)
{
m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "CSR returns:" + ex.Message);
}
if (httpPostResponse != null)
{
// use .net classes for Certificate Response
X509Certificate2 myCert;
byte[] byteCert = ReloadGlobals.ConvertNonSeekableStreamToByteArray(httpPostResponse.GetResponseStream());
myCert = new X509Certificate2(byteCert);
if (privateKey != null)
{
byte[] keyBuffer = Helpers.GetBytesFromPEM(rsa.PrivateKeyAsPEM, PemStringType.RsaPrivateKey);
RSACryptoServiceProvider prov = Crypto.DecodeRsaPrivateKey(keyBuffer);
myCert.PrivateKey = prov;
if (Utils.X509Utils.VerifyCertificate(myCert, m_ReloadConfig.RootCertificate))
m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TOPO, String.Format("Verified certificate!"));
m_ReloadConfig.ReloadLocalNetCertStorage.Add(myCert, true);
// Add client certificate to trusted root certificate store
//X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
//store.Open(OpenFlags.ReadWrite);
//store.Add(myCert);
//store.Close();
m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TOPO, String.Format("Successfully received certificate, Issuer: {0}", myCert.Issuer));
return true;
}
}
}
}
catch (Exception ex)
{
m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("CSR failed {0}", ex.ToString()));
}
return false;
}