예제 #1
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);
		}
예제 #2
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);
		}
예제 #3
0
		public byte[] Decrypt (byte[] value)
		{
			if (_params.Q == null) {
				if (_params.D == null)
					throw new CryptographicException ();
				_params.CreatePublicKeyFromPrivateKey ();
			}

			int domainLen = (int)((_domain.Bits >> 3) + ((_domain.Bits & 7) == 0 ? 0 : 1));
			int macKeyLen = _mac.HashSize >> 3;
			
			// Step.1
			if (value[0] != 2 && value[0] != 3 && value[0] != 4)
				throw new CryptographicException ();
			byte[] RBytes = new byte[domainLen + 1];
			byte[] EM = new byte[value.Length - RBytes.Length - macKeyLen];
			byte[] D = new byte[macKeyLen];
			if (value.Length != RBytes.Length + EM.Length + D.Length)
				throw new CryptographicException ();
			Array.Copy (value, 0, RBytes, 0, RBytes.Length);
			Array.Copy (value, RBytes.Length, EM, 0, EM.Length);
			Array.Copy (value, RBytes.Length + EM.Length, D, 0, D.Length);
			int encKeyLen = (_symmetricAlgo == null ? EM.Length : _symmetricAlgo.KeySize >> 3);;

			// Step.2
			ECPoint R = new ECPoint (_domain.Group, RBytes);

			// Step.3
			// TODO: Step.3

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

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

			// Step.7
			byte[] EK = null;
			if (_symmetricAlgo != null) {
				EK = new byte[encKeyLen];
				for (int i = 0; i < EK.Length; i ++)
					EK[i] = K[i];
			}
			byte[] MK = new byte[macKeyLen];
			for (int i = 0; i < MK.Length; i++)
				MK[i] = K[K.Length - MK.Length + i];

			// Step.8
			// TODO: HMAC-SHA1-80への対応
			_mac.Key = MK;
			_mac.Initialize ();
			_mac.TransformBlock (EM, 0, EM.Length, null, 0);
			if (_sharedInfo == null)
				_mac.TransformFinalBlock (EM, 0, 0);
			else
				_mac.TransformFinalBlock (_sharedInfo, 0, _sharedInfo.Length);
			byte[] hash = _mac.Hash;
			for (int i = 0; i < hash.Length; i ++)
				if (hash[i] != D[i])
					throw new CryptographicException ();

			// Step.9
			byte[] result = new byte[EM.Length];
			if (_symmetricAlgo == null) {
				for (int i = 0; i < result.Length; i ++)
					result[i] = (byte)(EM[i] ^ K[i]);
			} else {
				int blockBytes = _symmetricAlgo.BlockSize >> 3;
				using (ICryptoTransform transform = _symmetricAlgo.CreateDecryptor (EK, new byte[blockBytes])) {
					int i = 0;
					for (; i < result.Length - blockBytes; i += blockBytes)
						transform.TransformBlock (EM, i, blockBytes, result, i);
					byte[] temp = transform.TransformFinalBlock (EM, i, EM.Length - i);
					Buffer.BlockCopy (temp, 0, result, i, temp.Length);
					if (temp.Length != blockBytes)
						Array.Resize<byte> (ref result, i + temp.Length);
				}
			}
			return result;
		}