//--------------------------------------------------------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; } } } }
public OmemoMessage(OmemoSessionModel session) { N = session.nS; PN = session.pn; DH = session.dhS.pubKey; cipherText = null; }
//--------------------------------------------------------Constructor:----------------------------------------------------------------\\ #region --Constructors-- public OmemoFingerprint(ECPubKeyModel identityKey, OmemoProtocolAddress address, DateTime lastSeen, bool trusted) { IDENTITY_KEY = identityKey; ADDRESS = address; this.lastSeen = lastSeen; this.trusted = trusted; }
/// <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; }
/// <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()); }
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(); }
//--------------------------------------------------------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(); }
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); } }
/// <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); }
/// <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) { }
public EphemeralKeyPairModel(ECPrivKeyModel privKey, ECPubKeyModel pubKey) : base(privKey, pubKey) { }
/// <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)); }
//--------------------------------------------------------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)); }
public OmemoFingerprint(ECPubKeyModel identityKey, OmemoProtocolAddress address) : this(identityKey, address, DateTime.MinValue, false) { }
/// <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) { }