예제 #1
0
        byte[] PerformKeyAgreement(ECPoint other, int keyDataLength)
        {
            // Diffie-Hellman Primitives
            if (_params.D == null)
            {
                _params.CreateNewPrivateKey();
            }
            Number sharedSecretField = other.Multiply(_params.D).Export().X;

            byte[] sharedSecretValue = new byte[(_params.Domain.Bits >> 3) + ((_params.Domain.Bits & 7) == 0 ? 0 : 1)];
            sharedSecretField.CopyToBigEndian(sharedSecretValue, 0, sharedSecretValue.Length);

            // KDF
            if (_kdf == null)
            {
                return(sharedSecretValue);
            }
            _kdf.SharedInfo = _sharedInfo;
            return(_kdf.Calculate(sharedSecretValue, keyDataLength));
        }
예제 #2
0
        public byte[] PerformKeyAgreement(byte[] otherPublicKey1, byte[] otherPublicKey2, int keyDataLength)
        {
            ECPoint      otherQ1 = new ECPoint(_params.Domain.Group, otherPublicKey1);
            ECPoint      otherQ2 = new ECPoint(_params.Domain.Group, otherPublicKey2);
            IFiniteField ff      = _params.Domain.FieldN;

            // MQV Primitives
            if (_params.KeyPair1.D == null)
            {
                _params.KeyPair1.CreateNewPrivateKey();
            }
            if (_params.KeyPair2.D == null)
            {
                _params.KeyPair2.CreateNewPrivateKey();
            }
            if (_params.KeyPair2.Q == null)
            {
                _params.KeyPair2.CreatePublicKeyFromPrivateKey();
            }
            int logBits = _params.Domain.N.BitCount();

            logBits = (logBits >> 1) + ((logBits & 1) == 0 ? 0 : 1);
            Number  mod  = Number.One << logBits;
            Number  mask = mod - Number.One;
            Number  q2u  = (_params.KeyPair2.Q.Export().X & mask) + mod;
            Number  s    = ff.Add(_params.KeyPair2.D, ff.Multiply(q2u, _params.KeyPair1.D));
            Number  q2v  = (otherQ2.Export().X & mask) + mod;
            ECPoint P    = otherQ2.Add(otherQ1.Multiply(q2v)).Multiply(s * new Number(new uint[] { _params.Domain.H }));

            if (P.IsInifinity())
            {
                throw new CryptographicException();
            }
            int keyBytes = (int)((_params.Domain.Bits >> 3) + ((_params.Domain.Bits & 7) == 0 ? 0 : 1));

            byte[] sharedSecretValue = P.Export().X.ToByteArray(keyBytes, false);

            // KDF
            _kdf.SharedInfo = _sharedInfo;
            return(_kdf.Calculate(sharedSecretValue, keyDataLength));
        }
예제 #3
0
        public byte[] Encrypt(byte[] value, byte[] randomK)
#endif
        {
            int domainLen     = (int)((_domain.Bits >> 3) + ((_domain.Bits & 7) == 0 ? 0 : 1));
            int encBlockBytes = (_symmetricAlgo == null ? 0 : _symmetricAlgo.BlockSize >> 3);
            int encKeyLen     = (_symmetricAlgo == null ? value.Length : _symmetricAlgo.KeySize >> 3);
            int encPaddingLen = 0;
            int encTotalBytes = value.Length;
            int macKeyLen     = _mac.HashSize >> 3;

            byte[] result;
            int    ridx = 0;

            if (_params.D == null)
            {
                _params.CreateNewPrivateKey();
            }
            if (_params.Q == null)
            {
                _params.CreatePublicKeyFromPrivateKey();
            }
            if (_symmetricAlgo != null)
            {
                int mod  = value.Length % encBlockBytes;
                int rmod = encBlockBytes - mod;
                if (mod == 0)
                {
                    if (!(_symmetricAlgo.Padding == PaddingMode.None || _symmetricAlgo.Padding == PaddingMode.Zeros))
                    {
                        encPaddingLen = _symmetricAlgo.BlockSize >> 3;
                    }
                }
                else
                {
                    encPaddingLen = rmod;
                }
                encTotalBytes += encPaddingLen;
            }

            // Step.1
#if !TEST
            ECKeyPair pair = new ECKeyPair(null, null, _domain);
#else
            ECKeyPair pair = new ECKeyPair(new Number(randomK, false), null, _domain);
#endif

            // Step.2
            // TODO: 点圧縮を利用しないオプションを追加する
            byte[] R = pair.ExportPublicKey(true);
            result = new byte[R.Length + encTotalBytes + macKeyLen];
            for (int i = 0; i < R.Length; i++)
            {
                result[ridx++] = R[i];
            }

            // Step.3 & 4
            // TODO: Cofactor Diffie-Hellmanプリミティブを利用するオプションを追加する
            byte[] z = _params.Q.Multiply(pair.D).Export().X.ToByteArray(domainLen, false);

            // Step.5
            byte[] K = _kdf.Calculate(z, encKeyLen + macKeyLen);

            // Step.6
            byte[] MK = new byte[macKeyLen];
            for (int i = 0; i < MK.Length; i++)
            {
                MK[i] = K[K.Length - MK.Length + i];
            }

            // Step.7
            if (_symmetricAlgo == null)
            {
                for (int i = 0; i < value.Length; i++)
                {
                    result[ridx++] = (byte)(value[i] ^ K[i]);
                }
            }
            else
            {
                byte[] EK = new byte[encKeyLen];
                for (int i = 0; i < EK.Length; i++)
                {
                    EK[i] = K[i];
                }
                using (ICryptoTransform transform = _symmetricAlgo.CreateEncryptor(EK, new byte[encBlockBytes])) {
                    int i = 0;
                    for (; i < value.Length - encBlockBytes; i += encBlockBytes)
                    {
                        transform.TransformBlock(value, i, encBlockBytes, result, ridx + i);
                    }
                    byte[] padding = transform.TransformFinalBlock(value, i, value.Length - i);
                    Buffer.BlockCopy(padding, 0, result, ridx + i, padding.Length);
                    ridx += i + padding.Length;
                }
            }

            // Step.8
            // TODO: HMAC-SHA1-80への対応
            _mac.Key = MK;
            _mac.Initialize();
            _mac.TransformBlock(result, R.Length, encTotalBytes, null, 0);
            if (_sharedInfo == null)
            {
                _mac.TransformFinalBlock(result, 0, 0);
            }
            else
            {
                _mac.TransformFinalBlock(_sharedInfo, 0, _sharedInfo.Length);
            }
            _mac.Hash.CopyTo(result, ridx);

            return(result);
        }