Пример #1
0
        //public string PublicKeyBeforeSha256 { get; set; }
        //private string _privateKey;


        //public AsymmetricCipherKeyPair GenerateKeyPair()
        //{
        //    ECKeyPairGenerator keyPair = new ECKeyPairGenerator("EC");
        //    keyPair.Init(new KeyGenerationParameters(new SecureRandom(), 384));
        //    var pair = keyPair.GenerateKeyPair();

        //    //PublicKeyBeforeSha256 = GetPublicKeyStringRepresentation(pair.Public);
        //    //_privateKey = GetPrivateKeyStringRepresentation(pair.Private);

        //    return pair;
        //}


        /**
         * Generate a random private key that can be used with Secp256k1.
         */
        public static byte[] GeneratePrivateKey()
        {
            SecureRandom secureRandom = null;

            try
            {
                secureRandom =
                    SecureRandom.GetInstance(RANDOM_NUMBER_ALGORITHM, RANDOM_NUMBER_ALGORITHM_PROVIDER);
            }
            catch (Exception e)
            {
                Console.WriteLine("err");
            }

            BigInteger privateKeyCheck = BigInteger.Zero;
            // Bit of magic, move this maybe. This is the max key range.
            BigInteger maxKey =
                new BigInteger("00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140", 16);

            // Generate the key, skipping as many as desired.
            byte[] privateKeyAttempt = new byte[32];
            secureRandom?.NextBytes(privateKeyAttempt);
            privateKeyCheck = new BigInteger(1, privateKeyAttempt);
            while (privateKeyCheck.CompareTo(BigInteger.Zero) == 0 ||
                   privateKeyCheck.CompareTo(maxKey) == 1)
            {
                secureRandom?.NextBytes(privateKeyAttempt);
                privateKeyCheck = new BigInteger(1, privateKeyAttempt);
            }

            return(privateKeyAttempt);
        }
Пример #2
0
		private void doTestCreateKeyParameter(
			string				algorithm,
			DerObjectIdentifier	oid,
			int					keyBits,
			Type				expectedType,
			SecureRandom		random)
		{
			int keyLength = keyBits / 8;
			byte[] bytes = new byte[keyLength];
			random.NextBytes(bytes);

			KeyParameter key;

			key = ParameterUtilities.CreateKeyParameter(algorithm, bytes);
			checkKeyParameter(key, expectedType, bytes);

			key = ParameterUtilities.CreateKeyParameter(oid, bytes);
			checkKeyParameter(key, expectedType, bytes);

			bytes = new byte[keyLength * 2];
			random.NextBytes(bytes);

			int offset = random.Next(1, keyLength);
			byte[] expected = new byte[keyLength];
			Array.Copy(bytes, offset, expected, 0, keyLength);

			key = ParameterUtilities.CreateKeyParameter(algorithm, bytes, offset, keyLength);
			checkKeyParameter(key, expectedType, expected);

			key = ParameterUtilities.CreateKeyParameter(oid, bytes, offset, keyLength);
			checkKeyParameter(key, expectedType, expected);
		}
Пример #3
0
        public void TestSha1PrngBackward()
        {
            byte[] seed = Encoding.ASCII.GetBytes("backward compatible");

            SecureRandom sx = new SecureRandom(seed);
            SecureRandom sy = SecureRandom.GetInstance("SHA1PRNG", false); sy.SetSeed(seed);

            byte[] bx = new byte[128]; sx.NextBytes(bx);
            byte[] by = new byte[128]; sy.NextBytes(by);

            Assert.IsTrue(Arrays.AreEqual(bx, by));
        }
Пример #4
0
        private void randomTest(
            SecureRandom srng,
            IGcmMultiplier m)
        {
            int kLength = 16 + 8 * srng.Next(3);

            byte[] K = new byte[kLength];
            srng.NextBytes(K);

            int pLength = srng.Next(1024);

            byte[] P = new byte[pLength];
            srng.NextBytes(P);

            int aLength = srng.Next(1024);

            byte[] A = new byte[aLength];
            srng.NextBytes(A);

            int ivLength = 1 + srng.Next(1024);

            byte[] IV = new byte[ivLength];
            srng.NextBytes(IV);

            GcmBlockCipher cipher     = new GcmBlockCipher(new AesFastEngine(), m);
            AeadParameters parameters = new AeadParameters(new KeyParameter(K), 16 * 8, IV, A);

            cipher.Init(true, parameters);
            byte[] C   = new byte[cipher.GetOutputSize(P.Length)];
            int    len = cipher.ProcessBytes(P, 0, P.Length, C, 0);

            len += cipher.DoFinal(C, len);

            if (C.Length != len)
            {
//				Console.WriteLine("" + C.Length + "/" + len);
                Fail("encryption reported incorrect length in randomised test");
            }

            byte[] encT = cipher.GetMac();
            byte[] tail = new byte[C.Length - P.Length];
            Array.Copy(C, P.Length, tail, 0, tail.Length);

            if (!AreEqual(encT, tail))
            {
                Fail("stream contained wrong mac in randomised test");
            }

            cipher.Init(false, parameters);
            byte[] decP = new byte[cipher.GetOutputSize(C.Length)];
            len  = cipher.ProcessBytes(C, 0, C.Length, decP, 0);
            len += cipher.DoFinal(decP, len);

            if (!AreEqual(P, decP))
            {
                Fail("incorrect decrypt in randomised test");
            }

            byte[] decT = cipher.GetMac();
            if (!AreEqual(encT, decT))
            {
                Fail("decryption produced different mac from encryption");
            }
        }
        private static double measureChiSquared(
            SecureRandom random,
            int rounds)
        {
            int[] counts = new int[256];

            byte[] bs = new byte[256];
            for (int i = 0; i < rounds; ++i)
            {
                random.NextBytes(bs);

                for (int b = 0; b < 256; ++b)
                {
                    ++counts[bs[b]];
                }
            }

            byte mask = SecureRandom.GetSeed(1)[0];

            for (int i = 0; i < rounds; ++i)
            {
                random.NextBytes(bs);

                for (int b = 0; b < 256; ++b)
                {
                    ++counts[bs[b] ^ mask];
                }

                ++mask;
            }

            byte shift = SecureRandom.GetSeed(1)[0];

            for (int i = 0; i < rounds; ++i)
            {
                random.NextBytes(bs);

                for (int b = 0; b < 256; ++b)
                {
                    ++counts[(byte)(bs[b] + shift)];
                }

                ++shift;
            }

            int total = 3 * rounds;

            double chi2 = 0;

            for (int k = 0; k < counts.Length; ++k)
            {
                double diff  = ((double)counts[k]) - total;
                double diff2 = diff * diff;

                chi2 += diff2;
            }

            chi2 /= total;

            return(chi2);
        }
Пример #6
0
 public static void GeneratePrivateKey(SecureRandom random, byte[] k)
 {
     random.NextBytes(k);
 }
Пример #7
0
        public void GenerateBitsAfterDisposing()
        {
            SecureRandom random = null;

            using (random = new SecureRandom())
            {
            }

            random.NextBytes(new byte[10]);
        }
Пример #8
0
        /// <summary>
        /// Generate a set of M-of-N parts for a specific private key.
        /// If desiredPrivKey is null, then a random key will be selected.
        /// </summary>
        public void Generate(int PartsNeededToDecode, int PartsToGenerate, byte[] desiredPrivKey)
        {
            if (PartsNeededToDecode > PartsToGenerate)
            {
                throw new ApplicationException("Number of parts needed exceeds number of parts to generate.");
            }

            if (PartsNeededToDecode > 8 || PartsToGenerate > 8)
            {
                throw new ApplicationException("Maximum number of parts is 8");
            }

            if (PartsNeededToDecode < 1 || PartsToGenerate < 1)
            {
                throw new ApplicationException("Minimum number of parts is 1");
            }

            if (desiredPrivKey != null && desiredPrivKey.Length != 32)
            {
                throw new ApplicationException("Desired private key must be 32 bytes");
            }

            KeyParts.Clear();
            decodedKeyParts.Clear();

            SecureRandom sr = new SecureRandom();

            // Get 8 random big integers into v[i].
            byte[][]     vvv = new byte[8][];
            BigInteger[] v   = new BigInteger[8];

            for (int i = 0; i < 8; i++)
            {
                byte[] b = new byte[32];
                sr.NextBytes(b, 0, 32);
                // For larger values of i, chop off some most-significant-bits to prevent overflows as they are
                // multiplied with increasingly larger factors.
                if (i >= 7)
                {
                    b[0] &= 0x7f;
                }
                v[i] = new BigInteger(1, b);
                Debug.WriteLine(String.Format("v({0})={1}", i, v[i].ToString()));
            }

            // if a certain private key is desired, then specify it.
            if (desiredPrivKey != null)
            {
                // replace v[0] with xor(v[1...7]) xor desiredPrivKey
                BigInteger newv0 = BigInteger.Zero;
                for (int i = 1; i < PartsNeededToDecode; i++)
                {
                    newv0 = newv0.Xor(v[i]);
                }
                v[0] = newv0.Xor(new BigInteger(1, desiredPrivKey));
            }


            // Generate the expected private key from all the parts
            BigInteger privkey = new BigInteger("0");

            for (int i = 0; i < PartsNeededToDecode; i++)
            {
                privkey = privkey.Xor(v[i]);
            }

            // Get the bitcoin address
            byte[] keybytes = privkey.ToByteArrayUnsigned();
            // make sure we have 32 bytes, we'll need it
            if (keybytes.Length < 32)
            {
                byte[] array32 = new byte[32];
                Array.Copy(keybytes, 0, array32, 32 - keybytes.Length, keybytes.Length);
                keybytes = array32;
            }
            KeyPair = new KeyPair(keybytes);

            byte[] checksum = Util.ComputeSha256(BitcoinAddress);



            // Generate the parts
            for (int i = 0; i < PartsToGenerate; i++)
            {
                BigInteger total = new BigInteger("0");
                for (int j = 0; j < PartsNeededToDecode; j++)
                {
                    int factor = 1;
                    for (int ii = 0; ii <= i; ii++)
                    {
                        factor = factor * (j + 1);
                    }

                    BigInteger bfactor = new BigInteger(factor.ToString());

                    total = total.Add(v[j].Multiply(bfactor));
                }

                Debug.WriteLine(String.Format(" pc{0}={1}", i, total.ToString()));
                byte[] parts = new byte[39];
                parts[0] = 0x4f;
                parts[1] = (byte)(0x93 + PartsNeededToDecode);
                int parts23 = (((checksum[0] << 8) + checksum[1]) & 0x1ff);
                Debug.WriteLine("checksum " + parts23.ToString());
                parts23 += 0x6000;
                parts23 += (i << 9);
                byte[] btotal = total.ToByteArrayUnsigned();
                for (int jj = 0; jj < btotal.Length; jj++)
                {
                    parts[jj + 4 + (35 - btotal.Length)] = btotal[jj];
                }

                parts[2] = (byte)((parts23 & 0xFF00) >> 8);
                parts[3] = (byte)(parts23 & 0xFF);

                KeyParts.Add(Util.ByteArrayToBase58Check(parts));
                decodedKeyParts.Add(parts);
            }
        }
Пример #9
0
        private void RandomTest(SecureRandom srng, IGcmMultiplier m)
        {
            int kLength = 16 + 8 * srng.Next(3);

            byte[] K = new byte[kLength];
            srng.NextBytes(K);

            int pLength = srng.Next(65536);

            byte[] P = new byte[pLength];
            srng.NextBytes(P);

            int aLength = srng.Next(256);

            byte[] A = new byte[aLength];
            srng.NextBytes(A);

            int saLength = srng.Next(256);

            byte[] SA = new byte[saLength];
            srng.NextBytes(SA);

            int ivLength = 1 + srng.Next(256);

            byte[] IV = new byte[ivLength];
            srng.NextBytes(IV);

            AeadParameters parameters = new AeadParameters(new KeyParameter(K), 16 * 8, IV, A);
            GcmBlockCipher cipher     = InitCipher(m, true, parameters);

            byte[] C         = new byte[cipher.GetOutputSize(P.Length)];
            int    predicted = cipher.GetUpdateOutputSize(P.Length);

            int split = srng.Next(SA.Length + 1);

            cipher.ProcessAadBytes(SA, 0, split);
            int len = cipher.ProcessBytes(P, 0, P.Length, C, 0);

            cipher.ProcessAadBytes(SA, split, SA.Length - split);

            if (predicted != len)
            {
                Fail("encryption reported incorrect update length in randomised test");
            }

            len += cipher.DoFinal(C, len);

            if (C.Length != len)
            {
                Fail("encryption reported incorrect length in randomised test");
            }

            byte[] encT = cipher.GetMac();
            byte[] tail = new byte[C.Length - P.Length];
            Array.Copy(C, P.Length, tail, 0, tail.Length);

            if (!AreEqual(encT, tail))
            {
                Fail("stream contained wrong mac in randomised test");
            }

            cipher.Init(false, parameters);
            byte[] decP = new byte[cipher.GetOutputSize(C.Length)];
            predicted = cipher.GetUpdateOutputSize(C.Length);

            split = srng.Next(SA.Length + 1);
            cipher.ProcessAadBytes(SA, 0, split);
            len = cipher.ProcessBytes(C, 0, C.Length, decP, 0);
            cipher.ProcessAadBytes(SA, split, SA.Length - split);

            if (predicted != len)
            {
                Fail("decryption reported incorrect update length in randomised test");
            }

            len += cipher.DoFinal(decP, len);

            if (!AreEqual(P, decP))
            {
                Fail("incorrect decrypt in randomised test");
            }

            byte[] decT = cipher.GetMac();
            if (!AreEqual(encT, decT))
            {
                Fail("decryption produced different mac from encryption");
            }

            //
            // key reuse test
            //
            cipher.Init(false, AeadTestUtilities.ReuseKey(parameters));
            decP = new byte[cipher.GetOutputSize(C.Length)];

            split = NextInt(srng, SA.Length + 1);
            cipher.ProcessAadBytes(SA, 0, split);
            len = cipher.ProcessBytes(C, 0, C.Length, decP, 0);
            cipher.ProcessAadBytes(SA, split, SA.Length - split);

            len += cipher.DoFinal(decP, len);

            if (!AreEqual(P, decP))
            {
                Fail("incorrect decrypt in randomised test");
            }

            decT = cipher.GetMac();
            if (!AreEqual(encT, decT))
            {
                Fail("decryption produced different mac from encryption");
            }
        }
Пример #10
0
 internal static byte[] GenerateIV(int length, SecureRandom random)
 {
     byte[] iv = new byte[length];
     random.NextBytes(iv);
     return(iv);
 }
Пример #11
0
        protected virtual DsaParameters GenerateParameters_FIPS186_2()
        {
            byte[] seed  = new byte[20];
            byte[] part1 = new byte[20];
            byte[] part2 = new byte[20];
            byte[] u     = new byte[20];
            int    n     = (L - 1) / 160;

            byte[] w = new byte[L / 8];

            if (!(digest is Sha1Digest))
            {
                throw new InvalidOperationException("can only use SHA-1 for generating FIPS 186-2 parameters");
            }

            for (;;)
            {
                random.NextBytes(seed);

                Hash(digest, seed, part1);
                Array.Copy(seed, 0, part2, 0, seed.Length);
                Inc(part2);
                Hash(digest, part2, part2);

                for (int i = 0; i != u.Length; i++)
                {
                    u[i] = (byte)(part1[i] ^ part2[i]);
                }

                u[0]  |= (byte)0x80;
                u[19] |= (byte)0x01;

                BigInteger q = new BigInteger(1, u);

                if (!q.IsProbablePrime(certainty))
                {
                    continue;
                }

                byte[] offset = Arrays.Clone(seed);
                Inc(offset);

                for (int counter = 0; counter < 4096; ++counter)
                {
                    for (int k = 0; k < n; k++)
                    {
                        Inc(offset);
                        Hash(digest, offset, part1);
                        Array.Copy(part1, 0, w, w.Length - (k + 1) * part1.Length, part1.Length);
                    }

                    Inc(offset);
                    Hash(digest, offset, part1);
                    Array.Copy(part1, part1.Length - ((w.Length - (n) * part1.Length)), w, 0, w.Length - n * part1.Length);

                    w[0] |= (byte)0x80;

                    BigInteger x = new BigInteger(1, w);

                    BigInteger c = x.Mod(q.ShiftLeft(1));

                    BigInteger p = x.Subtract(c.Subtract(BigInteger.One));

                    if (p.BitLength != L)
                    {
                        continue;
                    }

                    if (p.IsProbablePrime(certainty))
                    {
                        BigInteger g = CalculateGenerator_FIPS186_2(p, q, random);

                        return(new DsaParameters(p, q, g, new DsaValidationParameters(seed, counter)));
                    }
                }
            }
        }
Пример #12
0
        public async void Handle(TLUpdatePhoneCall update)
        {
            await VoIPConnection.Current.SendUpdateAsync(update);

            await Task.Delay(2000);

            //if (update.PhoneCall is TLPhoneCallDiscarded discarded)
            //{
            //    if (discarded.IsNeedRating)
            //    {
            //        Debugger.Break();
            //    }

            //    if (discarded.IsNeedDebug)
            //    {
            //        Debugger.Break();
            //    }
            //}

            return;

            if (update.PhoneCall is TLPhoneCallRequested callRequested)
            {
                var reqReceived = new TLPhoneReceivedCall();
                reqReceived.Peer            = new TLInputPhoneCall();
                reqReceived.Peer.Id         = callRequested.Id;
                reqReceived.Peer.AccessHash = callRequested.AccessHash;

                ProtoService.SendRequestAsync <bool>("phone.receivedCall", reqReceived, null, null);

                var user = CacheService.GetUser(callRequested.AdminId) as TLUser;

                Execute.BeginOnUIThread(async() =>
                {
                    var dialog = await TLMessageDialog.ShowAsync(user.DisplayName, "CAAAALLL", "OK", "Cancel");
                    if (dialog == Windows.UI.Xaml.Controls.ContentDialogResult.Primary)
                    {
                        var config = await ProtoService.GetDHConfigAsync(0, 256);
                        if (config.IsSucceeded)
                        {
                            var dh = config.Result;
                            if (!TLUtils.CheckPrime(dh.P, dh.G))
                            {
                                return;
                            }

                            secretP = dh.P;

                            var salt         = new byte[256];
                            var secureRandom = new SecureRandom();
                            secureRandom.NextBytes(salt);

                            a_or_b = salt;

                            var g_b = MTProtoService.GetGB(salt, dh.G, dh.P);

                            var request = new TLPhoneAcceptCall
                            {
                                GB   = g_b,
                                Peer = new TLInputPhoneCall
                                {
                                    Id         = callRequested.Id,
                                    AccessHash = callRequested.AccessHash
                                },
                                Protocol = new TLPhoneCallProtocol
                                {
                                    IsUdpP2p       = true,
                                    IsUdpReflector = true,
                                    MinLayer       = 65,
                                    MaxLayer       = 65,
                                }
                            };

                            var response = await ProtoService.SendRequestAsync <TLPhonePhoneCall>("phone.acceptCall", request);
                            if (response.IsSucceeded)
                            {
                            }
                        }
                    }
                    else
                    {
                        var req             = new TLPhoneDiscardCall();
                        req.Peer            = new TLInputPhoneCall();
                        req.Peer.Id         = callRequested.Id;
                        req.Peer.AccessHash = callRequested.AccessHash;
                        req.Reason          = new TLPhoneCallDiscardReasonHangup();

                        ProtoService.SendRequestAsync <TLPhonePhoneCall>("phone.acceptCall", req, null, null);
                    }
                });
            }
            else if (update.PhoneCall is TLPhoneCall call)
            {
                var auth_key = computeAuthKey(call);
                var g_a      = call.GAOrB;

                var buffer = TLUtils.Combine(auth_key, g_a);
                var sha256 = Utils.ComputeSHA256(buffer);

                var emoji = EncryptionKeyEmojifier.EmojifyForCall(sha256);

                var user = CacheService.GetUser(call.AdminId) as TLUser;

                Execute.BeginOnUIThread(async() =>
                {
                    var dialog = await TLMessageDialog.ShowAsync(user.DisplayName, string.Join(" ", emoji), "OK");
                });
            }
        }
Пример #13
0
        public static TLEncryptedTransportMessage Encrypt(TLEncryptedTransportMessage transportMessage, byte[] authKey)
        {
#if MTPROTO
            var random = new SecureRandom();

            var data = transportMessage.Data;

            var    length       = data.Length;
            var    padding      = 16 - (length % 16);
            byte[] paddingBytes = null;
            if (padding < 12)
            {
                padding += 16;
            }
            if (padding >= 12 && padding <= 1024)
            {
                paddingBytes = new byte[padding];
                random.NextBytes(paddingBytes);
            }

            var dataWithPadding = data;
            if (paddingBytes != null)
            {
                dataWithPadding = TLUtils.Combine(data, paddingBytes);
            }

            var msgKey        = TLUtils.GetEncryptMsgKey(authKey, dataWithPadding);
            var keyIV         = TLUtils.GetEncryptKeyIV(authKey, msgKey);
            var encryptedData = Utils.AesIge(dataWithPadding, keyIV.Item1, keyIV.Item2, true);

            var authKeyId = TLUtils.GenerateLongAuthKeyId(authKey);

            transportMessage.AuthKeyId = new TLLong(authKeyId);
            transportMessage.MsgKey    = msgKey;
            transportMessage.Data      = encryptedData;

            return(transportMessage);
#else
            var random = new SecureRandom();

            var data = transportMessage.Data;

            var    length       = data.Length;
            var    padding      = 16 - (length % 16);
            byte[] paddingBytes = null;
            if (padding > 0 && padding < 16)
            {
                paddingBytes = new byte[padding];
                random.NextBytes(paddingBytes);
            }

            byte[] dataWithPadding = data;
            if (paddingBytes != null)
            {
                dataWithPadding = TLUtils.Combine(data, paddingBytes);
            }


            var msgKey        = TLUtils.GetMsgKey(data);
            var keyIV         = TLUtils.GetEncryptKeyIV(authKey, msgKey);
            var encryptedData = Utils.AesIge(dataWithPadding, keyIV.Item1, keyIV.Item2, true);

            var authKeyId = TLUtils.GenerateLongAuthKeyId(authKey);

            transportMessage.AuthKeyId = new TLLong(authKeyId);
            transportMessage.MsgKey    = msgKey;
            transportMessage.Data      = encryptedData;

            return(transportMessage);
#endif
        }
Пример #14
0
 public byte[] GenerateRandomBytes(int size)
 {
     byte[] bytes = new byte[size];
     Random.NextBytes(bytes);
     return(bytes);
 }
Пример #15
0
        public void Encryption(Stream inputStream, int subBlockSize)
        {
            bool ifBlock = false;

            byte[] data;
            using (MemoryStream ms = new MemoryStream())
            {
                inputStream.CopyTo(ms);
                data = ms.ToArray();
            }

            IBlockCipher engine = null;

            switch (this.Algorithm)
            {
            case "IDEA":
                engine = new IdeaEngine();
                break;

            case "DES":
                engine = new DesEngine();
                break;

            case "AES":
                engine = new AesEngine();
                break;
            }

            IBufferedCipher     cipher      = null;
            BufferedBlockCipher blockCipher = null;

            switch (this.CipherMode)
            {
            case "CBC":
                blockCipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(engine), new Pkcs7Padding());
                ifBlock     = true;
                break;

            case "ECB":
                cipher = CipherUtilities.GetCipher(this.Algorithm + "/ECB/PKCS7Padding");
                cipher.Init(true, new KeyParameter(this.Key));
                this.EncryptedData = cipher.DoFinal(data);
                break;

            case "CFB":
                blockCipher = new PaddedBufferedBlockCipher(new CfbBlockCipher(engine, subBlockSize), new Pkcs7Padding());
                ifBlock     = true;
                break;

            case "OFB":
                blockCipher = new PaddedBufferedBlockCipher(new OfbBlockCipher(engine, subBlockSize), new Pkcs7Padding());
                ifBlock     = true;
                break;

            default:
                Console.WriteLine("Default case");
                break;
            }

            if (ifBlock)
            {
                ICipherParameters cipherParams = null;

                this.IvVector = new byte[8];
                SecureRandom rand = new SecureRandom();
                rand.NextBytes(this.IvVector);
                KeyParameter kluczParam = new KeyParameter(this.Key);
                cipherParams = new ParametersWithIV(kluczParam, this.IvVector);

                blockCipher.Init(true, cipherParams);
                this.EncryptedData = new byte[blockCipher.GetOutputSize(data.Length)];
                int bytesLength = blockCipher.ProcessBytes(data, 0, data.Length, this.EncryptedData, 0);
                blockCipher.DoFinal(this.EncryptedData, bytesLength);
                ifBlock = false;
            }
        }
        public byte[] GenerateKey()
        {
            var key = new byte[KeyBitSize / 8];

            _random.NextBytes(key);
            key[^ 1] &= 0x7F;
Пример #17
0
        public void StartOutgoingCall(TLInputUserBase userId)
        {
            var salt   = new Byte[256];
            var random = new SecureRandom();

            random.NextBytes(salt);

            var version      = _lastVersion ?? new TLInt(0);
            var randomLength = new TLInt(256);

            _mtProtoService.GetDHConfigAsync(version, randomLength,
                                             result =>
            {
                ConfigureDeviceForCall();
                ShowNotifications();
                StartConnectionSound();
                DispatchStateChanged(PhoneCallState.STATE_REQUESTING);

                _eventAggregator.Publish(new PhoneCallEventArgs("NotificationCenter.didStartedCall"));

                var dhConfig = result as TLDHConfig;
                if (dhConfig != null)
                {
                    if (!TLUtils.CheckPrime(dhConfig.P.Data, dhConfig.G.Value))
                    {
                        CallFailed();
                        return;
                    }

                    _secretP      = dhConfig.P;
                    _secretG      = dhConfig.G;
                    _secretRandom = dhConfig.Random;
                }

                for (var i = 0; i < 256; i++)
                {
                    salt[i] = (byte)(salt[i] ^ _secretRandom.Data[i]);
                }

                var gaBytes = MTProtoService.GetGB(salt, _secretG, _secretP);

                var protocol = new TLPhoneCallProtocol
                {
                    Flags        = new TLInt(0),
                    UdpP2P       = true,
                    UdpReflector = true,
                    MinLayer     = new TLInt(CALL_MIN_LAYER),
                    MaxLayer     = new TLInt(CALL_MAX_LAYER)
                };
                _ga        = gaBytes;
                var gaHash = Utils.ComputeSHA256(_ga);

                _mtProtoService.RequestCallAsync(userId, TLInt.Random(), TLString.FromBigEndianData(gaHash), protocol,
                                                 result2 =>
                {
                    _call = result2;
                    _aOrB = salt;
                    DispatchStateChanged(PhoneCallState.STATE_WAITING);
                    //if (_endCallAfterRequest)
                    //{
                    //    Hangup();
                    //    return;
                    //}
                },
                                                 error2 =>
                {
                });
            },
                                             error =>
            {
                Helpers.Execute.ShowDebugMessage("messages.getDHConfig error " + error);
                CallFailed();
            });
        }
 /// <summary>
 /// Creates a new KeyStoreAccount.
 /// </summary>
 /// <param name="name">Name of account</param>
 /// <param name="id">identifier (public address)</param>
 /// <param name="key">private key</param>
 public KeyStoreProfile(string name, HoardID id, byte[] key)
     : base(name, id)
 {
     Random.NextBytes(localKey);
     encryptedKey = Encode(key);
 }
Пример #19
0
        public static string DemonstrateFileEncryption(string plainText, string password)
        {
            #region INITIALIZATION
            SecureRandom Random            = new SecureRandom();
            byte[]       dataForEncryption = Encoding.UTF8.GetBytes(plainText);
            Pkcs5S2ParametersGenerator pkcs5S2ParametersGenerator = new Pkcs5S2ParametersGenerator();
            byte[] salt = new byte[16];
            Random.NextBytes(salt);
            pkcs5S2ParametersGenerator.Init(PbeParametersGenerator.Pkcs5PasswordToBytes(password.ToCharArray()), salt, 10000);
            KeyParameter key   = (KeyParameter)pkcs5S2ParametersGenerator.GenerateDerivedMacParameters(256);
            byte[]       nonce = new byte[16];
            Random.NextBytes(nonce);
            GcmBlockCipher gcmBlockCipher = new GcmBlockCipher(new AesEngine());
            AeadParameters aeadParameters = new AeadParameters(new KeyParameter(key.GetKey()), 128, nonce, salt);
            gcmBlockCipher.Init(true, aeadParameters);
            #endregion

            #region ENCRYPTION
            //Generate ciphertext with authentication tag.
            byte[] cipherTextAsByteArray = new byte[gcmBlockCipher.GetOutputSize(dataForEncryption.Length)];
            int    length = gcmBlockCipher.ProcessBytes(dataForEncryption, 0, dataForEncryption.Length, cipherTextAsByteArray, 0);
            gcmBlockCipher.DoFinal(cipherTextAsByteArray, length);
            byte[] output = null;
            //Put the pices of the message together.
            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream))
                {
                    binaryWriter.Write(salt);
                    binaryWriter.Write(nonce);
                    binaryWriter.Write(cipherTextAsByteArray);
                }
                output = memoryStream.ToArray();
            }
            File.WriteAllBytes("encryptedFile.enc", output);
            #endregion

            #region DECRYPTION
            byte[] encryptedMessageAsByteArray = File.ReadAllBytes("encryptedFile.enc");
            salt = new byte[16];
            Array.Copy(encryptedMessageAsByteArray, salt, salt.Length);

            using (MemoryStream memoryStream = new MemoryStream(encryptedMessageAsByteArray))
                using (BinaryReader binaryReader = new BinaryReader(memoryStream))
                {
                    salt           = binaryReader.ReadBytes(salt.Length);
                    nonce          = binaryReader.ReadBytes(16);
                    gcmBlockCipher = new GcmBlockCipher(new AesEngine());
                    aeadParameters = new AeadParameters(new KeyParameter(key.GetKey()), 128, nonce, salt);
                    gcmBlockCipher.Init(false, aeadParameters);

                    cipherTextAsByteArray = binaryReader.ReadBytes(encryptedMessageAsByteArray.Length - salt.Length - nonce.Length);
                    byte[] decryptedTextAsByteArray = new byte[gcmBlockCipher.GetOutputSize(cipherTextAsByteArray.Length)];

                    try
                    {
                        //Authentication check.
                        length = gcmBlockCipher.ProcessBytes(cipherTextAsByteArray, 0, cipherTextAsByteArray.Length, decryptedTextAsByteArray, 0);
                        gcmBlockCipher.DoFinal(decryptedTextAsByteArray, length);
                    }
                    catch (InvalidCipherTextException e)
                    {
                        //Authentication failed.
                        Log.Error("Error: {0}", e.Message);
                        return(null);
                    }
                    Log.Information("Decrypted file content and original plain text are the same: {0}", plainText.Equals(Encoding.UTF8.GetString(decryptedTextAsByteArray)));
                    return(Encoding.UTF8.GetString(decryptedTextAsByteArray));
                }
            #endregion
        }
Пример #20
0
        /// <summary> Generate a signature for the loaded message using the key we were
        /// initialised with.
        /// </summary>
        public byte[] GenerateSignature()
        {
            int digSize = digest.GetDigestSize();

            byte[] m2Hash = new byte[digSize];
            digest.DoFinal(m2Hash, 0);

            byte[] C = new byte[8];
            LtoOSP(messageLength * 8, C);

            digest.BlockUpdate(C, 0, C.Length);
            digest.BlockUpdate(mBuf, 0, messageLength);
            digest.BlockUpdate(m2Hash, 0, m2Hash.Length);

            byte[] salt;
            if (standardSalt != null)
            {
                salt = standardSalt;
            }
            else
            {
                salt = new byte[saltLength];
                random.NextBytes(salt);
            }

            digest.BlockUpdate(salt, 0, salt.Length);

            byte[] hash = new byte[digest.GetDigestSize()];
            digest.DoFinal(hash, 0);

            int tLength = 2;

            if (trailer == TrailerImplicit)
            {
                tLength = 1;
            }

            int off = block.Length - messageLength - salt.Length - hLen - tLength - 1;

            block[off] = (byte)(0x01);

            Array.Copy(mBuf, 0, block, off + 1, messageLength);
            Array.Copy(salt, 0, block, off + 1 + messageLength, salt.Length);

            byte[] dbMask = MaskGeneratorFunction1(hash, 0, hash.Length, block.Length - hLen - tLength);
            for (int i = 0; i != dbMask.Length; i++)
            {
                block[i] ^= dbMask[i];
            }

            Array.Copy(hash, 0, block, block.Length - hLen - tLength, hLen);

            if (trailer == TrailerImplicit)
            {
                block[block.Length - 1] = (byte)TrailerImplicit;
            }
            else
            {
                block[block.Length - 2] = (byte)((uint)trailer >> 8);
                block[block.Length - 1] = (byte)trailer;
            }

            block[0] &= (byte)(0x7f);

            byte[] b = cipher.ProcessBlock(block, 0, block.Length);

            ClearBlock(mBuf);
            ClearBlock(block);
            messageLength = 0;

            return(b);
        }
Пример #21
0
 private void FillCryptoBytes(byte[] bytes)
 {
     random.NextBytes(bytes); // generates 8 random bytes
 }
Пример #22
0
        public void InitAsync(Action <Tuple <byte[], long?, long?> > callback, Action <TLRPCError> faultCallback = null)
        {
            var authTime = Stopwatch.StartNew();
            var newNonce = TLInt256.Random();

#if LOG_REGISTRATION
            TLUtils.WriteLog("Start ReqPQ");
#endif
            var nonce = TLInt128.Random();
            ReqPQAsync(nonce,
                       resPQ =>
            {
                var serverNonce = resPQ.ServerNonce;
                if (nonce != resPQ.Nonce)
                {
                    var error = new TLRPCError {
                        ErrorCode = 404, ErrorMessage = "incorrect nonce"
                    };
#if LOG_REGISTRATION
                    TLUtils.WriteLog("Stop ReqPQ with error " + error);
#endif

                    if (faultCallback != null)
                    {
                        faultCallback(error);
                    }
                    TLUtils.WriteLine(error.ToString());
                }

#if LOG_REGISTRATION
                TLUtils.WriteLog("Stop ReqPQ");
#endif
                TimeSpan calcTime;
                Tuple <ulong, ulong> pqPair;
                var innerData          = GetInnerData(resPQ, newNonce, out calcTime, out pqPair);
                var encryptedInnerData = GetEncryptedInnerData(innerData, null);

#if LOG_REGISTRATION
                var pq = BitConverter.ToUInt64(resPQ.PQ.Reverse().ToArray(), 0);

                var logPQString = new StringBuilder();
                logPQString.AppendLine("PQ Counters");
                logPQString.AppendLine();
                logPQString.AppendLine("pq: " + pq);
                logPQString.AppendLine("p: " + pqPair.Item1);
                logPQString.AppendLine("q: " + pqPair.Item2);
                logPQString.AppendLine("encrypted_data length: " + encryptedInnerData.Length);
                TLUtils.WriteLog(logPQString.ToString());

                TLUtils.WriteLog("Start ReqDHParams");
#endif
                ReqDHParamsAsync(
                    resPQ.Nonce,
                    resPQ.ServerNonce,
                    innerData.P,
                    innerData.Q,
                    resPQ.ServerPublicKeyFingerprints[0],
                    encryptedInnerData,
                    serverDHParams =>
                {
                    if (nonce != serverDHParams.Nonce)
                    {
                        var error = new TLRPCError {
                            ErrorCode = 404, ErrorMessage = "incorrect nonce"
                        };
#if LOG_REGISTRATION
                        TLUtils.WriteLog("Stop ReqDHParams with error " + error);
#endif

                        if (faultCallback != null)
                        {
                            faultCallback(error);
                        }
                        TLUtils.WriteLine(error.ToString());
                    }
                    if (serverNonce != serverDHParams.ServerNonce)
                    {
                        var error = new TLRPCError {
                            ErrorCode = 404, ErrorMessage = "incorrect server_nonce"
                        };
#if LOG_REGISTRATION
                        TLUtils.WriteLog("Stop ReqDHParams with error " + error);
#endif

                        if (faultCallback != null)
                        {
                            faultCallback(error);
                        }
                        TLUtils.WriteLine(error.ToString());
                    }

#if LOG_REGISTRATION
                    TLUtils.WriteLog("Stop ReqDHParams");
#endif
                    var random = new SecureRandom();

                    var serverDHParamsOk = serverDHParams as TLServerDHParamsOk;
                    if (serverDHParamsOk == null)
                    {
                        var error = new TLRPCError {
                            ErrorCode = 404, ErrorMessage = "Incorrect serverDHParams " + serverDHParams.GetType()
                        };
                        if (faultCallback != null)
                        {
                            faultCallback(error);
                        }
                        TLUtils.WriteLine(error.ToString());
#if LOG_REGISTRATION
                        TLUtils.WriteLog("ServerDHParams " + serverDHParams);
#endif
                        return;
                    }

                    var aesParams = GetAesKeyIV(resPQ.ServerNonce.ToArray(), newNonce.ToArray());

                    var decryptedAnswerWithHash = Utils.AesIge(serverDHParamsOk.EncryptedAnswer, aesParams.Item1, aesParams.Item2, false);

                    //var position = 0;
                    //var serverDHInnerData = (TLServerDHInnerData)new TLServerDHInnerData().FromBytes(decryptedAnswerWithHash.Skip(20).ToArray(), ref position);
                    var serverDHInnerData = TLFactory.From <TLServerDHInnerData>(decryptedAnswerWithHash.Skip(20).ToArray());

                    var sha1 = Utils.ComputeSHA1(serverDHInnerData.ToArray());
                    if (!TLUtils.ByteArraysEqual(sha1, decryptedAnswerWithHash.Take(20).ToArray()))
                    {
                        var error = new TLRPCError {
                            ErrorCode = 404, ErrorMessage = "incorrect sha1 TLServerDHInnerData"
                        };
#if LOG_REGISTRATION
                        TLUtils.WriteLog("Stop ReqDHParams with error " + error);
#endif

                        if (faultCallback != null)
                        {
                            faultCallback(error);
                        }
                        TLUtils.WriteLine(error.ToString());
                    }

                    if (!TLUtils.CheckPrime(serverDHInnerData.DHPrime, serverDHInnerData.G))
                    {
                        var error = new TLRPCError {
                            ErrorCode = 404, ErrorMessage = "incorrect (p, q) pair"
                        };
#if LOG_REGISTRATION
                        TLUtils.WriteLog("Stop ReqDHParams with error " + error);
#endif

                        if (faultCallback != null)
                        {
                            faultCallback(error);
                        }
                        TLUtils.WriteLine(error.ToString());
                    }

                    if (!TLUtils.CheckGaAndGb(serverDHInnerData.GA, serverDHInnerData.DHPrime))
                    {
                        var error = new TLRPCError {
                            ErrorCode = 404, ErrorMessage = "incorrect g_a"
                        };
#if LOG_REGISTRATION
                        TLUtils.WriteLog("Stop ReqDHParams with error " + error);
#endif

                        if (faultCallback != null)
                        {
                            faultCallback(error);
                        }
                        TLUtils.WriteLine(error.ToString());
                    }

                    var bBytes = new byte[256];         //big endian B
                    random.NextBytes(bBytes);

                    var gbBytes = GetGB(bBytes, serverDHInnerData.G, serverDHInnerData.DHPrime);

                    var clientDHInnerData = new TLClientDHInnerData
                    {
                        Nonce       = resPQ.Nonce,
                        ServerNonce = resPQ.ServerNonce,
                        RetryId     = 0,
                        GB          = gbBytes
                    };

                    var encryptedClientDHInnerData = GetEncryptedClientDHInnerData(clientDHInnerData, aesParams);
#if LOG_REGISTRATION
                    TLUtils.WriteLog("Start SetClientDHParams");
#endif
                    SetClientDHParamsAsync(resPQ.Nonce, resPQ.ServerNonce, encryptedClientDHInnerData,
                                           dhGen =>
                    {
                        if (nonce != dhGen.Nonce)
                        {
                            var error = new TLRPCError {
                                ErrorCode = 404, ErrorMessage = "incorrect nonce"
                            };
#if LOG_REGISTRATION
                            TLUtils.WriteLog("Stop SetClientDHParams with error " + error);
#endif

                            if (faultCallback != null)
                            {
                                faultCallback(error);
                            }
                            TLUtils.WriteLine(error.ToString());
                        }
                        if (serverNonce != dhGen.ServerNonce)
                        {
                            var error = new TLRPCError {
                                ErrorCode = 404, ErrorMessage = "incorrect server_nonce"
                            };
#if LOG_REGISTRATION
                            TLUtils.WriteLog("Stop SetClientDHParams with error " + error);
#endif

                            if (faultCallback != null)
                            {
                                faultCallback(error);
                            }
                            TLUtils.WriteLine(error.ToString());
                        }

                        var dhGenOk = dhGen as TLDHGenOk;
                        if (dhGenOk == null)
                        {
                            var error = new TLRPCError {
                                ErrorCode = 404, ErrorMessage = "Incorrect dhGen " + dhGen.GetType()
                            };
                            if (faultCallback != null)
                            {
                                faultCallback(error);
                            }
                            TLUtils.WriteLine(error.ToString());
#if LOG_REGISTRATION
                            TLUtils.WriteLog("DHGen result " + serverDHParams);
#endif
                            return;
                        }


                        _authTimeElapsed = authTime.Elapsed;
#if LOG_REGISTRATION
                        TLUtils.WriteLog("Stop SetClientDHParams");
#endif
                        var getKeyTimer = Stopwatch.StartNew();
                        var authKey     = GetAuthKey(bBytes, serverDHInnerData.GA.ToBytes(), serverDHInnerData.DHPrime.ToBytes());

                        var logCountersString = new StringBuilder();

                        logCountersString.AppendLine("Auth Counters");
                        logCountersString.AppendLine();
                        logCountersString.AppendLine("pq factorization time: " + calcTime);
                        logCountersString.AppendLine("calc auth key time: " + getKeyTimer.Elapsed);
                        logCountersString.AppendLine("auth time: " + _authTimeElapsed);
#if LOG_REGISTRATION
                        TLUtils.WriteLog(logCountersString.ToString());
#endif
                        //newNonce - little endian
                        //authResponse.ServerNonce - little endian
                        var salt      = GetSalt(newNonce.ToArray(), resPQ.ServerNonce.ToArray());
                        var sessionId = new byte[8];
                        random.NextBytes(sessionId);

                        TLUtils.WriteLine("Salt " + BitConverter.ToInt64(salt, 0) + " (" + BitConverter.ToString(salt) + ")");
                        TLUtils.WriteLine("Session id " + BitConverter.ToInt64(sessionId, 0) + " (" + BitConverter.ToString(sessionId) + ")");

                        callback(new Tuple <byte[], long?, long?>(authKey, BitConverter.ToInt64(salt, 0), BitConverter.ToInt64(sessionId, 0)));
                    },
                                           error =>
                    {
#if LOG_REGISTRATION
                        TLUtils.WriteLog("Stop SetClientDHParams with error " + error.ToString());
#endif
                        if (faultCallback != null)
                        {
                            faultCallback(error);
                        }
                        TLUtils.WriteLine(error.ToString());
                    });
                },
                    error =>
                {
#if LOG_REGISTRATION
                    TLUtils.WriteLog("Stop ReqDHParams with error " + error.ToString());
#endif
                    if (faultCallback != null)
                    {
                        faultCallback(error);
                    }
                    TLUtils.WriteLine(error.ToString());
                });
            },
                       error =>
            {
#if LOG_REGISTRATION
                TLUtils.WriteLog("Stop ReqPQ with error " + error.ToString());
#endif
                if (faultCallback != null)
                {
                    faultCallback(error);
                }
                TLUtils.WriteLine(error.ToString());
            });
        }
Пример #23
0
        public void WriteObject(
            object obj,
            string algorithm,
            char[]                  password,
            SecureRandom random)
        {
            if (obj == null)
            {
                throw new ArgumentNullException("obj");
            }
            if (algorithm == null)
            {
                throw new ArgumentNullException("algorithm");
            }
            if (password == null)
            {
                throw new ArgumentNullException("password");
            }
            if (random == null)
            {
                throw new ArgumentNullException("random");
            }

            if (obj is AsymmetricCipherKeyPair)
            {
                WriteObject(((AsymmetricCipherKeyPair)obj).Private, algorithm, password, random);
                return;
            }

            string type = null;

            byte[] keyData = null;

            if (obj is AsymmetricKeyParameter)
            {
                AsymmetricKeyParameter akp = (AsymmetricKeyParameter)obj;
                if (akp.IsPrivate)
                {
                    string keyType;
                    keyData = EncodePrivateKey(akp, out keyType);

                    type = keyType + " PRIVATE KEY";
                }
            }

            if (type == null || keyData == null)
            {
                // TODO Support other types?
                throw new ArgumentException("Object type not supported: " + obj.GetType().FullName, "obj");
            }


            string dekAlgName = algorithm.ToUpper(CultureInfo.InvariantCulture);

            // Note: For backward compatibility
            if (dekAlgName == "DESEDE")
            {
                dekAlgName = "DES-EDE3-CBC";
            }

            int ivLength = dekAlgName.StartsWith("AES-") ? 16 : 8;

            byte[] iv = new byte[ivLength];
            random.NextBytes(iv);

            byte[] encData = PemUtilities.Crypt(true, keyData, password, dekAlgName, iv);
            byte[] hexIV   = Hex.Encode(iv);

            WritePemBlock(type, encData,
                          "Proc-Type: 4,ENCRYPTED",
                          "DEK-Info: " + dekAlgName + "," + Encoding.ASCII.GetString(hexIV, 0, hexIV.Length));
        }
Пример #24
0
        public Tuple <string, byte[]> Post(byte[] body, ControllerSession session)
        {
            var parts = TLVParser.Parse(body);

            var state = parts.GetTypeAsInt(Constants.State);

            if (state == 1)
            {
                Console.WriteLine("* Pair Verify Step 1/4");
                Console.WriteLine("* Verify Start Request");

                var clientPublicKey = parts.GetType(Constants.PublicKey);

                byte[]       privateKey = new byte[32];
                SecureRandom random     = new SecureRandom();
                random.NextBytes(privateKey);

                var publicKey = Curve25519.GetPublicKey(privateKey);

                var sharedSecret = Curve25519.GetSharedSecret(privateKey, clientPublicKey);

                var serverUsername = Encoding.UTF8.GetBytes(Program.ID);

                byte[] material = publicKey.Concat(serverUsername).Concat(clientPublicKey).ToArray();

                var accessoryLTSK = File.ReadAllBytes("PrivateKey");

                byte[] proof = Ed25519.Sign(material, accessoryLTSK);

                HKDF g         = new HKDF(() => { return(new HMACSHA512()); }, sharedSecret, Encoding.UTF8.GetBytes("Pair-Verify-Encrypt-Salt"), Encoding.UTF8.GetBytes("Pair-Verify-Encrypt-Info"));
                var  outputKey = g.GetBytes(32);

                TLV encoder = new TLV();
                encoder.AddType(Constants.Identifier, serverUsername);
                encoder.AddType(Constants.Signature, proof);

                byte[] plaintext = TLVParser.Serialise(encoder);

                var nonce = Cnv.FromHex("00000000").Concat(Encoding.UTF8.GetBytes("PV-Msg02")).ToArray();
                var aad   = new byte[0];

                byte[] outputTag = new byte[0];

                var encryptedOutput = Aead.Encrypt(out outputTag, plaintext, outputKey, nonce, aad, Aead.Algorithm.Chacha20_Poly1305);

                byte[] ret = encryptedOutput.Concat(outputTag).ToArray();

                TLV responseTLV = new TLV();
                responseTLV.AddType(Constants.State, 2);
                responseTLV.AddType(Constants.PublicKey, publicKey);
                responseTLV.AddType(Constants.EncryptedData, ret);

                // Store the details on the session.
                //
                session.ClientPublicKey = clientPublicKey;
                session.PrivateKey      = privateKey;
                session.PublicKey       = publicKey;
                session.SharedSecret    = sharedSecret;
                session.HkdfPairEncKey  = outputKey;

                var encSalt   = Encoding.UTF8.GetBytes("Control-Salt");
                var infoRead  = Encoding.UTF8.GetBytes("Control-Read-Encryption-Key");
                var infoWrite = Encoding.UTF8.GetBytes("Control-Write-Encryption-Key");

                g = new HKDF(() => { return(new HMACSHA512()); }, sharedSecret, encSalt, infoRead);
                session.AccessoryToControllerKey = g.GetBytes(32);

                g = new HKDF(() => { return(new HMACSHA512()); }, sharedSecret, encSalt, infoWrite);
                session.ControllerToAccessoryKey = g.GetBytes(32);

                var output = TLVParser.Serialise(responseTLV);

                return(new Tuple <string, byte[]>("application/pairing+tlv8", output));
            }
            else if (state == 3)
            {
                Console.WriteLine("* Pair Verify Step 3/4");
                Console.WriteLine("* Verify Start Request");

                // We're looking good here. Need to set the encryption/settings on this session.
                //
                session.IsVerified          = true;
                session.SkipFirstEncryption = true;

                TLV responseTLV = new TLV();
                responseTLV.AddType(Constants.State, 4);

                var output = TLVParser.Serialise(responseTLV);

                return(new Tuple <string, byte[]>("application/pairing+tlv8", output));
            }

            return(null);
        }
Пример #25
0
//		private string GetHexEncoded(byte[] bytes)
//		{
//			bytes = Hex.Encode(bytes);
//
//			char[] chars = new char[bytes.Length];
//
//			for (int i = 0; i != bytes.Length; i++)
//			{
//				chars[i] = (char)bytes[i];
//			}
//
//			return new string(chars);
//		}

        private static PemObject CreatePemObject(
            object obj,
            string algorithm,
            char[]                      password,
            SecureRandom random)
        {
            if (obj == null)
            {
                throw new ArgumentNullException("obj");
            }
            if (algorithm == null)
            {
                throw new ArgumentNullException("algorithm");
            }
            if (password == null)
            {
                throw new ArgumentNullException("password");
            }
            if (random == null)
            {
                throw new ArgumentNullException("random");
            }

            if (obj is AsymmetricCipherKeyPair)
            {
                return(CreatePemObject(((AsymmetricCipherKeyPair)obj).Private, algorithm, password, random));
            }

            string type = null;

            byte[] keyData = null;

            if (obj is AsymmetricKeyParameter)
            {
                AsymmetricKeyParameter akp = (AsymmetricKeyParameter)obj;
                if (akp.IsPrivate)
                {
                    string keyType;
                    keyData = EncodePrivateKey(akp, out keyType);

                    type = keyType + " PRIVATE KEY";
                }
            }

            if (type == null || keyData == null)
            {
                // TODO Support other types?
                throw new PemGenerationException("Object type not supported: " + Platform.GetTypeName(obj));
            }


            string dekAlgName = Platform.ToUpperInvariant(algorithm);

            // Note: For backward compatibility
            if (dekAlgName == "DESEDE")
            {
                dekAlgName = "DES-EDE3-CBC";
            }

            int ivLength = Platform.StartsWith(dekAlgName, "AES-") ? 16 : 8;

            byte[] iv = new byte[ivLength];
            random.NextBytes(iv);

            byte[] encData = PemUtilities.Crypt(true, keyData, password, dekAlgName, iv);

            IList headers = Platform.CreateArrayList(2);

            headers.Add(new PemHeader("Proc-Type", "4,ENCRYPTED"));
            headers.Add(new PemHeader("DEK-Info", dekAlgName + "," + Hex.ToHexString(iv)));

            return(new PemObject(type, headers, encData));
        }
        public virtual void Connect(TlsClient tlsClient)
        {
            if (tlsClient == null)
            {
                throw new ArgumentNullException("tlsClient");
            }
            if (this.tlsClient != null)
            {
                throw new InvalidOperationException("Connect can only be called once");
            }

            /*
             * Send Client hello
             *
             * First, generate some random data.
             */
            this.securityParameters = new SecurityParameters();
            this.securityParameters.clientRandom = new byte[32];
            random.NextBytes(securityParameters.clientRandom, 4, 28);
            TlsUtilities.WriteGmtUnixTime(securityParameters.clientRandom, 0);

            this.tlsClientContext = new TlsClientContextImpl(random, securityParameters);
            this.tlsClient        = tlsClient;
            this.tlsClient.Init(tlsClientContext);

            MemoryStream outStr = new MemoryStream();

            TlsUtilities.WriteVersion(outStr);
            outStr.Write(securityParameters.clientRandom, 0, 32);

            /*
             * Length of Session id
             */
            TlsUtilities.WriteUint8(0, outStr);

            this.offeredCipherSuites = this.tlsClient.GetCipherSuites();

            // ExtensionType -> byte[]
            this.clientExtensions = this.tlsClient.GetClientExtensions();

            // Cipher Suites (and SCSV)
            {
                /*
                 * RFC 5746 3.4.
                 * The client MUST include either an empty "renegotiation_info"
                 * extension, or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling
                 * cipher suite value in the ClientHello.  Including both is NOT
                 * RECOMMENDED.
                 */
                bool noRenegExt = clientExtensions == null ||
                                  !clientExtensions.Contains(ExtensionType.renegotiation_info);

                int count = offeredCipherSuites.Length;
                if (noRenegExt)
                {
                    // Note: 1 extra slot for TLS_EMPTY_RENEGOTIATION_INFO_SCSV
                    ++count;
                }

                TlsUtilities.WriteUint16(2 * count, outStr);

                for (int i = 0; i < offeredCipherSuites.Length; ++i)
                {
                    TlsUtilities.WriteUint16((int)offeredCipherSuites[i], outStr);
                }

                if (noRenegExt)
                {
                    TlsUtilities.WriteUint16((int)CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV, outStr);
                }
            }

            /*
             * Compression methods, just the null method.
             */
            this.offeredCompressionMethods = tlsClient.GetCompressionMethods();

            {
                TlsUtilities.WriteUint8((byte)offeredCompressionMethods.Length, outStr);
                for (int i = 0; i < offeredCompressionMethods.Length; ++i)
                {
                    TlsUtilities.WriteUint8((byte)offeredCompressionMethods[i], outStr);
                }
            }

            // Extensions
            if (clientExtensions != null)
            {
                MemoryStream ext = new MemoryStream();

                foreach (ExtensionType extType in clientExtensions.Keys)
                {
                    WriteExtension(ext, extType, (byte[])clientExtensions[extType]);
                }

                TlsUtilities.WriteOpaque16(ext.ToArray(), outStr);
            }

            MemoryStream bos = new MemoryStream();

            TlsUtilities.WriteUint8((byte)HandshakeType.client_hello, bos);
            TlsUtilities.WriteUint24((int)outStr.Length, bos);
            byte[] outBytes = outStr.ToArray();
            bos.Write(outBytes, 0, outBytes.Length);
            byte[] message = bos.ToArray();
            SafeWriteMessage(ContentType.handshake, message, 0, message.Length);
            connection_state = CS_CLIENT_HELLO_SEND;

            /*
             * We will now read data, until we have completed the handshake.
             */
            while (connection_state != CS_DONE)
            {
                SafeReadData();
            }

            this.tlsStream = new TlsStream(this);
        }
 public void SetupGenerateKey()
 {
     privateKey = new byte[Ed25519.SecretKeySize];
     publicKey  = new byte[Ed25519.PublicKeySize];
     Random.NextBytes(privateKey);
 }
Пример #28
0
        /// <summary>
        /// <p>
        /// If buffer is non null stream assumed to be partial, otherwise the length will be used
        /// to output a fixed length packet.
        /// </p>
        /// <p>
        /// The stream created can be closed off by either calling Close()
        /// on the stream or Close() on the generator. Closing the returned
        /// stream does not close off the Stream parameter <c>outStr</c>.
        /// </p>
        /// </summary>
        private Stream Open(
            Stream outStr,
            long length,
            byte[]      buffer)
        {
            if (cOut != null)
            {
                throw new InvalidOperationException("generator already in open state");
            }
            if (methods.Count == 0)
            {
                throw new InvalidOperationException("No encryption methods specified");
            }
            if (outStr == null)
            {
                throw new ArgumentNullException("outStr");
            }

            pOut = new BcpgOutputStream(outStr);

            KeyParameter key;

            if (methods.Count == 1)
            {
                if (methods[0] is PbeMethod)
                {
                    PbeMethod m = (PbeMethod)methods[0];

                    key = m.GetKey();
                }
                else
                {
                    key = PgpUtilities.MakeRandomKey(defAlgorithm, rand);

                    byte[]    sessionInfo = CreateSessionInfo(defAlgorithm, key);
                    PubMethod m           = (PubMethod)methods[0];

                    try
                    {
                        m.AddSessionInfo(sessionInfo, rand);
                    }
                    catch (Exception e)
                    {
                        throw new PgpException("exception encrypting session key", e);
                    }
                }

                pOut.WritePacket((ContainedPacket)methods[0]);
            }
            else // multiple methods
            {
                key = PgpUtilities.MakeRandomKey(defAlgorithm, rand);
                byte[] sessionInfo = CreateSessionInfo(defAlgorithm, key);

                for (int i = 0; i != methods.Count; i++)
                {
                    EncMethod m = (EncMethod)methods[i];

                    try
                    {
                        m.AddSessionInfo(sessionInfo, rand);
                    }
                    catch (Exception e)
                    {
                        throw new PgpException("exception encrypting session key", e);
                    }

                    pOut.WritePacket(m);
                }
            }

            string cName = PgpUtilities.GetSymmetricCipherName(defAlgorithm);

            if (cName == null)
            {
                throw new PgpException("null cipher specified");
            }

            try
            {
                if (withIntegrityPacket)
                {
                    cName += "/CFB/NoPadding";
                }
                else
                {
                    cName += "/OpenPGPCFB/NoPadding";
                }

                c = CipherUtilities.GetCipher(cName);

                // TODO Confirm the IV should be all zero bytes (not inLineIv - see below)
                byte[] iv = new byte[c.GetBlockSize()];
                c.Init(true, new ParametersWithRandom(new ParametersWithIV(key, iv), rand));

                if (buffer == null)
                {
                    //
                    // we have to Add block size + 2 for the Generated IV and + 1 + 22 if integrity protected
                    //
                    if (withIntegrityPacket)
                    {
                        pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricEncryptedIntegrityProtected, length + c.GetBlockSize() + 2 + 1 + 22);
                        pOut.WriteByte(1);        // version number
                    }
                    else
                    {
                        pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricKeyEncrypted, length + c.GetBlockSize() + 2, oldFormat);
                    }
                }
                else
                {
                    if (withIntegrityPacket)
                    {
                        pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricEncryptedIntegrityProtected, buffer);
                        pOut.WriteByte(1);        // version number
                    }
                    else
                    {
                        pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricKeyEncrypted, buffer);
                    }
                }

                int    blockSize = c.GetBlockSize();
                byte[] inLineIv  = new byte[blockSize + 2];
                rand.NextBytes(inLineIv, 0, blockSize);
                Array.Copy(inLineIv, inLineIv.Length - 4, inLineIv, inLineIv.Length - 2, 2);

                Stream myOut = cOut = new CipherStream(pOut, null, c);

                if (withIntegrityPacket)
                {
                    string  digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1);
                    IDigest digest     = DigestUtilities.GetDigest(digestName);
                    myOut = digestOut = new DigestStream(myOut, null, digest);
                }

                myOut.Write(inLineIv, 0, inLineIv.Length);

                return(new WrappedGeneratorStream(this, myOut));
            }
            catch (Exception e)
            {
                throw new PgpException("Exception creating cipher", e);
            }
        }
Пример #29
0
 public void GenerateBits()
 {
     using (var random = new SecureRandom())
     {
         random.NextBytes(new byte[10]);
     }
 }
Пример #30
0
 /// <summary>
 /// Helper that generates a random new key on each call.
 /// </summary>
 /// <returns></returns>
 public static byte[] NewKey()
 {
     byte[] key = new byte[KeyBitSize / 8];
     Random.NextBytes(key);
     return(key);
 }
Пример #31
0
 public void GenerateBitsWithNullArgument()
 {
     using (var random = new SecureRandom())
     {
         random.NextBytes(null);
     }
 }
Пример #32
0
            internal RecipientInfo ToRecipientInfo(
                KeyParameter key,
                SecureRandom random)
            {
                byte[] keyBytes = key.GetKey();

                if (pubKey != null)
                {
                    IWrapper keyWrapper = Helper.CreateWrapper(keyEncAlg.ObjectID.Id);

                    keyWrapper.Init(true, new ParametersWithRandom(pubKey, random));

                    Asn1OctetString encKey = new DerOctetString(
                        keyWrapper.Wrap(keyBytes, 0, keyBytes.Length));

                    RecipientIdentifier recipId;
                    if (cert != null)
                    {
                        TbsCertificateStructure tbs = TbsCertificateStructure.GetInstance(
                            Asn1Object.FromByteArray(cert.GetTbsCertificate()));

                        Asn1.Cms.IssuerAndSerialNumber encSid = new Asn1.Cms.IssuerAndSerialNumber(
                            tbs.Issuer, tbs.SerialNumber.Value);

                        recipId = new RecipientIdentifier(encSid);
                    }
                    else
                    {
                        recipId = new RecipientIdentifier(subKeyId);
                    }

                    return(new RecipientInfo(new KeyTransRecipientInfo(recipId, keyEncAlg, encKey)));
                }
                else if (originator != null)
                {
                    IWrapper keyWrapper = Helper.CreateWrapper(
                        DerObjectIdentifier.GetInstance(
                            Asn1Sequence.GetInstance(keyEncAlg.Parameters)[0]).Id);

                    keyWrapper.Init(true, new ParametersWithRandom(secKey, random));

                    Asn1OctetString encKey = new DerOctetString(
                        keyWrapper.Wrap(keyBytes, 0, keyBytes.Length));

                    RecipientEncryptedKey rKey = new RecipientEncryptedKey(
                        new KeyAgreeRecipientIdentifier(
                            new Asn1.Cms.IssuerAndSerialNumber(
                                PrincipalUtilities.GetIssuerX509Principal(cert),
                                cert.SerialNumber)),
                        encKey);

                    return(new RecipientInfo(
                               new KeyAgreeRecipientInfo(originator, ukm, keyEncAlg, new DerSequence(rKey))));
                }
                else if (derivationAlg != null)
                {
                    string   rfc3211WrapperName = Helper.GetRfc3211WrapperName(secKeyAlgorithm);
                    IWrapper keyWrapper         = Helper.CreateWrapper(rfc3211WrapperName);


                    // Note: In Java build, the IV is automatically generated in JCE layer
                    int    ivLength = rfc3211WrapperName.StartsWith("DESEDE") ? 8 : 16;
                    byte[] iv       = new byte[ivLength];
                    random.NextBytes(iv);


                    ICipherParameters parameters = new ParametersWithIV(secKey, iv);
                    keyWrapper.Init(true, new ParametersWithRandom(parameters, random));

                    Asn1OctetString encKey = new DerOctetString(
                        keyWrapper.Wrap(keyBytes, 0, keyBytes.Length));

//					byte[] iv = keyWrapper.GetIV();

                    DerSequence seq = new DerSequence(
                        new DerObjectIdentifier(secKeyAlgorithm),
                        new DerOctetString(iv));

                    keyEncAlg = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdAlgPwriKek, seq);

                    return(new RecipientInfo(new PasswordRecipientInfo(derivationAlg, keyEncAlg, encKey)));
                }
                else
                {
                    IWrapper keyWrapper = Helper.CreateWrapper(keyEncAlg.ObjectID.Id);

                    keyWrapper.Init(true, new ParametersWithRandom(secKey, random));

                    Asn1OctetString encKey = new DerOctetString(
                        keyWrapper.Wrap(keyBytes, 0, keyBytes.Length));

                    return(new RecipientInfo(new KekRecipientInfo(secKeyId, keyEncAlg, encKey)));
                }
            }
Пример #33
0
        private static double MeasureChiSquared(SecureRandom random, int rounds)
        {
            byte[] opts = random.GenerateSeed(2);
            int[] counts = new int[256];

            byte[] bs = new byte[256];
            for (int i = 0; i < rounds; ++i)
            {
                random.NextBytes(bs);

                for (int b = 0; b < 256; ++b)
                {
                    ++counts[bs[b]];
                }
            }

            byte mask = opts[0];
            for (int i = 0; i < rounds; ++i)
            {
                random.NextBytes(bs);

                for (int b = 0; b < 256; ++b)
                {
                    ++counts[bs[b] ^ mask];
                }

                ++mask;
            }

            byte shift = opts[1];
            for (int i = 0; i < rounds; ++i)
            {
                random.NextBytes(bs);

                for (int b = 0; b < 256; ++b)
                {
                    ++counts[(byte)(bs[b] + shift)];
                }

                ++shift;
            }

            int total = 3 * rounds;

            double chi2 = 0;
            for (int k = 0; k < counts.Length; ++k)
            {
                double diff = ((double) counts[k]) - total;
                double diff2 = diff * diff;

                chi2 += diff2;
            }

            chi2 /= total;

            return chi2;
        }
Пример #34
0
        /**
         * which Generates the p and g values from the given parameters,
         * returning the DsaParameters object.
         * <p>
         * Note: can take a while...
         */
        public DsaParameters GenerateParameters()
        {
            byte[]     seed  = new byte[20];
            byte[]     part1 = new byte[20];
            byte[]     part2 = new byte[20];
            byte[]     u     = new byte[20];
            Sha1Digest sha1  = new Sha1Digest();
            int        n     = (size - 1) / 160;

            byte[] w = new byte[size / 8];

            BigInteger q = null, p = null, g = null;
            int        counter     = 0;
            bool       primesFound = false;

            while (!primesFound)
            {
                do
                {
                    random.NextBytes(seed);

                    sha1.BlockUpdate(seed, 0, seed.Length);

                    sha1.DoFinal(part1, 0);

                    Array.Copy(seed, 0, part2, 0, seed.Length);

                    Add(part2, seed, 1);

                    sha1.BlockUpdate(part2, 0, part2.Length);

                    sha1.DoFinal(part2, 0);

                    for (int i = 0; i != u.Length; i++)
                    {
                        u[i] = (byte)(part1[i] ^ part2[i]);
                    }

                    u[0]  |= (byte)0x80;
                    u[19] |= (byte)0x01;

                    q = new BigInteger(1, u);
                }while (!q.IsProbablePrime(certainty));

                counter = 0;

                int offset = 2;

                while (counter < 4096)
                {
                    for (int k = 0; k < n; k++)
                    {
                        Add(part1, seed, offset + k);
                        sha1.BlockUpdate(part1, 0, part1.Length);
                        sha1.DoFinal(part1, 0);
                        Array.Copy(part1, 0, w, w.Length - (k + 1) * part1.Length, part1.Length);
                    }

                    Add(part1, seed, offset + n);
                    sha1.BlockUpdate(part1, 0, part1.Length);
                    sha1.DoFinal(part1, 0);
                    Array.Copy(part1, part1.Length - ((w.Length - (n) * part1.Length)), w, 0, w.Length - n * part1.Length);

                    w[0] |= (byte)0x80;

                    BigInteger x = new BigInteger(1, w);

                    BigInteger c = x.Mod(q.ShiftLeft(1));

                    p = x.Subtract(c.Subtract(BigInteger.One));

                    if (p.TestBit(size - 1))
                    {
                        if (p.IsProbablePrime(certainty))
                        {
                            primesFound = true;
                            break;
                        }
                    }

                    counter += 1;
                    offset  += n + 1;
                }
            }

            //
            // calculate the generator g
            //
            BigInteger pMinusOneOverQ = p.Subtract(BigInteger.One).Divide(q);

            for (;;)
            {
                BigInteger h = new BigInteger(size, random);
                if (h.CompareTo(BigInteger.One) <= 0 || h.CompareTo(p.Subtract(BigInteger.One)) >= 0)
                {
                    continue;
                }

                g = h.ModPow(pMinusOneOverQ, p);
                if (g.CompareTo(BigInteger.One) <= 0)
                {
                    continue;
                }

                break;
            }

            return(new DsaParameters(p, q, g, new DsaValidationParameters(seed, counter)));
        }
Пример #35
0
        public void Save(
            Stream stream,
            char[]                      password,
            SecureRandom random)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }
            if (password == null)
            {
                throw new ArgumentNullException("password");
            }
            if (random == null)
            {
                throw new ArgumentNullException("random");
            }

            //
            // handle the key
            //
            Asn1EncodableVector keyS = new Asn1EncodableVector();

            foreach (string name in keys.Keys)
            {
                byte[] kSalt = new byte[SaltSize];
                random.NextBytes(kSalt);

                AsymmetricKeyEntry      privKey = (AsymmetricKeyEntry)keys[name];
                EncryptedPrivateKeyInfo kInfo   =
                    EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(
                        keyAlgorithm, password, kSalt, MinIterations, privKey.Key);

                Asn1EncodableVector kName = new Asn1EncodableVector();

                foreach (string oid in privKey.BagAttributeKeys)
                {
                    Asn1Encodable entry = privKey[oid];

                    // NB: Ignore any existing FriendlyName
                    if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id))
                    {
                        continue;
                    }

                    kName.Add(
                        new DerSequence(
                            new DerObjectIdentifier(oid),
                            new DerSet(entry)));
                }

                //
                // make sure we are using the local alias on store
                //
                // NB: We always set the FriendlyName based on 'name'
                //if (privKey[PkcsObjectIdentifiers.Pkcs9AtFriendlyName] == null)
                {
                    kName.Add(
                        new DerSequence(
                            PkcsObjectIdentifiers.Pkcs9AtFriendlyName,
                            new DerSet(new DerBmpString(name))));
                }

                //
                // make sure we have a local key-id
                //
                if (privKey[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] == null)
                {
                    X509CertificateEntry   ct           = GetCertificate(name);
                    AsymmetricKeyParameter pubKey       = ct.Certificate.GetPublicKey();
                    SubjectKeyIdentifier   subjectKeyID = CreateSubjectKeyID(pubKey);

                    kName.Add(
                        new DerSequence(
                            PkcsObjectIdentifiers.Pkcs9AtLocalKeyID,
                            new DerSet(subjectKeyID)));
                }

                SafeBag kBag = new SafeBag(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag, kInfo.ToAsn1Object(), new DerSet(kName));
                keyS.Add(kBag);
            }

            byte[] derEncodedBytes = new DerSequence(keyS).GetDerEncoded();

            BerOctetString keyString = new BerOctetString(derEncodedBytes);

            //
            // certificate processing
            //
            byte[] cSalt = new byte[SaltSize];

            random.NextBytes(cSalt);

            Asn1EncodableVector certSeq = new Asn1EncodableVector();
            Pkcs12PbeParams     cParams = new Pkcs12PbeParams(cSalt, MinIterations);
            AlgorithmIdentifier cAlgId  = new AlgorithmIdentifier(certAlgorithm, cParams.ToAsn1Object());
            ISet doneCerts = new HashSet();

            foreach (string name in keys.Keys)
            {
                X509CertificateEntry certEntry = GetCertificate(name);
                CertBag cBag = new CertBag(
                    PkcsObjectIdentifiers.X509Certificate,
                    new DerOctetString(certEntry.Certificate.GetEncoded()));

                Asn1EncodableVector fName = new Asn1EncodableVector();

                foreach (string oid in certEntry.BagAttributeKeys)
                {
                    Asn1Encodable entry = certEntry[oid];

                    // NB: Ignore any existing FriendlyName
                    if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id))
                    {
                        continue;
                    }

                    fName.Add(
                        new DerSequence(
                            new DerObjectIdentifier(oid),
                            new DerSet(entry)));
                }

                //
                // make sure we are using the local alias on store
                //
                // NB: We always set the FriendlyName based on 'name'
                //if (certEntry[PkcsObjectIdentifiers.Pkcs9AtFriendlyName] == null)
                {
                    fName.Add(
                        new DerSequence(
                            PkcsObjectIdentifiers.Pkcs9AtFriendlyName,
                            new DerSet(new DerBmpString(name))));
                }

                //
                // make sure we have a local key-id
                //
                if (certEntry[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] == null)
                {
                    AsymmetricKeyParameter pubKey       = certEntry.Certificate.GetPublicKey();
                    SubjectKeyIdentifier   subjectKeyID = CreateSubjectKeyID(pubKey);

                    fName.Add(
                        new DerSequence(
                            PkcsObjectIdentifiers.Pkcs9AtLocalKeyID,
                            new DerSet(subjectKeyID)));
                }

                SafeBag sBag = new SafeBag(
                    PkcsObjectIdentifiers.CertBag, cBag.ToAsn1Object(), new DerSet(fName));

                certSeq.Add(sBag);

                doneCerts.Add(certEntry.Certificate);
            }

            foreach (string certId in certs.Keys)
            {
                X509CertificateEntry cert = (X509CertificateEntry)certs[certId];

                if (keys[certId] != null)
                {
                    continue;
                }

                CertBag cBag = new CertBag(
                    PkcsObjectIdentifiers.X509Certificate,
                    new DerOctetString(cert.Certificate.GetEncoded()));

                Asn1EncodableVector fName = new Asn1EncodableVector();

                foreach (string oid in cert.BagAttributeKeys)
                {
                    // a certificate not immediately linked to a key doesn't require
                    // a localKeyID and will confuse some PKCS12 implementations.
                    //
                    // If we find one, we'll prune it out.
                    if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Id))
                    {
                        continue;
                    }

                    Asn1Encodable entry = cert[oid];

                    // NB: Ignore any existing FriendlyName
                    if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id))
                    {
                        continue;
                    }

                    fName.Add(
                        new DerSequence(
                            new DerObjectIdentifier(oid),
                            new DerSet(entry)));
                }

                //
                // make sure we are using the local alias on store
                //
                // NB: We always set the FriendlyName based on 'certId'
                //if (cert[PkcsObjectIdentifiers.Pkcs9AtFriendlyName] == null)
                {
                    fName.Add(
                        new DerSequence(
                            PkcsObjectIdentifiers.Pkcs9AtFriendlyName,
                            new DerSet(new DerBmpString(certId))));
                }

                SafeBag sBag = new SafeBag(PkcsObjectIdentifiers.CertBag,
                                           cBag.ToAsn1Object(), new DerSet(fName));

                certSeq.Add(sBag);

                doneCerts.Add(cert.Certificate);
            }

            foreach (CertId certId in chainCerts.Keys)
            {
                X509CertificateEntry cert = (X509CertificateEntry)chainCerts[certId];

                if (doneCerts.Contains(cert.Certificate))
                {
                    continue;
                }

                CertBag cBag = new CertBag(
                    PkcsObjectIdentifiers.X509Certificate,
                    new DerOctetString(cert.Certificate.GetEncoded()));

                Asn1EncodableVector fName = new Asn1EncodableVector();

                foreach (string oid in cert.BagAttributeKeys)
                {
                    // a certificate not immediately linked to a key doesn't require
                    // a localKeyID and will confuse some PKCS12 implementations.
                    //
                    // If we find one, we'll prune it out.
                    if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Id))
                    {
                        continue;
                    }

                    fName.Add(
                        new DerSequence(
                            new DerObjectIdentifier(oid),
                            new DerSet(cert[oid])));
                }

                SafeBag sBag = new SafeBag(PkcsObjectIdentifiers.CertBag, cBag.ToAsn1Object(), new DerSet(fName));

                certSeq.Add(sBag);
            }

            derEncodedBytes = new DerSequence(certSeq).GetDerEncoded();

            byte[] certBytes = CryptPbeData(true, cAlgId, password, false, derEncodedBytes);

            EncryptedData cInfo = new EncryptedData(PkcsObjectIdentifiers.Data, cAlgId, new BerOctetString(certBytes));

            ContentInfo[] info = new ContentInfo[]
            {
                new ContentInfo(PkcsObjectIdentifiers.Data, keyString),
                new ContentInfo(PkcsObjectIdentifiers.EncryptedData, cInfo.ToAsn1Object())
            };

            byte[] data = new AuthenticatedSafe(info).GetEncoded(
                useDerEncoding ? Asn1Encodable.Der : Asn1Encodable.Ber);

            ContentInfo mainInfo = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(data));

            //
            // create the mac
            //
            byte[] mSalt = new byte[20];
            random.NextBytes(mSalt);

            byte[] mac = CalculatePbeMac(OiwObjectIdentifiers.IdSha1,
                                         mSalt, MinIterations, password, false, data);

            AlgorithmIdentifier algId = new AlgorithmIdentifier(
                OiwObjectIdentifiers.IdSha1, DerNull.Instance);
            DigestInfo dInfo = new DigestInfo(algId, mac);

            MacData mData = new MacData(dInfo, mSalt, MinIterations);

            //
            // output the Pfx
            //
            Pfx pfx = new Pfx(mainInfo, mData);

            DerOutputStream derOut;

            if (useDerEncoding)
            {
                derOut = new DerOutputStream(stream);
            }
            else
            {
                derOut = new BerOutputStream(stream);
            }

            derOut.WriteObject(pfx);
        }
        /// <summary>
        /// Encryption constructor to create a new random key from an intermediate
        /// </summary>
        public Bip38KeyPair(Bip38Intermediate intermediate, bool retainPrivateKeyWhenPossible = false)
        {
            // generate seedb
            byte[]       seedb = new byte[24];
            SecureRandom sr    = new SecureRandom();

            sr.NextBytes(seedb);

            // get factorb as sha256(sha256(seedb))
            Sha256Digest sha256 = new Sha256Digest();

            sha256.BlockUpdate(seedb, 0, 24);
            factorb = new byte[32];
            sha256.DoFinal(factorb, 0);
            sha256.BlockUpdate(factorb, 0, 32);
            sha256.DoFinal(factorb, 0);

            // get ECPoint from passpoint
            PublicKey pk = new PublicKey(intermediate.passpoint);

            ECPoint generatedpoint = pk.GetECPoint().Multiply(new BigInteger(1, factorb));

            byte[]    generatedpointbytes = generatedpoint.GetEncoded();
            PublicKey generatedaddress    = new PublicKey(generatedpointbytes);

            // get addresshash
            UTF8Encoding utf8 = new UTF8Encoding(false);

            byte[] generatedaddressbytes = utf8.GetBytes(generatedaddress.AddressBase58);
            sha256.BlockUpdate(generatedaddressbytes, 0, generatedaddressbytes.Length);
            byte[] addresshashfull = new byte[32];
            sha256.DoFinal(addresshashfull, 0);
            sha256.BlockUpdate(addresshashfull, 0, 32);
            sha256.DoFinal(addresshashfull, 0);

            byte[] addresshashplusownerentropy = new byte[12];
            Array.Copy(addresshashfull, 0, addresshashplusownerentropy, 0, 4);
            Array.Copy(intermediate.ownerentropy, 0, addresshashplusownerentropy, 4, 8);

            // derive encryption key material
            derived = new byte[64];
            CryptSharp.Utility.SCrypt.ComputeKey(intermediate.passpoint, addresshashplusownerentropy, 1024, 1, 1, 1, derived);

            byte[] derivedhalf2 = new byte[32];
            Array.Copy(derived, 32, derivedhalf2, 0, 32);

            byte[] unencryptedpart1 = new byte[16];
            for (int i = 0; i < 16; i++)
            {
                unencryptedpart1[i] = (byte)(seedb[i] ^ derived[i]);
            }
            byte[] encryptedpart1 = new byte[16];

            // encrypt it
            var aes = Aes.Create();

            aes.KeySize = 256;
            aes.Mode    = CipherMode.ECB;
            aes.Key     = derivedhalf2;
            ICryptoTransform encryptor = aes.CreateEncryptor();

            encryptor.TransformBlock(unencryptedpart1, 0, 16, encryptedpart1, 0);
            encryptor.TransformBlock(unencryptedpart1, 0, 16, encryptedpart1, 0);

            byte[] unencryptedpart2 = new byte[16];
            for (int i = 0; i < 8; i++)
            {
                unencryptedpart2[i] = (byte)(encryptedpart1[i + 8] ^ derived[i + 16]);
            }
            for (int i = 0; i < 8; i++)
            {
                unencryptedpart2[i + 8] = (byte)(seedb[i + 16] ^ derived[i + 24]);
            }

            byte[] encryptedpart2 = new byte[16];
            encryptor.TransformBlock(unencryptedpart2, 0, 16, encryptedpart2, 0);
            encryptor.TransformBlock(unencryptedpart2, 0, 16, encryptedpart2, 0);

            byte[] result = new byte[39];
            result[0] = 0x01;
            result[1] = 0x43;
            result[2] = generatedaddress.IsCompressedPoint ? (byte)0x20 : (byte)0x00;
            if (intermediate.LotSequencePresent)
            {
                result[2] |= 0x04;
            }

            Array.Copy(addresshashfull, 0, result, 3, 4);
            Array.Copy(intermediate.ownerentropy, 0, result, 7, 8);
            Array.Copy(encryptedpart1, 0, result, 15, 8);
            Array.Copy(encryptedpart2, 0, result, 23, 16);

            _encryptedKey = Util.ByteArrayToBase58Check(result);
            _pubKey       = generatedaddress.PublicKeyBytes;
            _hash160      = generatedaddress.Hash160;

            var ps = Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetByName("secp256k1");

            if (retainPrivateKeyWhenPossible && intermediate.passfactor != null)
            {
                BigInteger privatekey = new BigInteger(1, intermediate.passfactor).Multiply(new BigInteger(1, factorb)).Mod(ps.N);
                _privKey = new KeyPair(privatekey).PrivateKeyBytes;
            }

            // create the confirmation code
            confirmationCodeInfo = new byte[51];
            // constant provides for prefix "cfrm38"
            confirmationCodeInfo[0] = 0x64;
            confirmationCodeInfo[1] = 0x3B;
            confirmationCodeInfo[2] = 0xF6;
            confirmationCodeInfo[3] = 0xA8;
            confirmationCodeInfo[4] = 0x9A;
            // fields for flagbyte, addresshash, and ownerentropy all copy verbatim
            Array.Copy(result, 2, confirmationCodeInfo, 5, 1 + 4 + 8);
        }