Beispiel #1
0
        //--------------------------------------------------------Misc Methods:---------------------------------------------------------------\\
        #region --Misc Methods (Public)--
        public void loadBundleInformation(XmlNode node)
        {
            foreach (XmlNode itemNode in node.ChildNodes)
            {
                if (string.Equals(itemNode.Name, "item"))
                {
                    if (!uint.TryParse(itemNode.Attributes["id"].Value, out uint id) || id == 0)
                    {
                        continue;
                    }
                    deviceId = id;
                    XmlNode bundleNode = XMLUtils.getChildNode(itemNode, "bundle", Consts.XML_XMLNS, Consts.XML_XEP_0384_NAMESPACE);
                    if (bundleNode != null)
                    {
                        bundle = new Bundle();
                        foreach (XmlNode n in bundleNode.ChildNodes)
                        {
                            switch (n.Name)
                            {
                            case "spk":
                                bundle.signedPreKey = ECPubKeyModel.FromBase64String(n.InnerText);

                                uint.TryParse(n.Attributes["id"]?.Value, out uint sigId);
                                bundle.signedPreKeyId = sigId;
                                break;

                            case "spks":
                                bundle.preKeySignature = Convert.FromBase64String(n.InnerText);
                                break;

                            case "ik":
                                bundle.identityKey = ECPubKeyModel.FromBase64String(n.InnerText);
                                break;

                            case "prekeys":
                                foreach (XmlNode n1 in n.ChildNodes)
                                {
                                    switch (n1.Name)
                                    {
                                    case "pk":
                                        if (uint.TryParse(n1.Attributes["id"]?.Value, out uint preKeyId))
                                        {
                                            byte[] pubPreKey = Convert.FromBase64String(n1.InnerText);
                                            bundle.preKeys.Add(new PreKeyModel(null, ECPubKeyModel.FromBase64String(n1.InnerText), preKeyId));
                                        }
                                        else
                                        {
                                            throw new InvalidOperationException("Invalid message. Unable to parse preKeyId");
                                        }
                                        break;
                                    }
                                }
                                break;
                            }
                        }
                        return;
                    }
                }
            }
        }
Beispiel #2
0
 public OmemoMessage(OmemoSessionModel session)
 {
     N          = session.nS;
     PN         = session.pn;
     DH         = session.dhS.pubKey;
     cipherText = null;
 }
Beispiel #3
0
 //--------------------------------------------------------Constructor:----------------------------------------------------------------\\
 #region --Constructors--
 public OmemoFingerprint(ECPubKeyModel identityKey, OmemoProtocolAddress address, DateTime lastSeen, bool trusted)
 {
     IDENTITY_KEY  = identityKey;
     ADDRESS       = address;
     this.lastSeen = lastSeen;
     this.trusted  = trusted;
 }
Beispiel #4
0
        /// <summary>
        /// Generates the ECDH shared secret between two Ed25519 public keys and returns it.
        /// </summary>
        /// <param name="a">An Ed25519 private key.</param>
        /// <param name="b">An Ed25519 public key.</param>
        public static byte[] SharedSecret(ECPrivKeyModel a, ECPubKeyModel b)
        {
#pragma warning disable CS0618 // Type or member is obsolete but can be ignored here since this function just needs more testing.
            return(Ed25519.KeyExchange(b.key, a.key));

#pragma warning restore CS0618 // Type or member is obsolete but can be ignored here since this function just needs more testing.
        }
 //--------------------------------------------------------Constructor:----------------------------------------------------------------\\
 #region --Constructors--
 public OmemoKeyExchangeMessage(uint pkId, uint spkId, ECPubKeyModel ik, ECPubKeyModel ek, OmemoAuthenticatedMessage message)
 {
     PK_ID   = pkId;
     SPK_ID  = spkId;
     IK      = ik;
     EK      = ek;
     MESSAGE = message;
 }
Beispiel #6
0
        /// <summary>
        /// Generates the OMEMO fingerprint for displaying as a QR code.
        /// </summary>
        /// <param name="identityKey">The identity public key.</param>
        /// <param name="bareJid">The bare JID the fingerprint belongs to.</param>
        /// <param name="deviceId">The OMEMO device id the fingerprint belongs to.</param>
        /// <returns>A string representation of the fingerprint concatenated with JID and device id.</returns>
        public static string generateOmemoQrCodeFingerprint(ECPubKeyModel identityKey, string bareJid, uint deviceId)
        {
            StringBuilder sb = new StringBuilder("xmpp:");

            sb.Append(bareJid);
            sb.Append("?omemo-sid-");
            sb.Append(deviceId);
            sb.Append('=');
            sb.Append(byteArrayToHexString(identityKey.key));
            return(sb.ToString());
        }
Beispiel #7
0
        public void Test_CryptoUtils_GenOmemoFingerprint()
        {
            string publicIdentKeySerializedHex = "3b6a27bcceb6a42d62a3a8d02a6f0d73653215771de243a63ac048a18b59da29";

            byte[]        publicIdentKeySerialized = SharedUtils.HexStringToByteArray(publicIdentKeySerializedHex);
            ECPubKeyModel identKeyPair             = new ECPubKeyModel(publicIdentKeySerialized);

            string outputRef = "3b6a27bc ceb6a42d 62a3a8d0 2a6f0d73 65321577 1de243a6 3ac048a1 8b59da29";
            string output    = CryptoUtils.generateOmemoFingerprint(identKeyPair.key);

            Assert.AreEqual(outputRef, output);
        }
 public OmemoKeyExchangeMessage(byte[] data)
 {
     PK_ID  = BitConverter.ToUInt32(data, 0);
     SPK_ID = BitConverter.ToUInt32(data, 4);
     IK     = new ECPubKeyModel(new byte[KeyHelper.PUB_KEY_SIZE]);
     Buffer.BlockCopy(data, 8, IK.key, 0, IK.key.Length);
     EK = new ECPubKeyModel(new byte[KeyHelper.PUB_KEY_SIZE]);
     Buffer.BlockCopy(data, 8 + IK.key.Length, EK.key, 0, EK.key.Length);
     byte[] msg = new byte[data.Length - 4 - 4 - IK.key.Length - EK.key.Length];
     Buffer.BlockCopy(data, 8 + IK.key.Length + EK.key.Length, msg, 0, msg.Length);
     MESSAGE = new OmemoAuthenticatedMessage(msg);
     Validate();
 }
Beispiel #9
0
        //--------------------------------------------------------Constructor:----------------------------------------------------------------\\
        #region --Constructors--
        public OmemoMessage(byte[] data)
        {
            N  = (uint)BitConverter.ToInt32(data, 0);
            PN = (uint)BitConverter.ToInt32(data, 4);
            DH = new ECPubKeyModel(new byte[Ed25519.PublicKeySizeInBytes]);
            Buffer.BlockCopy(data, 8, DH.key, 0, DH.key.Length);
            int cipherTextLenth = data.Length - (8 + DH.key.Length);

            // Cipher text here is optional:
            if (cipherTextLenth > 0)
            {
                cipherText = new byte[data.Length - (8 + DH.key.Length)];
                Buffer.BlockCopy(data, 8 + DH.key.Length, cipherText, 0, cipherText.Length);
            }
            Validate();
        }
Beispiel #10
0
        public void Test_SignPreKey()
        {
            ECPrivKeyModel       priv            = new ECPrivKeyModel(SharedUtils.HexStringToByteArray("1498b5467a63dffa2dc9d9e069caf075d16fc33fdd4c3b01bfadae6433767d93"));
            ECPubKeyModel        pub             = new ECPubKeyModel(SharedUtils.HexStringToByteArray("b7a3c12dc0c8c748ab07525b701122b88bd78f600c76342d27f25e5f92444cde"));
            IdentityKeyPairModel identityKeyPair = new IdentityKeyPairModel(priv, pub);

            for (uint id = 1; id < 250; id++)
            {
                byte[] data = Encoding.ASCII.GetBytes("Message for Ed25519 signing");

                byte[] signature = new byte[Ed25519.SignatureSize];
                Ed25519.Sign(identityKeyPair.privKey.key, 0, data, 0, data.Length, signature, 0);
                byte[] sigRef       = SharedUtils.HexStringToByteArray("6dd355667fae4eb43c6e0ab92e870edb2de0a88cae12dbd8591507f584fe4912babff497f1b8edf9567d2483d54ddc6459bea7855281b7a246a609e3001a4e08");
                string sigRefBase64 = Convert.ToBase64String(sigRef);
                string sigBase64    = Convert.ToBase64String(signature);
                Assert.AreEqual(sigBase64, sigRefBase64);
            }
        }
Beispiel #11
0
        /// <summary>
        /// [WIP]<para/>
        /// Parses XMPP IRIs and URIs based on RFC 5122 and returns the result.
        /// </summary>
        /// <param name="uri">The URI or IRI that should get parsed.</param>
        /// <returns>The URI or IRI result or null if an error occurred.</returns>
        public static IUriAction parse(Uri uri)
        {
            if (!string.IsNullOrEmpty(uri?.OriginalString))
            {
                if (string.Equals(uri.Scheme.ToLowerInvariant(), "xmpp"))
                {
                    string tmp = uri.OriginalString;

                    // 1. remove 'xmpp:'
                    tmp = tmp.Substring(5);

                    // 2. Authority
                    string authority = null;
                    if (tmp.StartsWith("//"))
                    {
                        tmp.Substring(2);
                        int authEnd = tmp.IndexOf('/');
                        if (authEnd < 0)
                        {
                            authEnd = tmp.IndexOf('?');
                            if (authEnd < 0)
                            {
                                authEnd = tmp.IndexOf('#');
                                if (authEnd < 0)
                                {
                                    authEnd = tmp.Length <= 0 ? 0 : tmp.Length - 1;
                                }
                            }
                            authority = tmp.Substring(0, authEnd);
                            tmp       = tmp.Substring(authEnd + 1);
                        }
                    }

                    if (string.Equals(uri.AbsolutePath, "iot-register"))
                    {
                        WwwFormUrlDecoder query = parseUriQuery(uri);
                        if (query is null)
                        {
                            return(null);
                        }

                        IWwwFormUrlDecoderEntry macEntry = query.FirstOrDefault(x => x.Name.StartsWith("mac"));
                        if (macEntry is null || string.IsNullOrEmpty(macEntry.Value))
                        {
                            Logger.Error("None or invalid IoT MAC address: " + uri.OriginalString);
                            return(null);
                        }
                        IWwwFormUrlDecoderEntry algoEntry = query.FirstOrDefault(x => x.Name.StartsWith("algo"));
                        if (algoEntry is null || string.IsNullOrEmpty(algoEntry.Value))
                        {
                            Logger.Error("None or invalid IoT key algorithm: " + uri.OriginalString);
                            return(null);
                        }
                        IWwwFormUrlDecoderEntry keyEntry = query.FirstOrDefault(x => x.Name.StartsWith("key"));
                        if (keyEntry is null || string.IsNullOrEmpty(keyEntry.Value))
                        {
                            Logger.Error("None or invalid IoT key: " + uri.OriginalString);
                            return(null);
                        }
                        return(new RegisterIoTUriAction(macEntry.Value, algoEntry.Value, keyEntry.Value));
                    }
                    else
                    {
                        // Check if is OMEMO fingerprint URI:
                        WwwFormUrlDecoder query = parseUriQuery(uri);
                        if (query is null)
                        {
                            return(null);
                        }

                        IWwwFormUrlDecoderEntry entry = query.FirstOrDefault(x => x.Name.StartsWith("omemo-sid-"));
                        if (!(entry is null))
                        {
                            ECPubKeyModel pubKey = null;
                            try
                            {
                                byte[] fingerprintBytes = SharedUtils.HexStringToByteArray(entry.Value);
                                pubKey = new ECPubKeyModel(fingerprintBytes);
                            }
                            catch (Exception e)
                            {
                                Logger.Error("Failed to parse XMPP URI. Parsing fingerprint failed: " + entry.Value, e);
                                return(null);
                            }

                            if (uint.TryParse(entry.Name.Replace("omemo-sid-", "").Trim(), out uint deviceId))
                            {
                                OmemoProtocolAddress address = new OmemoProtocolAddress(uri.LocalPath, deviceId);
                                return(new OmemoFingerprintUriAction(new OmemoFingerprint(pubKey, address)));
                            }
                            else
                            {
                                Logger.Warn("Failed to parse XMPP URI. Invalid device ID: " + entry.Name);
                            }
                        }
                    }
                }
                else
                {
                    Logger.Warn("Failed to parse XMPP URI. No 'xmpp' scheme.");
                }
            }
            return(null);
        }
Beispiel #12
0
 /// <summary>
 /// Generates the OMEMO fingerprint for displaying as a QR code.
 /// </summary>
 /// <param name="identityKey">The identity public key.</param>
 /// <param name="account">The XMPP account the fingerprint belongs to.</param>
 /// <returns>A string representation of the fingerprint concatenated with JID and device id.</returns>
 public static string generateOmemoQrCodeFingerprint(ECPubKeyModel identityKey, XMPPAccount account)
 {
     return(generateOmemoQrCodeFingerprint(identityKey, account.getBareJid(), account.omemoDeviceId));
 }
 public GenericECKeyPairModel(ECPrivKeyModel privKey, ECPubKeyModel pubKey) : base(privKey, pubKey)
 {
 }
Beispiel #14
0
 public EphemeralKeyPairModel(ECPrivKeyModel privKey, ECPubKeyModel pubKey) : base(privKey, pubKey)
 {
 }
Beispiel #15
0
 /// <summary>
 /// Verifies the signature of the given data with the given <see cref="ECPubKeyModel"/>.
 /// </summary>
 /// <param name="identityKey">The <see cref="ECPubKeyModel"/> of the IdentityKey used for validating the signature.</param>
 /// <param name="preKey">The <see cref="ECPubKeyModel"/> of the PreKey, the signature should be verified for.</param>
 /// <param name="signature">The signature that should be verified.</param>
 /// <returns>True in case the signature is valid.</returns>
 public static bool VerifySignature(ECPubKeyModel identityKey, ECPubKeyModel preKey, byte[] signature)
 {
     return(Ed25519.Verify(signature, 0, identityKey.key, 0, preKey.key, 0, preKey.key.Length));
 }
Beispiel #16
0
        //--------------------------------------------------------Set-, Get- Methods:---------------------------------------------------------\\
        #region --Set-, Get- Methods--


        #endregion
        //--------------------------------------------------------Misc Methods:---------------------------------------------------------------\\
        #region --Misc Methods (Public)--
        public bool checkIdentityKey(ECPubKeyModel other)
        {
            return(other.key.SequenceEqual(IDENTITY_KEY.key));
        }
Beispiel #17
0
 public OmemoFingerprint(ECPubKeyModel identityKey, OmemoProtocolAddress address) : this(identityKey, address, DateTime.MinValue, false)
 {
 }
Beispiel #18
0
 /// <summary>
 /// Generates the ECDH shared secret between two Ed25519 public keys and returns it.
 /// </summary>
 /// <param name="a">An Ed25519 private key.</param>
 /// <param name="b">An Ed25519 public key.</param>
 public static byte[] SharedSecret(ECPrivKeyModel a, ECPubKeyModel b)
 {
     return(X25519KeyAgreement.Agreement(a.key, b.key));
 }
 public IdentityKeyPairModel(ECPrivKeyModel privKey, ECPubKeyModel pubKey) : base(privKey, pubKey)
 {
 }