private string ServerCertValidate()
        {
            var errorMessage = String.Empty;

            var store = WorkContext.IsMono
                            ? X509StoreManager.CurrentUser.TrustedRoot
                            : X509StoreManager.LocalMachine.TrustedRoot;

            var storage = StorageFactory.GetStorage("-1", "certs");

            try
            {
                CoreContext.TenantManager.SetCurrentTenant(_currentTenantId);

                // Import the details of the certificate from the server.
                lock (RootSync)
                {
                    var certificate = Cache.Get <Syscert.X509Certificate>("ldapCertificate");
                    if (certificate != null)
                    {
                        var data = certificate.GetRawCertData();
                        var x509 = new X509Certificate(data);
                        // Check for ceritficate in store.
                        if (!store.Certificates.Contains(x509))
                        {
                            if (storage.IsFile("ldap/ldap.cer"))
                            {
                                var storageData = GetCertificateFromStorage(storage);
                                var storageX509 = new X509Certificate(storageData);
                                if (CompareHash(storageX509.Hash, x509.Hash))
                                {
                                    // Add the certificate to the store.
                                    store.Import(storageX509);
                                    store.Certificates.Add(storageX509);
                                    return(String.Empty);
                                }
                            }
                            if (_certificateConfirmRequest.Approved)
                            {
                                AddCertificateToStorage(storage, x509);
                                // Add the certificate to the store.
                                store.Import(x509);
                                store.Certificates.Add(x509);
                                return(String.Empty);
                            }
                            if (!_certificateConfirmRequest.Requested)
                            {
                                _certificateConfirmRequest.SerialNumber = CryptoConvert.ToHex(x509.SerialNumber);
                                _certificateConfirmRequest.IssuerName   = x509.IssuerName;
                                _certificateConfirmRequest.SubjectName  = x509.SubjectName;
                                _certificateConfirmRequest.ValidFrom    = x509.ValidFrom;
                                _certificateConfirmRequest.ValidUntil   = x509.ValidUntil;
                                _certificateConfirmRequest.Hash         = CryptoConvert.ToHex(x509.Hash);
                                var certificateErrors = Cache.Get <int[]>("ldapCertificateErrors");
                                _certificateConfirmRequest.CertificateErrors = certificateErrors.ToArray();
                                _certificateConfirmRequest.Requested         = true;
                            }
                        }
                    }
                    else
                    {
                        // for AD
                        if (storage.IsFile("ldap/ldap.cer"))
                        {
                            var storageData = GetCertificateFromStorage(storage);
                            var storageX509 = new X509Certificate(storageData);
                            // Add the certificate to the store.
                            store.Import(storageX509);
                            store.Certificates.Add(storageX509);
                            return(String.Empty);
                        }

                        errorMessage = "LDAP TlsHandler. Certificate not found in certificate store.";

                        _log.Error(errorMessage);

                        return(errorMessage);
                    }
                }
            }
            catch (Exception ex)
            {
                errorMessage = String.Format("LDAP TlsHandler error: {0}. {1}. store path = {2}",
                                             ex, ex.InnerException != null ? ex.InnerException.ToString() : string.Empty,
                                             store.Name);
                _log.ErrorFormat(errorMessage);
            }

            return(errorMessage);
        }
 public void FromCapiKeyBlob_UnknownBlob()
 {
     byte[] blob = new byte [160];
     RSA    rsa  = CryptoConvert.FromCapiKeyBlob(blob, 12);
 }
Beispiel #3
0
        private void SetKeyPair(AssemblyName aname)
        {
#if ONLY_1_1
            switch (delaysign)
            {
            case DelaySign.Yes:
                AddCattr(typeof(AssemblyDelaySignAttribute),
                         typeof(bool), true);
                break;

            case DelaySign.No:
                AddCattr(typeof(AssemblyDelaySignAttribute),
                         typeof(bool), false);
                break;
            }
#endif

            if (keyfile != null)
            {
                if (!File.Exists(keyfile))
                {
                    Report(1044, String.Format("Couldn't open '{0}' key file.", keyfile));
                }

#if ONLY_1_1
                AddCattr(typeof(AssemblyKeyFileAttribute),
                         keyfile);
#endif

                using (FileStream fs = File.OpenRead(keyfile)) {
                    byte[] data = new byte [fs.Length];
                    try {
                        fs.Read(data, 0, data.Length);

                        if (delaysign == DelaySign.Yes)
                        {
                            SetPublicKey(aname, data);
                        }
                        else
                        {
                            CryptoConvert.FromCapiPrivateKeyBlob(data);
                            aname.KeyPair = new StrongNameKeyPair(data);
                        }
                    }
                    catch (CryptographicException) {
                        if (delaysign != DelaySign.Yes)
                        {
                            if (data.Length == 16)
                            {
                                // error # is different for ECMA key
                                Report(1019, "Could not strongname the assembly. " +
                                       "ECMA key can only be used to delay-sign assemblies");
                            }
                            else
                            {
                                Report(1028, String.Format("Key file {0}' is missing it's private key " +
                                                           "or couldn't be decoded.", keyfile));
                            }
                        }
                        else
                        {
                            Report(1044, String.Format("Couldn't decode '{0}' key file.", keyfile));
                        }
                    }
                    fs.Close();
                }
            }
            else if (keyname != null)
            {
#if ONLY_1_1
                AddCattr(typeof(AssemblyKeyNameAttribute),
                         keyname);
#endif
                // delay-sign doesn't apply to key containers
                aname.KeyPair = new StrongNameKeyPair(keyname);
            }
        }
Beispiel #4
0
 public byte[] GetBytes() =>
 CryptoConvert.ToCapiPrivateKeyBlob(this.RSA);
 public void FromHex_NonHexChars()
 {
     CryptoConvert.FromHex("abcdefgh");
 }
 public void ToHex()
 {
     AssertNull("FromHex(null)", CryptoConvert.FromHex(null));
     byte[] data = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
     AssertEquals("0123456789abcdef", "0123456789ABCDEF", CryptoConvert.ToHex(data));
 }
 public void FromCapiPublicKeyBlob_Invalid()
 {
     RSA rsa = CryptoConvert.FromCapiPublicKeyBlob(strongName, 0);
 }
 public void FromCapiPublicKeyBlobDSA_Invalid()
 {
     byte[] blob = new byte[400];
     DSA    dsa  = CryptoConvert.FromCapiPublicKeyBlobDSA(blob, 0);
 }
 public void FromCapiPublicKeyBlob_Null()
 {
     RSA rsa = CryptoConvert.FromCapiPublicKeyBlob(null);
 }
 public void FromCapiPublicKeyBlob_InvalidOffset()
 {
     RSA rsa = CryptoConvert.FromCapiPublicKeyBlob(new byte [0], 0);
 }
        public void FromCapiPublicKeyBlob()
        {
            RSA rsa = CryptoConvert.FromCapiPublicKeyBlob(strongNamePublicKey, 12);

            AssertEquals("PublicKey", strongNamePublicKeyString, rsa.ToXmlString(false));
        }
 public void FromCapiPrivateKeyBlob_Invalid()
 {
     RSA rsa = CryptoConvert.FromCapiPrivateKeyBlob(strongNamePublicKey, 12);
 }
        public void FromCapiPrivateKeyBlob()
        {
            RSA rsa = CryptoConvert.FromCapiPrivateKeyBlob(strongName, 0);

            AssertEquals("KeyPair", strongNameString, rsa.ToXmlString(true));
        }
 public void FromCapiPublicKeyBlobDSA_Null()
 {
     DSA dsa = CryptoConvert.FromCapiPublicKeyBlobDSA(null);
 }
        public void ToCapiKeyBlob_AsymmetricAlgorithm()
        {
            AsymmetricAlgorithm rsa = RSA.Create();

            rsa.FromXmlString(strongNameString);
            byte[] keypair = CryptoConvert.ToCapiKeyBlob(rsa, true);
            AssertEquals("RSA-KeyPair", strongName, keypair);

            byte[] publicKey = CryptoConvert.ToCapiKeyBlob(rsa, false);
            AssertEquals("RSA-PublicKey", BitConverter.ToString(strongNamePublicKey, 12), BitConverter.ToString(publicKey));

            AsymmetricAlgorithm dsa = DSA.Create();

            dsa.FromXmlString(dsaKeyPairString);
            AssertEquals("DSA-KeyPair", dsaPrivBlob, CryptoConvert.ToCapiKeyBlob(dsa, true));
            AssertEquals("DSA-PublicKey", BitConverter.ToString(dsaPubBlob), BitConverter.ToString(CryptoConvert.ToCapiKeyBlob(dsa, false)));
        }
 public void FromCapiPublicKeyBlobDSA_InvalidOffset()
 {
     DSA dsa = CryptoConvert.FromCapiPublicKeyBlobDSA(new byte[0], 0);
 }
        public void ToCapiKeyBlob_AsymmetricNull()
        {
            AsymmetricAlgorithm aa = null;

            CryptoConvert.ToCapiKeyBlob(aa, false);
        }
        public void ToCapiKeyBlob_DSANull()
        {
            DSA dsa = null;

            CryptoConvert.ToCapiKeyBlob(dsa, false);
        }
        public void ToCapiKeyBlob_RSANull()
        {
            RSA rsa = null;

            CryptoConvert.ToCapiKeyBlob(rsa, false);
        }
 public void FromHex_NonMultipleOf2()
 {
     CryptoConvert.FromHex("abc");
 }
 public void FromCapiKeyBlobDSA_UnknownBlob()
 {
     byte[] blob = new byte [334];
     DSA    dsa  = CryptoConvert.FromCapiKeyBlobDSA(blob, 0);
 }
Beispiel #22
0
        static int Process(string[] args)
        {
            int    i     = 0;
            string param = args [i];
            bool   quiet = ((param == "-quiet") || (param == "-q"));

            if (quiet)
            {
                i++;
            }
            else
            {
                Header();
            }

            LoadConfig(quiet);

            StrongName               sn  = null;
            AssemblyName             an  = null;
            RSACryptoServiceProvider rsa = null;
            CspParameters            csp = new CspParameters();

            csp.ProviderName = defaultCSP;

            switch (args [i++])
            {
            case "-c":
                // Change global CSP provider options
                defaultCSP = args [i];
                return(SaveConfig());

            case "-d":
                // Delete specified key container
                csp.KeyContainerName = args [i];
                rsa = new RSACryptoServiceProvider(csp);
                rsa.PersistKeyInCsp = false;
                if (!quiet)
                {
                    Console.WriteLine("Keypair in container {0} has been deleted", args [i]);
                }
                break;

            case "-D":
                StrongName a1 = new StrongName();
                byte[]     h1 = a1.Hash(args [i++]);
                StrongName a2 = new StrongName();
                byte[]     h2 = a2.Hash(args [i++]);
                if (Compare(h1, h2))
                {
                    Console.WriteLine("Both assembly are identical (same digest for metadata)");
                    // TODO: if equals then compare signatures
                }
                else
                {
                    Console.WriteLine("Assemblies are not identical (different digest for metadata)");
                }
                break;

            case "-e":
                // Export public key from assembly
                an = AssemblyName.GetAssemblyName(args [i++]);
                WriteToFile(args[i], an.GetPublicKey());
                if (!quiet)
                {
                    Console.WriteLine("Public Key extracted to file {0}", args [i]);
                }
                break;

            case "-i":
                // import keypair from SNK to container
                sn = new StrongName(ReadFromFile(args [i++]));
                csp.KeyContainerName = args [i];
                rsa = new RSACryptoServiceProvider(csp);
                rsa.ImportParameters(sn.RSA.ExportParameters(true));
                break;

            case "-k":
                // Create a new strong name key pair
                // (a new RSA keypair automagically if none is present)
                int size = 1024;
                if (i < args.Length + 2)
                {
                    try {
                        size = Int32.Parse(args[i++]);
                    }
                    catch {
                        // oops, that wasn't a valid key size (assume 1024 bits)
                        i--;
                    }
                }
                sn = new StrongName(size);
                WriteToFile(args[i], CryptoConvert.ToCapiKeyBlob(sn.RSA, true));
                if (!quiet)
                {
                    Console.WriteLine("A new {0} bits strong name keypair has been generated in file '{1}'.", size, args [i]);
                }
                break;

            case "-m":
                Console.WriteLine("Unimplemented option");
                break;

            case "-o":
                byte[] infileD = ReadFromFile(args [i++]);
                WriteCSVToFile(args [i], infileD, "D");
                if (!quiet)
                {
                    Console.WriteLine("Output CSV file is {0} (decimal format)", args [i]);
                }
                break;

            case "-oh":
                byte[] infileX2 = ReadFromFile(args [i++]);
                WriteCSVToFile(args [i], infileX2, "X2");
                if (!quiet)
                {
                    Console.WriteLine("Output CVS file is {0} (hexadecimal format)", args [i]);
                }
                break;

            case "-p":
                // Extract public key from SNK or PKCS#12/PFX file
                sn = new StrongName(GetKeyFromFile(args [i++]));
                WriteToFile(args[i], sn.PublicKey);
                if (!quiet)
                {
                    Console.WriteLine("Public Key extracted to file {0}", args [i]);
                }
                break;

            case "-pc":
                // Extract public key from container
                csp.KeyContainerName = args [i++];
                rsa = new RSACryptoServiceProvider(csp);
                sn  = new StrongName(rsa);
                WriteToFile(args[i], sn.PublicKey);
                if (!quiet)
                {
                    Console.WriteLine("Public Key extracted to file {0}", args [i]);
                }
                break;

            case "-R":
                string filename = args [i++];
                if (!ReSign(filename, GetKeyFromFile(args [i]), quiet))
                {
                    return(1);
                }
                break;

            case "-Rc":
                filename             = args [i++];
                csp.KeyContainerName = args [i];
                rsa = new RSACryptoServiceProvider(csp);
                if (!ReSign(filename, rsa, quiet))
                {
                    return(1);
                }
                break;

            case "-t":
                // Show public key token from file
                sn = new StrongName(ReadFromFile(args [i]));
                // note: ignore quiet
                Console.WriteLine("Public Key Token: " + ToString(sn.PublicKeyToken), Environment.NewLine);
                break;

            case "-tp":
                // Show public key and public key token from assembly
                sn = new StrongName(ReadFromFile(args [i]));
                // note: ignore quiet
                Console.WriteLine("Public Key:" + ToString(sn.PublicKey));
                Console.WriteLine("{0}Public Key Token: " + ToString(sn.PublicKeyToken), Environment.NewLine);
                break;

            case "-T":
                // Show public key token from assembly
                an = AssemblyName.GetAssemblyName(args [i++]);
                // note: ignore quiet
                byte [] pkt = an.GetPublicKeyToken();
                if (pkt == null)
                {
                    Console.WriteLine("{0} does not represent a strongly named assembly.", args [i - 1]);
                }
                else
                {
                    Console.WriteLine("Public Key Token: " + ToString(pkt));
                }
                break;

            case "-Tp":
                // Show public key and public key token from assembly
                an = AssemblyName.GetAssemblyName(args [i++]);
                byte [] token = an.GetPublicKeyToken();
                if (token == null)
                {
                    Console.WriteLine("{0} does not represent a strongly named assembly.", args [i - 1]);
                }
                else
                {
                    Console.WriteLine("Public Key:" + ToString(an.GetPublicKey()));
                    Console.WriteLine("{0}Public Key Token: " + ToString(token), Environment.NewLine);
                }
                break;

            case "-v":
                filename = args [i++];
                return(Verify(filename, false, quiet));

            case "-vf":
                filename = args [i++];
                return(Verify(filename, true, quiet));                          // force verification

            case "-Vl":
                Console.WriteLine(new StrongNameManager().ToString());
                break;

            case "-Vr":
                Console.WriteLine("Unimplemented option");
                break;

            case "-Vu":
                Console.WriteLine("Unimplemented option");
                break;

            case "-Vx":
                // we must remove <verificationSettings> from each config files
                Console.WriteLine("Unimplemented option");
                break;

            case "-?":
            case "-h":
                Help((i < args.Length) ? args [i] : null);
                break;

            default:
                if (!quiet)
                {
                    Console.WriteLine("Unknown option {0}", args [i - 1]);
                }
                return(1);
            }
            return(0);
        }
        public void FromCapiPrivateKeyBlobDSA()
        {
            DSA dsa = CryptoConvert.FromCapiPrivateKeyBlobDSA(dsaPrivBlob, 0);

            AssertEquals("KeyPair", dsaKeyPairString, dsa.ToXmlString(true));
        }
Beispiel #24
0
        public void FromXml(SecurityElement element)
        {
#if DISABLE_SECURITY
            throw new PlatformNotSupportedException();
#else
            if (element == null)
            {
                throw new ArgumentNullException("element");
            }

            if (element.Tag != "ApplicationTrust")
            {
                throw new ArgumentException("element");
            }

            string s = element.Attribute("FullName");
            if (s != null)
            {
                _appid = new ApplicationIdentity(s);
            }
            else
            {
                _appid = null;
            }

            _defaultPolicy = null;
            SecurityElement defaultGrant = element.SearchForChildByTag("DefaultGrant");
            if (defaultGrant != null)
            {
                for (int i = 0; i < defaultGrant.Children.Count; i++)
                {
                    SecurityElement se = (defaultGrant.Children [i] as SecurityElement);
                    if (se.Tag == "PolicyStatement")
                    {
                        DefaultGrantSet.FromXml(se, null);
                        break;
                    }
                }
            }

            if (!Boolean.TryParse(element.Attribute("TrustedToRun"), out _trustrun))
            {
                _trustrun = false;
            }

            if (!Boolean.TryParse(element.Attribute("Persist"), out _persist))
            {
                _persist = false;
            }

            _xtranfo = null;
            SecurityElement xtra = element.SearchForChildByTag("ExtraInfo");
            if (xtra != null)
            {
                s = xtra.Attribute("Data");
                if (s != null)
                {
                    byte[] data = CryptoConvert.FromHex(s);
                    using (MemoryStream ms = new MemoryStream(data)) {
                        BinaryFormatter bf = new BinaryFormatter();
                        _xtranfo = bf.Deserialize(ms);
                    }
                }
            }
#endif
        }
 public void FromCapiPrivateKeyBlobDSA_Invalid()
 {
     byte[] blob = new byte[334];
     DSA    dsa  = CryptoConvert.FromCapiPrivateKeyBlobDSA(blob, 0);
 }
        public static bool MySSLHandler(Syscert.X509Certificate certificate,
                                        int[] certificateErrors)
        {
            X509Store  store  = null;
            X509Stores stores = X509StoreManager.CurrentUser;
            String     input;

            store = stores.TrustedRoot;


            //Import the details of the certificate from the server.

            X509Certificate           x509 = null;
            X509CertificateCollection coll = new X509CertificateCollection();

            byte[] data = certificate.GetRawCertData();
            if (data != null)
            {
                x509 = new X509Certificate(data);
            }

            //List the details of the Server

            //check for ceritficate in store
            X509CertificateCollection check = store.Certificates;

            if (!check.Contains(x509))
            {
                if (bindCount == 1)
                {
                    Console.WriteLine(" \n\nCERTIFICATE DETAILS: \n");
                    Console.WriteLine(" {0}X.509 v{1} Certificate", (x509.IsSelfSigned ? "Self-signed " : String.Empty), x509.Version);
                    Console.WriteLine("  Serial Number: {0}", CryptoConvert.ToHex(x509.SerialNumber));
                    Console.WriteLine("  Issuer Name:   {0}", x509.IssuerName);
                    Console.WriteLine("  Subject Name:  {0}", x509.SubjectName);
                    Console.WriteLine("  Valid From:    {0}", x509.ValidFrom);
                    Console.WriteLine("  Valid Until:   {0}", x509.ValidUntil);
                    Console.WriteLine("  Unique Hash:   {0}", CryptoConvert.ToHex(x509.Hash));
                    Console.WriteLine();
                }

                //Get the response from the Client
                do
                {
                    Console.WriteLine("\nDo you want to proceed with the connection (y/n)?");
                    input = Console.ReadLine();
                    if (input == "y" || input == "Y")
                    {
                        bHowToProceed = true;
                    }
                    if (input == "n" || input == "N")
                    {
                        bHowToProceed = false;
                    }
                }while(input != "y" && input != "Y" && input != "n" && input != "N");
            }
            else
            {
                if (bHowToProceed == true)
                {
                    //Add the certificate to the store.

                    if (x509 != null)
                    {
                        coll.Add(x509);
                    }
                    store.Import(x509);
                    if (bindCount == 1)
                    {
                        removeFlag = true;
                    }
                }
            }
            if (bHowToProceed == false)
            {
                //Remove the certificate added from the store.

                if (removeFlag == true && bindCount > 1)
                {
                    foreach (X509Certificate xt509 in store.Certificates)
                    {
                        if (CryptoConvert.ToHex(xt509.Hash) == CryptoConvert.ToHex(x509.Hash))
                        {
                            store.Remove(x509);
                        }
                    }
                }
                Console.WriteLine("SSL Bind Failed.");
            }
            return(bHowToProceed);
        }
        public void FromCapiPublicKeyBlobDSA()
        {
            DSA dsa = CryptoConvert.FromCapiPublicKeyBlobDSA(dsaPubBlob, 0);

            AssertEquals("PublicKey", dsaPubKeyString, dsa.ToXmlString(false));
        }
Beispiel #28
0
        public void Save(string filename, string password)
        {
            if (filename == null)
            {
                throw new ArgumentNullException("filename");
            }
            byte[]     array      = null;
            FileStream fileStream = File.Open(filename, FileMode.Create, FileAccess.Write);

            try
            {
                byte[] array2 = new byte[4];
                byte[] bytes  = BitConverterLE.GetBytes(2964713758u);
                fileStream.Write(bytes, 0, 4);
                fileStream.Write(array2, 0, 4);
                bytes = BitConverterLE.GetBytes(this.keyType);
                fileStream.Write(bytes, 0, 4);
                this.encrypted = (password != null);
                array          = CryptoConvert.ToCapiPrivateKeyBlob(this.rsa);
                if (this.encrypted)
                {
                    bytes = BitConverterLE.GetBytes(1);
                    fileStream.Write(bytes, 0, 4);
                    bytes = BitConverterLE.GetBytes(16);
                    fileStream.Write(bytes, 0, 4);
                    bytes = BitConverterLE.GetBytes(array.Length);
                    fileStream.Write(bytes, 0, 4);
                    byte[] array3 = new byte[16];
                    RC4    rc     = RC4.Create();
                    byte[] array4 = null;
                    try
                    {
                        RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create();
                        randomNumberGenerator.GetBytes(array3);
                        fileStream.Write(array3, 0, array3.Length);
                        array4 = this.DeriveKey(array3, password);
                        if (this.Weak)
                        {
                            Array.Clear(array4, 5, 11);
                        }
                        ICryptoTransform cryptoTransform = rc.CreateEncryptor(array4, null);
                        cryptoTransform.TransformBlock(array, 8, array.Length - 8, array, 8);
                    }
                    finally
                    {
                        Array.Clear(array3, 0, array3.Length);
                        Array.Clear(array4, 0, array4.Length);
                        rc.Clear();
                    }
                }
                else
                {
                    fileStream.Write(array2, 0, 4);
                    fileStream.Write(array2, 0, 4);
                    bytes = BitConverterLE.GetBytes(array.Length);
                    fileStream.Write(bytes, 0, 4);
                }
                fileStream.Write(array, 0, array.Length);
            }
            finally
            {
                Array.Clear(array, 0, array.Length);
                fileStream.Close();
            }
        }
Beispiel #29
0
        public void Save(string filename, string password)
        {
            if (filename == null)
            {
                throw new ArgumentNullException("filename");
            }

            byte[]     blob = null;
            FileStream fs   = File.Open(filename, FileMode.Create, FileAccess.Write);

            try {
                // header
                byte[] empty = new byte [4];
                byte[] data  = BitConverterLE.GetBytes(magic);
                fs.Write(data, 0, 4);                   // magic
                fs.Write(empty, 0, 4);                  // reserved
                data = BitConverterLE.GetBytes(keyType);
                fs.Write(data, 0, 4);                   // key type

                encrypted = (password != null);
                blob      = CryptoConvert.ToCapiPrivateKeyBlob(rsa);
                if (encrypted)
                {
                    data = BitConverterLE.GetBytes(1);
                    fs.Write(data, 0, 4);                       // encrypted
                    data = BitConverterLE.GetBytes(16);
                    fs.Write(data, 0, 4);                       // saltlen
                    data = BitConverterLE.GetBytes(blob.Length);
                    fs.Write(data, 0, 4);                       // keylen

                    byte[] salt = new byte [16];
                    RC4    rc4  = RC4.Create();
                    byte[] key  = null;
                    try {
                        // generate new salt (16 bytes)
                        RandomNumberGenerator rng = RandomNumberGenerator.Create();
                        rng.GetBytes(salt);
                        fs.Write(salt, 0, salt.Length);
                        key = DeriveKey(salt, password);
                        if (Weak)
                        {
                            Array.Clear(key, 5, 11);
                        }
                        ICryptoTransform enc = rc4.CreateEncryptor(key, null);
                        // we don't encrypt the header part of the BLOB
                        enc.TransformBlock(blob, 8, blob.Length - 8, blob, 8);
                    }
                    finally {
                        Array.Clear(salt, 0, salt.Length);
                        Array.Clear(key, 0, key.Length);
                        rc4.Clear();
                    }
                }
                else
                {
                    fs.Write(empty, 0, 4);                      // encrypted
                    fs.Write(empty, 0, 4);                      // saltlen
                    data = BitConverterLE.GetBytes(blob.Length);
                    fs.Write(data, 0, 4);                       // keylen
                }

                fs.Write(blob, 0, blob.Length);
            }
            finally {
                // BLOB may include an uncrypted keypair
                Array.Clear(blob, 0, blob.Length);
                fs.Close();
            }
        }