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)); }
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)); }
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); }