protected virtual byte[] CalculateECDHBasicAgreement(ECPublicKeyParameters publicKey, ECPrivateKeyParameters privateKey) { ECDHBasicAgreement basicAgreement = new ECDHBasicAgreement(); basicAgreement.Init(privateKey); BigInteger agreement = basicAgreement.CalculateAgreement(publicKey); return(BigIntegers.AsUnsignedByteArray(agreement)); }
/// <summary> /// Creates symmetric key from sender's public key and own key pair /// </summary> /// <param name="publicKeyBytes"></param> /// <returns></returns> protected byte[] GetSymmetricKey(byte[] publicKeyBytes) { ECPublicKeyParameters publicKey = new ECPublicKeyParameters(X9.Curve.DecodePoint(publicKeyBytes), EcSpec); var agree = new ECDHBasicAgreement(); agree.Init(KeyPair.Private); BigInteger z = agree.CalculateAgreement((AsymmetricKeyParameter)publicKey); return(BigIntegers.AsUnsignedByteArray(agree.GetFieldSize(), z)); }
public static byte[] Agree(PrivateKey privateKey, PublicKey publicKey) { ECPrivateKeyParameters privateKeyParameters = WrapPrivateKey(privateKey); ECPublicKeyParameters publicKeyParameters = WrapPublicKey(publicKey); ECDHBasicAgreement agreement = new ECDHBasicAgreement(); agreement.Init(privateKeyParameters); byte[] agreementBytes = agreement.CalculateAgreement(publicKeyParameters).ToByteArray(); return(agreementBytes.Length > 32 ? agreementBytes.Slice(agreementBytes.Length - 32, 32) : agreementBytes.PadLeft(32)); }
public static byte[] GetSharedSecret(AsymmetricCipherKeyPair localKeyWithPrivate, byte[] remotePublicKeyDerEncoded) { var remotePublicKey = PublicKeyFactory.CreateKey(remotePublicKeyDerEncoded); var agreement = new ECDHBasicAgreement(); agreement.Init(localKeyWithPrivate.Private); using (var sha = SHA256.Create()) { // CalculateAgreement returns a BigInteger, whose length is variable, and bits are not whitened. // So hash it. return(sha.ComputeHash(agreement.CalculateAgreement(remotePublicKey).ToByteArray())); } }
/// <summary> /// Derives a shared secret key from a private key and another persons public key /// </summary> /// <param name="myPrivateKey">the private key which is used</param> /// <param name="otherPartyPublicKey">the public key of the other person</param> /// <returns></returns> public byte[] DeriveKey(byte[] myPrivateKey, byte[] otherPartyPublicKey) { ECPrivateKeyParameters privKey = null; try { privKey = (ECPrivateKeyParameters)CreateAsymmetricKeyParameterFromPrivateKeyInfo(myPrivateKey); } catch (InvalidCastException exception) { string message = "Private Key Import Failed!\n" + $"{exception.Message}.\n" + "The contents of the source do not represent a valid EC key parameter\n" + "Verify that the key is not corrupted.\n" + "- or - Verify that the correct key is selected."; throw new CryptoException(message, exception); } var a1 = new ECDHBasicAgreement(); a1.Init(privKey); ECPublicKeyParameters pubKey = null; try { pubKey = (ECPublicKeyParameters)CreateAsymmetricKeyParameterFromPublicKeyInfo(otherPartyPublicKey); } catch (InvalidCastException exception) { string message = "Public Key Import Failed!\n" + $"{exception.Message}.\n" + "The contents of the source do not represent a valid EC key parameter\n" + "Verify that the key is not corrupted.\n" + "- or - Verify that the correct key is selected."; throw new CryptoException(message, exception); } BigInteger k = null; try { k = a1.CalculateAgreement(pubKey); } catch (InvalidOperationException exception) { string message = "Key Deriviation Failed!\n" + $"{exception.Message}.\n" + "Different EC curves were used to create the public keys."; throw new CryptoException(message, exception); } return(k.ToByteArrayUnsigned()); }
public string GenerateSharedSecretHex(string pubKeyHex) { var pubKeyBytes = pubKeyHex.HexToByteArray(); var q = _curve.Curve.DecodePoint(pubKeyBytes); var remotePublicKey = new ECPublicKeyParameters("ECDH", q, _domain); var agreement = new ECDHBasicAgreement(); agreement.Init(_key.Private); var basicAgreementResult = agreement.CalculateAgreement(remotePublicKey); return(BigIntegers.AsUnsignedByteArray(agreement.GetFieldSize(), basicAgreementResult).ToHex(true)); }
public byte[] Old() { ECPrivateKeyParameters privateKeyParameters = BouncyCrypto.WrapPrivateKey(privateKey); ECPublicKeyParameters publicKeyParameters = BouncyCrypto.WrapPublicKey(ephemeral); IBasicAgreement agreement = new ECDHBasicAgreement(); agreement.Init(privateKeyParameters); BigInteger zAsInteger = agreement.CalculateAgreement(publicKeyParameters); byte[] bytes = BigIntegers.AsUnsignedByteArray(32, zAsInteger); return(bytes); }
BigInteger ECDHAgree(byte[] publicKey, byte[] privateKey) { var domain = SecNamedCurves.GetByName("secp160r1"); ECDHBasicAgreement agreement = new ECDHBasicAgreement(); BigInteger privKeyInt = new BigInteger(privateKey); ECDomainParameters parm = new ECDomainParameters(domain.Curve, domain.G, domain.N); ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(privKeyInt, parm); agreement.Init(privKey); var pt = Key.Curve.Curve.DecodePoint(publicKey); ECPublicKeyParameters pubParams = new ECPublicKeyParameters(pt, parm); return(agreement.CalculateAgreement(pubParams)); }
public static byte[] CalculateECDHBasicAgreement(ECPublicKeyParameters publicKey, ECPrivateKeyParameters privateKey) { ECDHBasicAgreement basicAgreement = new ECDHBasicAgreement(); basicAgreement.Init(privateKey); BigInteger agreementValue = basicAgreement.CalculateAgreement(publicKey); /* * RFC 4492 5.10. Note that this octet string (Z in IEEE 1363 terminology) as output by * FE2OSP, the Field Element to Octet String Conversion Primitive, has constant length for * any given field; leading zeros found in this octet string MUST NOT be truncated. */ return(BigIntegers.AsUnsignedByteArray(basicAgreement.GetFieldSize(), agreementValue)); }
internal static byte[] ComputeSharedSecret(ECPrivateKeyParameters privateKey, ECPublicKeyParameters publicKey) { if (!KeyParser.ValidateCurve(privateKey)) { throw new ArgumentException("Private key not on NIST P-256 curve", "privateKey"); } if (!KeyParser.ValidateCurve(publicKey)) { throw new ArgumentException("Public key not on NIST P-256 curve", "publicKey"); } var ecdhAgreement = new ECDHBasicAgreement(); ecdhAgreement.Init(privateKey); BigInteger secret = ecdhAgreement.CalculateAgreement(publicKey); return(BigIntegers.AsUnsignedByteArray(SharedSecretSize, secret)); }
public static byte[] GenerateSharedSecret(ECPublicKeyParameters publicKey, ECPrivateKeyParameters privateKey) { var agreement = new ECDHBasicAgreement(); agreement.Init(privateKey); var z = agreement.CalculateAgreement(publicKey); var sharedSecret = new byte[32]; var zArr = z.ToByteArrayUnsigned(); // zero the output array for (var i = 0; i < sharedSecret.Length; i++) { sharedSecret[i] = 0; } Array.Copy(zArr, 0, sharedSecret, 32 - zArr.Length, zArr.Length); return(sharedSecret); }
/// <summary> /// Called by client to get his ephemaral ECC keys /// TODO: get information about which ECC curve should be used /// </summary> /// <param name="version"></param> /// <param name="data"></param> /// <returns></returns> public override byte[] ProcessServerKeys(ProtocolVersion version, byte[] data, X509Certificate serverCertificate) { if (data == null) { throw new ArgumentNullException(nameof(data)); } if (data.Length < 4) { throw new ArgumentException(nameof(data)); } //if (data[0] != 3 || data[1] != 0 || data[2] != 23) if (data[0] != 3 || data[1] != 0) { throw new ArgumentException(nameof(data)); } //if (data[3] != 65 || data[4] > data.Length - 4) if (data[4] > data.Length - 4) { throw new ArgumentException(nameof(data)); } // Extract the public key from the data byte[] ecPointData = new byte[data[3]]; Buffer.BlockCopy(data, 4, ecPointData, 0, ecPointData.Length); ushort curveNameId = (ushort)(data[1] << 8 | data[2]); var ecPoint = this.ObtainCurveNameAndPoint(curveNameId, ecPointData); var theirPublicKey = new ECPublicKeyParameters(ecPoint, this.domainParameters); // Calculate the actual agreement var agreement = new ECDHBasicAgreement(); agreement.Init(this.privateKey); this.preMasterSecret = BigIntegerToByteArray(agreement.CalculateAgreement(theirPublicKey), ecPoint.Curve.FieldSize / 8); var signature = new byte[data.Length - 4 - data[3]]; Buffer.BlockCopy(data, 4 + data[3], signature, 0, signature.Length); return(signature); }
static byte[] GenerateAESKey(ECPublicKeyParameters bobPublicKey, AsymmetricKeyParameter alicePrivateKey) { ECDHBasicAgreement aKeyAgree = new ECDHBasicAgreement(); aKeyAgree.Init(alicePrivateKey); byte[] sharedSecret = aKeyAgree.CalculateAgreement(bobPublicKey).ToByteArray(); // make sure each part has the correct and same size ResizeRight(ref sharedSecret, 66); // 66 is the desired key size Sha256Digest digest = new Sha256Digest(); byte[] symmetricKey = new byte[digest.GetDigestSize()]; digest.BlockUpdate(sharedSecret, 0, sharedSecret.Length); digest.DoFinal(symmetricKey, 0); return(symmetricKey); }
public static byte[] AsymmetricDecrypt(byte[] data, ref AsymmetricCipherKeyPair keypair) { //create the key agreement ECDHBasicAgreement ag = new ECDHBasicAgreement(); ag.Init(keypair.Private); //calculate the shared secret key BigInteger a = ag.CalculateAgreement(keypair.Public); byte[] secret = a.ToByteArray(); //derive the symmetric encryption key ECDHKekGenerator topkek = new ECDHKekGenerator(DigestUtilities.GetDigest("SHA256")); topkek.Init(new DHKdfParameters(NistObjectIdentifiers.Aes, secret.Length, secret)); byte[] symKey = new byte[DigestUtilities.GetDigest("SHA256").GetDigestSize()]; topkek.GenerateBytes(symKey, 0, symKey.Length); //decrypt the data KeyParameter parm = ParameterUtilities.CreateKeyParameter("DES", symKey); IBufferedCipher cipher = CipherUtilities.GetCipher("DES/ECB/ISO7816_4PADDING"); cipher.Init(false, parm); byte[] ret = null; try { ret = cipher.DoFinal(data); } catch (Exception e) { if (e != null) { return(null); } } //erase the keys Eraser.SecureErase(secret); Eraser.SecureErase(symKey); return(ret); }
public static EncryptionResult EncryptMessage(byte[] userKey, byte[] userSecret, byte[] data, ushort padding = 0, bool randomisePadding = false) { var Random = new SecureRandom(); var Salt = new byte[16]; Random.NextBytes(Salt); var Curve = ECNamedCurveTable.GetByName("prime256v1"); var Spec = new ECDomainParameters(Curve.Curve, Curve.G, Curve.N, Curve.H, Curve.GetSeed()); var Generator = new ECKeyPairGenerator(); Generator.Init(new ECKeyGenerationParameters(Spec, new SecureRandom())); var KeyPair = Generator.GenerateKeyPair(); var AgreementGenerator = new ECDHBasicAgreement(); AgreementGenerator.Init(KeyPair.Private); var IKM = AgreementGenerator.CalculateAgreement(new ECPublicKeyParameters(Spec.Curve.DecodePoint(userKey), Spec)); var PRK = GenerateHKDF(userSecret, IKM.ToByteArrayUnsigned(), Encoding.UTF8.GetBytes("Content-Encoding: auth\0"), 32); var PublicKey = ((ECPublicKeyParameters)KeyPair.Public).Q.GetEncoded(false); var CEK = GenerateHKDF(Salt, PRK, CreateInfoChunk("aesgcm", userKey, PublicKey), 16); var Nonce = GenerateHKDF(Salt, PRK, CreateInfoChunk("nonce", userKey, PublicKey), 12); if (randomisePadding && padding > 0) { padding = Convert.ToUInt16(Math.Abs(Random.NextInt()) % (padding + 1)); } var Input = new byte[padding + 2 + data.Length]; Buffer.BlockCopy(ConvertInt(padding), 0, Input, 0, 2); Buffer.BlockCopy(data, 0, Input, padding + 2, data.Length); var Cipher = CipherUtilities.GetCipher("AES/GCM/NoPadding"); Cipher.Init(true, new AeadParameters(new KeyParameter(CEK), 128, Nonce)); var Message = new byte[Cipher.GetOutputSize(Input.Length)]; Cipher.DoFinal(Input, 0, Input.Length, Message, 0); return(new EncryptionResult { Salt = Salt, Payload = Message, PublicKey = PublicKey }); }
public virtual Task <byte[]> SharedSecret(ECDSAPublicKey Pbk) { return(Task.Run(() => { lock (Cache) { var clipped = Pbk.FingerprintEncodedClipped; if (Cache.ContainsKey(clipped)) { return Cache[clipped]; } } var agree = new ECDHBasicAgreement(); agree.Init(PrivateKey); var result = agree.CalculateAgreement(Pbk.PublicKey).ToByteArrayUnsigned(); result = CryptoHelper.Sha256(result); lock (Cache) Cache[Pbk.FingerprintEncodedClipped] = result; return result; })); }
public static byte[] GetSharedSecret(byte[] localPrivateKeyBytes, byte[] remotePublicKeyBytes) { var curve = NistNamedCurves.GetByName("P-256"); var dom = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H); ECKeyParameters privateKeyParameters = new ECPrivateKeyParameters(new BigInteger(1, localPrivateKeyBytes), dom); var q = curve.Curve.DecodePoint(new byte[] { 0x04 }.Concat(remotePublicKeyBytes).ToArray()); ECKeyParameters publicKeyParameters = new ECPublicKeyParameters(q, dom); var agreement = new ECDHBasicAgreement(); agreement.Init(privateKeyParameters); using (var sha = SHA256.Create()) { // CalculateAgreement returns a BigInteger, whose length is variable, and bits are not whitened, so hash it. var temp = agreement.CalculateAgreement(publicKeyParameters).ToByteArray(); return(sha.ComputeHash(temp)); } }
public override void ProcessClientKeys(ProtocolVersion version, ProtocolVersion clientVersion, CertificatePrivateKey privateKey, byte[] data) { if (data == null) { throw new ArgumentNullException("data"); } if (data.Length < 1) { throw new ArgumentException("data"); } byte[] ecPointData = new byte[data[0]]; Buffer.BlockCopy(data, 1, ecPointData, 0, ecPointData.Length); ECPoint ecPoint = _domainParameters.Curve.DecodePoint(ecPointData); ECPublicKeyParameters theirPublicKey = new ECPublicKeyParameters(ecPoint, _domainParameters); // Calculate the actual agreement ECDHBasicAgreement agreement = new ECDHBasicAgreement(); agreement.Init(_privateKey); _preMasterSecret = BigIntegerToByteArray(agreement.CalculateAgreement(theirPublicKey), 32); }
private static EncryptionResult EncryptMessage(byte[] userKey, byte[] userSecret, byte[] data, ushort padding = 0, bool randomisePadding = false) { SecureRandom random = new SecureRandom(); byte[] salt = new byte[16]; random.NextBytes(salt); X9ECParameters curve = ECNamedCurveTable.GetByName("prime256v1"); ECDomainParameters spec = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H, curve.GetSeed()); ECKeyPairGenerator generator = new ECKeyPairGenerator(); generator.Init(new ECKeyGenerationParameters(spec, new SecureRandom())); AsymmetricCipherKeyPair keyPair = generator.GenerateKeyPair(); ECDHBasicAgreement agreementGenerator = new ECDHBasicAgreement(); agreementGenerator.Init(keyPair.Private); BigInteger ikm = agreementGenerator.CalculateAgreement(new ECPublicKeyParameters(spec.Curve.DecodePoint(userKey), spec)); byte[] prk = GenerateHkdf(userSecret, ikm.ToByteArrayUnsigned(), Encoding.UTF8.GetBytes("Content-Encoding: auth\0"), 32); byte[] publicKey = ((ECPublicKeyParameters)keyPair.Public).Q.GetEncoded(false); byte[] cek = GenerateHkdf(salt, prk, CreateInfoChunk("aesgcm", userKey, publicKey), 16); byte[] nonce = GenerateHkdf(salt, prk, CreateInfoChunk("nonce", userKey, publicKey), 12); if (randomisePadding && padding > 0) { padding = Convert.ToUInt16(Math.Abs(random.NextInt()) % (padding + 1)); } byte[] input = new byte[padding + 2 + data.Length]; Buffer.BlockCopy(ConvertInt(padding), 0, input, 0, 2); Buffer.BlockCopy(data, 0, input, padding + 2, data.Length); IBufferedCipher cipher = CipherUtilities.GetCipher("AES/GCM/NoPadding"); cipher.Init(true, new AeadParameters(new KeyParameter(cek), 128, nonce)); byte[] message = new byte[cipher.GetOutputSize(input.Length)]; cipher.DoFinal(input, 0, input.Length, message, 0); return(new EncryptionResult() { Salt = salt, Payload = message, PublicKey = publicKey }); }
private (byte[], byte[]) ExtractSecretAndContext(ECPublicKeyParameters senderPublicKey, ECPublicKeyParameters receiverPublicKey, ECPrivateKeyParameters receiverPrivateKey) { IBasicAgreement aKeyAgree = new ECDHBasicAgreement(); aKeyAgree.Init(receiverPrivateKey); byte[] sharedSecret = aKeyAgree.CalculateAgreement(senderPublicKey).ToByteArrayUnsigned(); byte[] receiverKeyBytes = AddLengthPrefix(receiverPublicKey.Q.GetEncoded()); byte[] senderPublicKeyBytes = AddLengthPrefix(senderPublicKey.Q.GetEncoded()); byte[] context = new byte[keyLabel.Length + 1 + receiverKeyBytes.Length + senderPublicKeyBytes.Length]; int destinationOffset = 0; Array.Copy(keyLabel, 0, context, destinationOffset, keyLabel.Length); destinationOffset += keyLabel.Length + 1; Array.Copy(receiverKeyBytes, 0, context, destinationOffset, receiverKeyBytes.Length); destinationOffset += receiverKeyBytes.Length; Array.Copy(senderPublicKeyBytes, 0, context, destinationOffset, senderPublicKeyBytes.Length); return(sharedSecret, context); }
public new void InitiateEncryption(byte[] serverKey, byte[] randomKeyToken) { try { ECPublicKeyParameters remotePublicKey = (ECPublicKeyParameters) PublicKeyFactory.CreateKey(serverKey); ECDHBasicAgreement agreement = new ECDHBasicAgreement(); agreement.Init(Session.CryptoContext.ClientKey.Private); byte[] secret; using (var sha = SHA256.Create()) { secret = sha.ComputeHash(randomKeyToken.Concat(agreement.CalculateAgreement(remotePublicKey).ToByteArrayUnsigned()).ToArray()); } // Create a decrytor to perform the stream transform. IBufferedCipher decryptor = CipherUtilities.GetCipher("AES/CFB8/NoPadding"); decryptor.Init(false, new ParametersWithIV(new KeyParameter(secret), secret.Take(16).ToArray())); IBufferedCipher encryptor = CipherUtilities.GetCipher("AES/CFB8/NoPadding"); encryptor.Init(true, new ParametersWithIV(new KeyParameter(secret), secret.Take(16).ToArray())); Session.CryptoContext = new CryptoContext { Decryptor = decryptor, Encryptor = encryptor, UseEncryption = true, Key = secret }; Thread.Sleep(1250); McpeClientToServerHandshake magic = new McpeClientToServerHandshake(); SendPacket(magic); } catch (Exception e) { Log.Error("Initiate encryption", e); } }
public override string ComputeSharedSecret(string otherKey, bool isBase64 = true) { byte[] blob = (isBase64 ? Convert.FromBase64String(otherKey) : Encoding.UTF8.GetBytes(otherKey)); // the shared secret is the x-coordinate of a point on the EC. the point // is calculated by multiplying the remote entity's public key (which itself is // a point on the curve) by our private key (an integer value). // the following calculation follows the code example here: // https://stackoverflow.com/questions/15430784/ PrivateKeyInfo info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(_keyPair.Private); ECPrivateKeyParameters priv = (ECPrivateKeyParameters)PrivateKeyFactory.CreateKey(info); ECPoint point = priv.Parameters.Curve.DecodePoint(blob); ECPublicKeyParameters pub = new ECPublicKeyParameters(point, priv.Parameters); IBasicAgreement agree = new ECDHBasicAgreement(); agree.Init(priv); BigInteger value = agree.CalculateAgreement(pub); SharedSecret = Convert.ToBase64String(value.ToByteArrayUnsigned()); return(SharedSecret); }
public override byte[] ProcessServerKeys(ProtocolVersion version, byte[] data) { if (data == null) { throw new ArgumentNullException("data"); } if (data.Length < 4) { throw new ArgumentException("data"); } if (data[0] != 3 || data[1] != 0 || data[2] != 23) { throw new ArgumentException("data"); } if (data[3] != 65 || data[4] > data.Length - 4) { throw new ArgumentException("data"); } // Generate our private key GenerateKeys("secp256r1"); // Extract the public key from the data byte[] ecPointData = new byte[data[3]]; Buffer.BlockCopy(data, 4, ecPointData, 0, ecPointData.Length); ECPoint ecPoint = _domainParameters.Curve.DecodePoint(ecPointData); ECPublicKeyParameters theirPublicKey = new ECPublicKeyParameters(ecPoint, _domainParameters); // Calculate the actual agreement ECDHBasicAgreement agreement = new ECDHBasicAgreement(); agreement.Init(_privateKey); _preMasterSecret = BigIntegerToByteArray(agreement.CalculateAgreement(theirPublicKey), 32); byte[] signature = new byte[data.Length - 4 - data[3]]; Buffer.BlockCopy(data, 4 + data[3], signature, 0, signature.Length); return(signature); }
public byte[] DeriveKey(ArraySegment <byte> otherPublicKey) { if (_pk == null) { throw new ObjectDisposedException(nameof(KeyAgreement)); } if (otherPublicKey == null) { throw new ArgumentNullException(nameof(otherPublicKey)); } if (otherPublicKey.Count != 32) { throw new ArgumentException("The other public key needs to be compressed with the first byte omitted. Only even public keys are accepted"); } var pubk = DecodePublicKey(otherPublicKey); var ecdh = new ECDHBasicAgreement(); ecdh.Init(_pk); var key = ecdh.CalculateAgreement(pubk); var keyBytes = key.ToByteArray(); if (keyBytes.Length != 32) { byte[] output = new byte[32]; int l = keyBytes.Length; int o = Math.Max(0, l - 32); int t = Math.Min(32, l); int w = 32 - t; Array.Copy(keyBytes, o, output, w, t); keyBytes = output; } return(keyBytes); }
public static EphemeralKeyPair Generate(string curveName) { var ecp = CustomNamedCurves.GetByName(curveName); var ecs = new ECDomainParameters(ecp.Curve, ecp.G, ecp.N, ecp.H, ecp.GetSeed()); var g = new ECKeyPairGenerator(); g.Init(new ECKeyGenerationParameters(ecs, new SecureRandom())); var pair = g.GenerateKeyPair(); var agree = new ECDHBasicAgreement(); agree.Init(pair.Private); var pubkey = MarshalCurvePoint(((ECPublicKeyParameters)pair.Public).Q); var done = new GenerateSharedKeyDelegate(theirPub => { var point = UnmarshalCurvePoint(ecp.Curve, theirPub); var key = new ECPublicKeyParameters(point, ecs); return(agree.CalculateAgreement(key).ToByteArray()); }); return(new EphemeralKeyPair(pubkey, done)); }
private byte[] ECDH_GenerateSecret(JWK key, EncryptMessage msg) { JWK epk; if ((key.AsString("kty") != "EC") && (key.AsString("kty") != "OKP")) { throw new JoseException("Not an EC or OKP Key"); } if (_mSenderKey != null) { epk = _mSenderKey; } else { CBORObject epkT = FindAttr("epk", msg); if (epkT == null) { throw new JoseException("No Ephemeral key"); } epk = new JWK(epkT); } if (epk.AsString("crv") != key.AsString("crv")) { throw new JoseException("not a match of curves"); } if (key.AsString("kty") == "EC") { // Get the curve X9ECParameters p = NistNamedCurves.GetByName(key.AsString("crv")); ECDomainParameters parameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H); Org.BouncyCastle.Math.EC.ECPoint pubPoint = p.Curve.CreatePoint(epk.AsBigInteger("x"), epk.AsBigInteger("y")); ECPublicKeyParameters pub = new ECPublicKeyParameters(pubPoint, parameters); ECPrivateKeyParameters priv = new ECPrivateKeyParameters(key.AsBigInteger("d"), parameters); IBasicAgreement e1 = new ECDHBasicAgreement(); e1.Init(priv); BigInteger k1 = e1.CalculateAgreement(pub); return(k1.ToByteArrayUnsigned()); } else { switch (epk.AsString("crv")) { case "X25519": { X25519PublicKeyParameters pub = new X25519PublicKeyParameters(epk.AsBytes("x"), 0); X25519PrivateKeyParameters priv = new X25519PrivateKeyParameters(key.AsBytes("d"), 0); X25519Agreement agree = new X25519Agreement(); agree.Init(priv); byte[] secret = new byte[32]; agree.CalculateAgreement(pub, secret, 0); return(secret); } default: throw new JoseException("Unsupported curve"); } } }
protected void DecodeCertMono(McpeLogin message) { byte[] buffer = message.payload; if (message.payload.Length != buffer.Length) { Log.Debug($"Wrong lenght {message.payload.Length} != {message.payload.Length}"); throw new Exception($"Wrong lenght {message.payload.Length} != {message.payload.Length}"); } if (Log.IsDebugEnabled) { Log.Debug("Lenght: " + message.payload.Length + ", Message: " + buffer.EncodeBase64()); } string certificateChain; string skinData; try { var destination = new MemoryStream(buffer); destination.Position = 0; NbtBinaryReader reader = new NbtBinaryReader(destination, false); var countCertData = reader.ReadInt32(); certificateChain = Encoding.UTF8.GetString(reader.ReadBytes(countCertData)); if (Log.IsDebugEnabled) { Log.Debug($"Certificate Chain (Lenght={countCertData})\n{certificateChain}"); } var countSkinData = reader.ReadInt32(); skinData = Encoding.UTF8.GetString(reader.ReadBytes(countSkinData)); if (Log.IsDebugEnabled) { Log.Debug($"Skin data (Lenght={countSkinData})\n{skinData}"); } } catch (Exception e) { Log.Error("Parsing login", e); return; } try { { IDictionary <string, dynamic> headers = JWT.Headers(skinData); dynamic payload = JObject.Parse(JWT.Payload(skinData)); if (Log.IsDebugEnabled) { Log.Debug($"Skin JWT Header: {string.Join(";", headers)}"); } if (Log.IsDebugEnabled) { Log.Debug($"Skin JWT Payload:\n{payload.ToString()}"); } try { _playerInfo.ClientId = payload.ClientRandomId; _playerInfo.CurrentInputMode = payload.CurrentInputMode; _playerInfo.DefaultInputMode = payload.DefaultInputMode; _playerInfo.DeviceModel = payload.DeviceModel; _playerInfo.DeviceOS = payload.DeviceOS; _playerInfo.GameVersion = payload.GameVersion; _playerInfo.GuiScale = payload.GuiScale; _playerInfo.LanguageCode = payload.LanguageCode; _playerInfo.ServerAddress = payload.ServerAddress; _playerInfo.UIProfile = payload.UIProfile; _playerInfo.Skin = new Skin() { CapeData = Convert.FromBase64String((string)payload.CapeData), SkinId = payload.SkinId, SkinData = Convert.FromBase64String((string)payload.SkinData), SkinGeometryName = payload.SkinGeometryName, SkinGeometry = Encoding.UTF8.GetString(Convert.FromBase64String((string)payload.SkinGeometry)), }; Log.Warn($"Cape data lenght={_playerInfo.Skin.CapeData.Length}"); } catch (Exception e) { Log.Error("Parsing skin data", e); } } //var chainArray = chain.ToArray(); string validationKey = null; string identityPublicKey = null; //if (!isMono) { dynamic json = JObject.Parse(certificateChain); if (Log.IsDebugEnabled) { Log.Debug($"Certificate JSON:\n{json}"); } JArray chain = json.chain; foreach (JToken token in chain) { IDictionary <string, dynamic> headers = JWT.Headers(token.ToString()); if (Log.IsDebugEnabled) { Log.Debug("Raw chain element:\n" + token.ToString()); Log.Debug($"JWT Header: {string.Join(";", headers)}"); dynamic jsonPayload = JObject.Parse(JWT.Payload(token.ToString())); Log.Debug($"JWT Payload:\n{jsonPayload}"); } // Mojang root x5u cert (string): MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8ELkixyLcwlZryUQcu1TvPOmI2B7vX83ndnWRUaXm74wFfa5f/lwQNTfrLVHa2PmenpGI6JhIMUJaWZrjmMj90NoKNFSNBuKdm8rYiXsfaz3K36x/1U26HpG0ZxK/V1V if (!headers.ContainsKey("x5u")) { continue; } string x5u = headers["x5u"]; if (identityPublicKey == null) { if (CertificateData.MojangRootKey.Equals(x5u, StringComparison.InvariantCultureIgnoreCase)) { Log.Debug("Key is ok, and got Mojang root"); } else if (chain.Count > 1) { Log.Debug("Got client cert (client root)"); continue; } else if (chain.Count == 1) { Log.Debug("Selfsigned chain"); } } else if (identityPublicKey.Equals(x5u)) { Log.Debug("Derived Key is ok"); } // Validate var key = PublicKeyFactory.CreateKey(x5u.DecodeBase64Url()); CertificateData data = CryptoUtils.Decode(token.ToString(), key); if (data != null) { identityPublicKey = data.IdentityPublicKey; if (Log.IsDebugEnabled) { Log.Debug("Decoded token success"); } if (CertificateData.MojangRootKey.Equals(x5u, StringComparison.InvariantCultureIgnoreCase)) { Log.Debug("Got Mojang key. Is valid = " + data.CertificateAuthority); validationKey = data.IdentityPublicKey; } else if (validationKey != null && validationKey.Equals(x5u, StringComparison.InvariantCultureIgnoreCase)) { _playerInfo.CertificateData = data; } else { if (data.ExtraData == null) { continue; } // Self signed, make sure they don't fake XUID if (data.ExtraData.Xuid != null) { Log.Warn("Received fake XUID from " + data.ExtraData.DisplayName); data.ExtraData.Xuid = null; } _playerInfo.CertificateData = data; } } else { Log.Error("Not a valid Identity Public Key for decoding"); } } } //TODO: Implement disconnect here _playerInfo.Username = _playerInfo.CertificateData.ExtraData.DisplayName; _session.Username = _playerInfo.Username; string identity = _playerInfo.CertificateData.ExtraData.Identity; if (Log.IsDebugEnabled) { Log.Debug($"Connecting user {_playerInfo.Username} with identity={identity}"); } _playerInfo.ClientUuid = new UUID(identity); bool useEncryption = (Config.GetProperty("UseEncryptionForAll", false) || (Config.GetProperty("UseEncryption", true) && !string.IsNullOrWhiteSpace(_playerInfo.CertificateData.ExtraData.Xuid))); if (useEncryption) { var publicKey = PublicKeyFactory.CreateKey(_playerInfo.CertificateData.IdentityPublicKey.DecodeBase64Url()); string namedCurve = "secp384r1"; ECKeyPairGenerator pGen = new ECKeyPairGenerator(); ECKeyGenerationParameters genParam = new ECKeyGenerationParameters( SecNamedCurves.GetOid(namedCurve), new SecureRandom()); pGen.Init(genParam); AsymmetricCipherKeyPair keyPair = pGen.GenerateKeyPair(); ECDHBasicAgreement agreement = new ECDHBasicAgreement(); agreement.Init(keyPair.Private); byte[] preHash = agreement.CalculateAgreement(publicKey).ToByteArray(); byte[] prepend = Encoding.UTF8.GetBytes("RANDOM SECRET"); byte[] secret; SHA256Managed sha = new SHA256Managed(); using (var memoryStream = new MemoryStream()) { memoryStream.Write(prepend, 0, prepend.Length); memoryStream.Write(preHash, 0, preHash.Length); memoryStream.Position = 0; secret = sha.ComputeHash(memoryStream); } sha.Dispose(); //if (Log.IsDebugEnabled) Log.Debug($"SECRET KEY (b64, {secret.Length}):\n{secret.EncodeBase64()}"); { RijndaelManaged rijAlg = new RijndaelManaged { BlockSize = 128, Padding = PaddingMode.None, Mode = CipherMode.CFB, FeedbackSize = 8, Key = secret, IV = secret.Take(16).ToArray(), }; // Create a decrytor to perform the stream transform. ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV); MemoryStream inputStream = new MemoryStream(); CryptoStream cryptoStreamIn = new CryptoStream(inputStream, decryptor, CryptoStreamMode.Read); ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV); MemoryStream outputStream = new MemoryStream(); CryptoStream cryptoStreamOut = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write); _session.CryptoContext = new CryptoContext { UseEncryption = true, Algorithm = rijAlg, Decryptor = decryptor, Encryptor = encryptor, InputStream = inputStream, OutputStream = outputStream, CryptoStreamIn = cryptoStreamIn, CryptoStreamOut = cryptoStreamOut }; var pubKey1 = ((ECPublicKeyParameters)keyPair.Public); byte[] asn = new byte[24] { 0x30, 0x76, 0x30, 0x10, 0x6, 0x7, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x2, 0x1, 0x6, 0x5, 0x2b, 0x81, 0x4, 0x0, 0x22, 0x3, 0x62, 0x0, 0x4 }; string b64Key = asn.Concat(ConvertToNCryptEccPublicBlob(pubKey1.Q).Skip(8)).ToArray().EncodeBase64(); var handshakeJson = new HandshakeData() { salt = prepend.EncodeBase64() }; string val = CryptoUtils.Encode(handshakeJson, keyPair.Private, JwsAlgorithm.ES384, new Dictionary <string, object> { { "x5u", b64Key } }); var response = McpeServerToClientHandshake.CreateObject(); response.NoBatch = true; response.ForceClear = true; response.token = val; _session.SendPackage(response); if (Log.IsDebugEnabled) { Log.Warn($"Encryption enabled for {_session.Username}"); } } } else { _session.CryptoContext = new CryptoContext { UseEncryption = false }; _session.MessageHandler.HandleMcpeClientToServerHandshake(null); } } catch (Exception e) { Log.Error("Decrypt", e); } }
protected static byte[] ECDH_GenerateSecret(OneKey[] keys) { if (keys[0][CoseKeyKeys.KeyType].Type != CBORType.Number) { throw new CoseException("Not an EC Key"); } if (keys[1][CoseKeyKeys.KeyType].Type != CBORType.Number) { throw new CoseException("Not an EC Key"); } OneKey epkPub = keys[1]; OneKey epkPriv = keys[0]; byte[] temp; switch ((GeneralValuesInt)epkPub[CoseKeyKeys.KeyType].AsInt32()) { case GeneralValuesInt.KeyType_OKP: if (epkPub[CoseKeyParameterKeys.OKP_Curve].AsInt32() != epkPriv[CoseKeyParameterKeys.OKP_Curve].AsInt32()) { throw new CoseException("Not a match of curves"); } switch ((GeneralValuesInt)epkPriv[CoseKeyParameterKeys.OKP_Curve].AsInt32()) { case GeneralValuesInt.X25519: temp = X25519.CalculateAgreement(epkPub.AsBytes(CoseKeyParameterKeys.OKP_X), epkPriv.AsBytes(CoseKeyParameterKeys.OKP_D)); break; default: throw new CoseException("Not a supported Curve"); } return(temp); case GeneralValuesInt.KeyType_EC2: if (epkPub[CoseKeyParameterKeys.EC_Curve].AsInt32() != epkPriv[CoseKeyParameterKeys.EC_Curve].AsInt32()) { throw new CoseException("not a match of curves"); } // Get the curve X9ECParameters p = epkPub.GetCurve(); ECPoint pubPoint = epkPub.GetPoint(); ECDomainParameters parameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H); ECPublicKeyParameters pub = new ECPublicKeyParameters(pubPoint, parameters); ECPrivateKeyParameters priv = new ECPrivateKeyParameters(epkPriv.AsBigInteger(CoseKeyParameterKeys.EC_D), parameters); IBasicAgreement e1 = new ECDHBasicAgreement(); e1.Init(priv); BigInteger k1 = e1.CalculateAgreement(pub); return(PadBytes(k1.ToByteArrayUnsigned(), p.Curve.FieldSize)); default: throw new CoseException("Not an EC Key"); } }
public string GenerateSharedSecretHex(string pubKeyHex) { var encoded = pubKeyHex.HexToByteArray(); if (encoded.Length == 64) { var numArray = new byte[encoded.Length + 1]; numArray[0] = (byte)4; Array.Copy((Array)encoded, 0, (Array)numArray, 1, encoded.Length); encoded = numArray; } var publicKeyParameters = new ECPublicKeyParameters("ECDH", ECDH_Key._curve.Curve.DecodePoint(encoded), ECDH_Key._domain); var ecdhBasicAgreement = new ECDHBasicAgreement(); ecdhBasicAgreement.Init(_key.Private); return(BigIntegers.AsUnsignedByteArray(ecdhBasicAgreement.GetFieldSize(), ecdhBasicAgreement.CalculateAgreement((ICipherParameters)publicKeyParameters)).ToHex(true)); }
public static byte[] HandleKey(byte[] key, byte[] secretKey) { Asn1InputStream inputStream = new Asn1InputStream(key); Asn1Object o1 = inputStream.ReadObject(); DerSequence seq = o1 as DerSequence; DerInteger x = seq[2] as DerInteger; DerInteger y = seq[3] as DerInteger; X9ECParameters p = CustomNamedCurves.GetByName("secp521r1"); ECDomainParameters domainParameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H); ECPoint point = p.Curve.CreatePoint(x.Value, y.Value); ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(point, domainParameters); ECKeyPairGenerator generator = new ECKeyPairGenerator(); generator.Init(new ECKeyGenerationParameters(publicKeyParameters.Parameters, new SecureRandom())); AsymmetricCipherKeyPair keyPair = generator.GenerateKeyPair(); ECDHBasicAgreement basicAgreement = new ECDHBasicAgreement(); basicAgreement.Init(keyPair.Private); BigInteger agreement = basicAgreement.CalculateAgreement(publicKeyParameters); byte[] agreementBytes = agreement.ToByteArray(); if (agreementBytes.Length == 65) { byte[] newAgreement = new byte[66]; Array.Copy(agreementBytes, 0, newAgreement, 1, 65); agreementBytes = newAgreement; } Sha512Digest sha512 = new Sha512Digest(); byte[] hash = new byte[sha512.GetDigestSize()]; sha512.BlockUpdate(agreementBytes, 0, agreementBytes.Length); sha512.DoFinal(hash, 0); byte[] secret = new byte[secretKey.Length]; for (int i = 0; i < secret.Length; i++) { secret[i] = secretKey[i]; secret[i] ^= hash[i]; } ECPublicKeyParameters publicKey = keyPair.Public as ECPublicKeyParameters; MemoryStream keyStream = new MemoryStream(); DerSequenceGenerator gen2 = new DerSequenceGenerator(keyStream); gen2.AddObject(new DerBitString(new byte[] { 0x00 }, 7)); gen2.AddObject(new DerInteger(new byte[] { 0x41 })); gen2.AddObject(new DerInteger(publicKey.Q.XCoord.ToBigInteger())); gen2.AddObject(new DerInteger(publicKey.Q.YCoord.ToBigInteger())); gen2.Close(); MemoryStream memoryStream = new MemoryStream(); DerSequenceGenerator gen1 = new DerSequenceGenerator(memoryStream); gen1.AddObject(new DerObjectIdentifier("2.16.840.1.101.3.4.2.3")); gen1.AddObject(new DerOctetString(keyStream.ToArray())); gen1.AddObject(new DerOctetString(secret)); gen1.Close(); byte[] result = memoryStream.ToArray(); memoryStream.Close(); keyStream.Close(); return(result); }