Domanda

Sto creando un sistema di distribuzione certificato per tenere traccia dei clienti e roba del genere.

Quello che succede è:

  • Il cliente trasmette CSR al server
  • Il server controlla e segni certificato
  • server invia il certificato al client Signed
  • Client mette certificato firmato più della chiave privata nel negozio di Windows.

Quindi, sul client questo accade:

//Pseudo Server Object:
Server s = new Server();  

//Requested Certificate Name and things
X509Name name = new X509Name("CN=Client Cert, C=NL");  

//Key generation 2048bits
RsaKeyPairGenerator rkpg = new RsaKeyPairGenerator();
rkpg.Init(new KeyGenerationParameters(new SecureRandom(), 2048));
AsymmetricCipherKeyPair ackp = rkpg.GenerateKeyPair();  

//PKCS #10 Certificate Signing Request
Pkcs10CertificationRequest csr = new Pkcs10CertificationRequest("SHA1WITHRSA", name, ackp.Public, null, ackp.Private);  

//Make it a nice PEM thingie
StringBuilder sb = new StringBuilder();
PemWriter pemwrit = new PemWriter(new StringWriter(b));
pemwrit.WriteObject(csr);
pemwrit.Writer.Flush();
s.SendRequest(sb.ToSting());

Ok, quindi salterò serverside Fidati di me il server firma il CERT e inviarlo al client. Thats dove Prenderò l'azione.

PemReader pr = new PemReader(new StringReader(b.ToString()));
X509Certificate cert = (X509Certificate)pr.ReadObject();  

//So lets asume I saved the AsymmetricCipherKeyPair (ackp) from before
//I have now the certificate and my private key;

//first I make it a "Microsoft" x509cert.
//This however does not have a PrivateKey thats in the AsymmetricCipherKeyPair (ackp)
System.Security.Cryptography.X509Certificates.X509Certificate2 netcert = DotNetUtilities.ToX509Certificate(cert);

//So here comes the RSACryptoServerProvider:
System.Security.Cryptography.RSACryptoServiceProvider rcsp = new System.Security.Cryptography.RSACryptoServiceProvider();  

//And the privateKeyParameters
System.Security.Cryptography.RSAParameters parms = new System.Security.Cryptography.RSAParameters();  

//now I have to translate ackp.PrivateKey to parms;
RsaPrivateCrtKeyParameters BCKeyParms = ((RsaPrivateCrtKeyParameters)ackp1.Private);  

//D is the private exponent
parms.Modulus   = BCKeyParms.Modulus.ToByteArray();
parms.P         = BCKeyParms.P.ToByteArray();
parms.Q         = BCKeyParms.Q.ToByteArray();
parms.DP        = BCKeyParms.DP.ToByteArray();
parms.DQ        = BCKeyParms.DQ.ToByteArray();
parms.InverseQ  = BCKeyParms.QInv.ToByteArray();
parms.D         = BCKeyParms.Exponent.ToByteArray();
parms.Exponent  = BCKeyParms.PublicExponent.ToByteArray();  

//Now I should be able to import the RSAParameters into the RSACryptoServiceProvider
rcsp.ImportParameters(parms);  

//<em><b>not really</b></em> This breaks says "Bad Data" and not much more. I'll Post the 
//stacktrace at the end  

//I open up the windows cert store because thats where I want to save it.
//Add it and save it this works fine without the privkey.
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.MaxAllowed);
store.Add(netcert);
store.Close();

Ora probabilmente stai pensando ci deve essere qualcosa che non va al lato server. questo è quello Beh quello che ho pensato troppo, ma quando ho fatto un file PFX da questo cert e importati a mano ha funzionato bene ....

In qualche modo c'è una diference bewteen una PrivateKey .NET RSA e un PrivateKey BouncyCastle RSA e non riesco a mettere il dito su di esso.

Sarà probabilmente suggerire di importare il pfx e quindi ottenere la chiave privata da esso attraverso il X509Store. Provai. : S e non è riuscito. Non appena cerco di ExportParameters(true) i veri stand per l'inclusione privateparameters. Si dice "Chiave non valido per l'utilizzo nello stato specificato.". Si veda ad eccezione completo alla fine.

Spero che alcuni di voi hanno ucciso questo maiale prima o potrebbe essere in grado di aiutarmi.

***Exceptions:***

System.Security.Cryptography.CryptographicException was unhandled
  Message="Key not valid for use in specified state.\r\n"
  Source="mscorlib"
  StackTrace:
       at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
       at System.Security.Cryptography.Utils._ExportKey(SafeKeyHandle hKey, Int32 blobType, Object cspObject)
       at System.Security.Cryptography.RSACryptoServiceProvider.ExportParameters(Boolean includePrivateParameters)
  InnerException: 

***And the other one:***

System.Security.Cryptography.CryptographicException was unhandled
  Message="Bad Data.\r\n"
  Source="mscorlib"
  StackTrace:
       at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
       at System.Security.Cryptography.Utils._ImportKey(SafeProvHandle hCSP, Int32 keyNumber, CspProviderFlags flags, Object cspObject, SafeKeyHandle& hKey)
       at System.Security.Cryptography.RSACryptoServiceProvider.ImportParameters(RSAParameters parameters)
  InnerException: 
È stato utile?

Soluzione

La risposta (da nome utente) indica la giusta direzione:. padding

ultima versione di Bouncy-castello da Git ha il seguente codice:

public static RSAParameters ToRSAParameters(RsaPrivateCrtKeyParameters privKey)
{
   RSAParameters rp = new RSAParameters();
   rp.Modulus = privKey.Modulus.ToByteArrayUnsigned();
   rp.Exponent = privKey.PublicExponent.ToByteArrayUnsigned();
   rp.P = privKey.P.ToByteArrayUnsigned();
   rp.Q = privKey.Q.ToByteArrayUnsigned();
   rp.D = ConvertRSAParametersField(privKey.Exponent, rp.Modulus.Length);
   rp.DP = ConvertRSAParametersField(privKey.DP, rp.P.Length);
   rp.DQ = ConvertRSAParametersField(privKey.DQ, rp.Q.Length);
   rp.InverseQ = ConvertRSAParametersField(privKey.QInv, rp.Q.Length);
   return rp;
}

private static byte[] ConvertRSAParametersField(BigInteger n, int size)
{
   byte[] bs = n.ToByteArrayUnsigned();
   if (bs.Length == size)
      return bs;
   if (bs.Length > size)
      throw new ArgumentException("Specified size too small", "size");
   byte[] padded = new byte[size];
   Array.Copy(bs, 0, padded, size - bs.Length, bs.Length);
   return padded;
}

. NB: Questo codice a non nella versione NuGet (2011) di castello gonfiabile, o nella maggior parte esempi di codice sono stati i parametri di RSA sono semplicemente copiati

Questo codice è diverso dal codice che si può vedere in qualsiasi altro luogo che in pratica copia / incolla i parametri chiave, e non esegue il passo chilo in più.

Altri suggerimenti

Cordiali saluti, ho aggiunto questa funzionalità alla classe Org.BouncyCastle.Security.DotNetUtilities; sarà in versione 1.6, a causa presto.

L'ho trovato!

o almeno parte di esso:)

Per quanto riguarda il PrivateKey.ExportToParameters(true) Ancora doens't lavoro, ma questo ha qualcosa todo con il fatto che la chiave era a 2048 bit. Perché quando ho cambiato in 1024bit ha funzionato. Quindi, se qualcuno mai scopre perché tenermi postato.

Quindi qui si va di nuovo.

//BouncyCastle's Key objects
RsaPrivateCrtKeyParameters rpckp = ((RsaPrivateCrtKeyParameters)ackp.Private);

//.NET RSA Key objects
System.Security.Cryptography.RSACryptoServiceProvider rcsp = new System.Security.Cryptography.RSACryptoServiceProvider();
System.Security.Cryptography.RSAParameters parms = new System.Security.Cryptography.RSAParameters();

//So the thing changed is offcourse the ToByteArrayUnsigned() instead of
//ToByteArray()
parms.Modulus   = rpckp.Modulus.ToByteArrayUnsigned();
parms.P         = rpckp.P.ToByteArrayUnsigned();
parms.Q         = rpckp.Q.ToByteArrayUnsigned();
parms.DP        = rpckp.DP.ToByteArrayUnsigned();
parms.DQ        = rpckp.DQ.ToByteArrayUnsigned();
parms.InverseQ  = rpckp.QInv.ToByteArrayUnsigned();
parms.D         = rpckp.Exponent.ToByteArrayUnsigned();
parms.Exponent  = rpckp.PublicExponent.ToByteArrayUnsigned();

//So now this now appears to work.
rcsp.ImportParameters(parms);

Così ora posso aggiungere il certificato completo al mio deposito :)

Credo di avere trovato la soluzione a questo problema. Non ha nulla a che fare con la per tasto, ma piuttosto con l'oggetto X509Certificate2 che deve essere creato con la bandiera X509KeyStorageFlags.Exportable.

In questo caso il vostro X509Certificate2 è stato creato con questo metodo: System.Security.Cryptography.X509Certificates.X509Certificate2 netcert = DotNetUtilities.ToX509Certificate(cert);

Quindi assicuratevi di passare il flag esportabile nel costruttore della X509Certificate2 in quel metodo. Ho la mia situazione avevo bisogno di firmare alcuni dati con una chiave privata che si trova in un file PFX così ho dovuto scrivere questo:

X509KeyStorageFlags flags = X509KeyStorageFlags.Exportable;
X509Certificate2 cert = new X509Certificate2("my.pfx", "somepass", flags);

Ora posso fare
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)cert.PrivateKey;
RSAParameters rsaParam = rsa.ExportParameters(true);

HTH,

Stefan

Nessuna delle soluzioni lavorato per me. Ma ho notato che l'eccezione viene sempre generata quando una delle seguenti matrici:

parms.Modulus   = rpckp.Modulus.ToByteArrayUnsigned();
parms.P         = rpckp.P.ToByteArrayUnsigned();
parms.Q         = rpckp.Q.ToByteArrayUnsigned();
parms.DP        = rpckp.DP.ToByteArrayUnsigned();
parms.DQ        = rpckp.DQ.ToByteArrayUnsigned();
parms.InverseQ  = rpckp.QInv.ToByteArrayUnsigned();
parms.D         = rpckp.Exponent.ToByteArrayUnsigned();
parms.Exponent  = rpckp.PublicExponent.ToByteArrayUnsigned();

ha una dimensione diversa, allora il suo vicino:

DP, DQ, InverseQ, P, Q

o di dimensioni doppie:

D, Modulus

Per ciascuno di questi due gruppi che ho calcolato la lunghezza massima e aggiunti zeri in più all'inizio di ciascun array per fare loro la stessa lunghezza (lo stesso per ogni gruppo). Questo funziona, suppongo che i controlli ImportParameters che sono della stessa lunghezza (purtroppo non ho un accesso al codice ImportParameters, sembra che chiama alcuni libreria nativa).

sto usando BouncyCastle.Crypto.dll ver 1.7

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top