// RSACryptoServiceProvider.cs: Handles an RSA implementation.
//
// Authors:
-// Sebastien Pouliot (spouliot@motus.com)
+// Sebastien Pouliot <sebastien@ximian.com>
// Ben Maurer (bmaurer@users.sf.net)
//
// (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
// Portions (C) 2003 Ben Maurer
+// (C) 2004 Novell (http://www.novell.com)
//
using System;
public sealed class RSACryptoServiceProvider : RSA {
- private CspParameters cspParams;
+ private const int PROV_RSA_FULL = 1; // from WinCrypt.h
+
+ private KeyPairPersistence store;
+ private bool persistKey;
+ private bool persisted;
private bool privateKeyExportable = true;
- private bool persistKey = false;
- private bool m_disposed = false;
+ private bool m_disposed;
private RSAManaged rsa;
Common (1024, null);
}
- [MonoTODO("Missing keypair persistance using CspParameters")]
public RSACryptoServiceProvider (CspParameters parameters)
{
Common (1024, parameters);
// no keypair generation done at this stage
}
- // FIXME: We currently dont link with MS CAPI. Anyway this makes
- // only sense in Windows - what do we do elsewhere ?
- [MonoTODO("Missing keypair persistance using CspParameters")]
public RSACryptoServiceProvider (int dwKeySize, CspParameters parameters)
{
Common (dwKeySize, parameters);
// no keypair generation done at this stage
}
- // FIXME: We currently dont link with MS CAPI. Anyway this makes
- // only sense in Windows - what do we do elsewhere ?
private void Common (int dwKeySize, CspParameters p)
{
- if (p == null) {
- cspParams = new CspParameters ();
-#if ! NET_1_0
- if (useMachineKeyStore)
- cspParams.Flags |= CspProviderFlags.UseMachineKeyStore;
-#endif
- // TODO: set default values (for keypair persistance)
- }
- else
- cspParams = p;
- // FIXME: We'll need this to support some kind of persistance
-
// Microsoft RSA CSP can do between 384 and 16384 bits keypair
LegalKeySizesValue = new KeySizes [1];
LegalKeySizesValue [0] = new KeySizes (384, 16384, 8);
base.KeySize = dwKeySize;
rsa = new RSAManaged (KeySize);
+ rsa.KeyGenerated += new RSAManaged.KeyGeneratedEventHandler (OnKeyGenerated);
+
+ persistKey = (p != null);
+ if (p == null) {
+ p = new CspParameters (PROV_RSA_FULL);
+#if ! NET_1_0
+ if (useMachineKeyStore)
+ p.Flags |= CspProviderFlags.UseMachineKeyStore;
+#endif
+ store = new KeyPairPersistence (p);
+ // no need to load - it cannot exists
+ }
+ else {
+ store = new KeyPairPersistence (p);
+ store.Load ();
+ if (store.KeyValue != null) {
+ persisted = true;
+ this.FromXmlString (store.KeyValue);
+ }
+ }
}
#if ! NET_1_0
private static bool useMachineKeyStore = false;
- [MonoTODO("Related to keypair persistance")]
public static bool UseMachineKeyStore {
get { return useMachineKeyStore; }
set { useMachineKeyStore = value; }
return rsa.KeySize;
}
}
-
- [MonoTODO("Related to keypair persistance")]
+
public bool PersistKeyInCsp {
- get { return persistKey; }
- set { persistKey = value; }
+ get { return persistKey; }
+ set {
+ persistKey = value;
+ if (persistKey)
+ OnKeyGenerated (rsa);
+ }
+ }
+
+#if (NET_1_0 || NET_1_1)
+ internal
+#else
+ public
+#endif
+ bool PublicOnly {
+ get { return rsa.PublicOnly; }
}
public override string SignatureAlgorithm {
public byte[] Decrypt (byte[] rgb, bool fOAEP)
{
+#if NET_1_1
+ if (m_disposed)
+ throw new ObjectDisposedException ("rsa");
+#endif
// choose between OAEP or PKCS#1 v.1.5 padding
AsymmetricKeyExchangeDeformatter def = null;
if (fOAEP)
// HashAlgorithm descendant
public byte[] SignData (byte[] buffer, object halg)
{
+#if NET_1_1
+ if (buffer == null)
+ throw new ArgumentNullException ("buffer");
+#endif
return SignData (buffer, 0, buffer.Length, halg);
}
// HashAlgorithm descendant
public bool VerifyData (byte[] buffer, object halg, byte[] signature)
{
+#if NET_1_1
+ if (buffer == null)
+ throw new ArgumentNullException ("buffer");
+#endif
if (signature == null)
throw new ArgumentNullException ("signature");
// LAMESPEC: str is not the hash name but an OID
// NOTE: this method is LIMITED to SHA1 and MD5 like the MS framework 1.0
- // and 1.1 because there's no mathod to get a hash algorithm from an OID.
+ // and 1.1 because there's no method to get a hash algorithm from an OID.
// However there's no such limit when using the [De]Formatter class.
public bool VerifyHash (byte[] rgbHash, string str, byte[] rgbSignature)
{
protected override void Dispose (bool disposing)
{
- if (rsa != null)
- rsa.Clear ();
- // call base class
- // no need as they all are abstract before us
- m_disposed = true;
+ if (!m_disposed) {
+ // the key is persisted and we do not want it persisted
+ if ((persisted) && (!persistKey)) {
+ store.Remove (); // delete the container
+ }
+ if (rsa != null)
+ rsa.Clear ();
+ // call base class
+ // no need as they all are abstract before us
+ m_disposed = true;
+ }
+ }
+
+ // private stuff
+
+ private void OnKeyGenerated (object sender)
+ {
+ // the key isn't persisted and we want it persisted
+ if ((persistKey) && (!persisted)) {
+ // save the current keypair
+ store.KeyValue = this.ToXmlString (!rsa.PublicOnly);
+ store.Save ();
+ persisted = true;
+ }
}
}
}