Esempio n. 1
0
        /// <summary>
        /// TODO
        /// </summary>
        /// <param name="deviceIdentifier"></param>
        /// <param name="deviceKey"></param>
        /// <param name="identityKeyPair"></param>
        /// <param name="profileKey"></param>
        /// <param name="code"></param>
        /// <param name="token"></param>
        /// <exception cref="InvalidKeyException"><</exception>
        /// <exception cref="IOException"></exception>
        public async Task AddDeviceAsync(string deviceIdentifier,
                                         ECPublicKey deviceKey,
                                         IdentityKeyPair identityKeyPair,
                                         byte[] profileKey,
                                         string code,
                                         CancellationToken?token = null)
        {
            if (token == null)
            {
                token = CancellationToken.None;
            }

            ProvisioningCipher cipher  = new ProvisioningCipher(deviceKey);
            ProvisionMessage   message = new ProvisionMessage
            {
                IdentityKeyPublic  = ByteString.CopyFrom(identityKeyPair.getPublicKey().serialize()),
                IdentityKeyPrivate = ByteString.CopyFrom(identityKeyPair.getPrivateKey().serialize()),
                Number             = credentials.E164,
                ProvisioningCode   = code
            };

            if (profileKey != null)
            {
                message.ProfileKey = ByteString.CopyFrom(profileKey);
            }

            byte[] ciphertext = cipher.Encrypt(message);
            await pushServiceSocket.SendProvisioningMessageAsync(deviceIdentifier, ciphertext, token);
        }
        public DeviceConsistencyMessage(DeviceConsistencyCommitment commitment, IdentityKeyPair identityKeyPair)
        {
            try
            {
                byte[] signatureBytes = Curve.calculateVrfSignature(identityKeyPair.getPrivateKey(), commitment.toByteArray());
                byte[] vrfOutputBytes = Curve.verifyVrfSignature(identityKeyPair.getPublicKey().getPublicKey(), commitment.toByteArray(), signatureBytes);

                this.generation = commitment.getGeneration();
                this.signature  = new DeviceConsistencySignature(signatureBytes, vrfOutputBytes);
                this.serialized = new DeviceConsistencyCodeMessage
                {
                    Generation = (uint)commitment.getGeneration(),
                    Signature  = ByteString.CopyFrom(signature.getSignature())
                }.ToByteArray();
            }
            catch (InvalidKeyException e)
            {
                Debug.Assert(false);
                throw e;
            }
            catch (VrfSignatureVerificationFailedException e)
            {
                Debug.Assert(false);
                throw e;
            }
        }
Esempio n. 3
0
        public ProvisionMessage Decrypt(IdentityKeyPair tmpIdentity, byte[] message)
        {
            ProvisionEnvelope env       = ProvisionEnvelope.Parser.ParseFrom(message);
            ECPublicKey       publicKey = Curve.decodePoint(env.PublicKey.ToByteArray(), 0);

            byte[]   sharedSecret  = Curve.calculateAgreement(publicKey, tmpIdentity.getPrivateKey());
            byte[]   derivedSecret = new HKDFv3().deriveSecrets(sharedSecret, Encoding.UTF8.GetBytes("TextSecure Provisioning Message"), 64);
            byte[][] parts         = Util.Split(derivedSecret, 32, 32);
            byte[]   joined        = env.Body.ToByteArray();
            if (joined[0] != 0x01)
            {
                throw new Exception("Bad version number on provision message!");
            }
            byte[] iv = new byte[16];
            Array.Copy(joined, 1, iv, 0, 16);
            byte[] ciphertext = new byte[joined.Length - 32 - 17];
            Array.Copy(joined, 17, ciphertext, 0, joined.Length - 32 - 17);
            byte[] ivAndCiphertext = new byte[joined.Length - 32];
            Array.Copy(joined, ivAndCiphertext, joined.Length - 32);
            byte[] mac = new byte[32];
            Array.Copy(joined, joined.Length - 32, mac, 0, 32);

            VerifyMac(parts[1], ivAndCiphertext, mac);
            return(ProvisionMessage.Parser.ParseFrom(Decrypt(parts[0], iv, ciphertext)));
        }
Esempio n. 4
0
        /// <summary>
        /// Generate the keysets for ourself
        /// </summary>
        /// <returns></returns>
        public bool sendSetPreKeys(bool isnew = false)
        {
            uint registrationId = 0;

            if (!isnew)
            {
                registrationId = (uint)this.GetLocalRegistrationId();
            }
            else
            {
                registrationId = libaxolotl.util.KeyHelper.generateRegistrationId(true);
            }
            Random          random          = new Random();
            uint            randomid        = (uint)libaxolotl.util.KeyHelper.getRandomSequence(65536);
            IdentityKeyPair identityKeyPair = libaxolotl.util.KeyHelper.generateIdentityKeyPair();

            byte[] privateKey                  = identityKeyPair.getPrivateKey().serialize();
            byte[] publicKey                   = identityKeyPair.getPublicKey().serialize();
            IList <PreKeyRecord> preKeys       = libaxolotl.util.KeyHelper.generatePreKeys((uint)random.Next(), 200);
            SignedPreKeyRecord   signedPreKey  = libaxolotl.util.KeyHelper.generateSignedPreKey(identityKeyPair, randomid);
            PreKeyRecord         lastResortKey = libaxolotl.util.KeyHelper.generateLastResortPreKey();

            this.StorePreKeys(preKeys);
            this.StoreLocalData(registrationId, identityKeyPair.getPublicKey().serialize(), identityKeyPair.getPrivateKey().serialize());
            this.StoreSignedPreKey(signedPreKey.getId(), signedPreKey);

            List <ProtocolTreeNode> preKeyNodes = new List <ProtocolTreeNode>();

            for (int i = 0; i < 200; i++)
            {
                byte[]           prekeyId  = adjustId(preKeys[i].getId().ToString());
                byte[]           prekey    = preKeys[i].getKeyPair().getPublicKey().serialize().Skip(1).ToArray();
                ProtocolTreeNode NodeId    = new ProtocolTreeNode("id", null, null, prekeyId);
                ProtocolTreeNode NodeValue = new ProtocolTreeNode("value", null, null, prekey);
                preKeyNodes.Add(new ProtocolTreeNode("key", null, new[] { NodeId, NodeValue }, null));
            }

            ProtocolTreeNode registration = new ProtocolTreeNode("registration", null, null, adjustId(registrationId.ToString()));
            ProtocolTreeNode identity     = new ProtocolTreeNode("identity", null, null, publicKey.Skip(1).ToArray());
            ProtocolTreeNode type         = new ProtocolTreeNode("type", null, null, new byte[] { Curve.DJB_TYPE });
            ProtocolTreeNode list         = new ProtocolTreeNode("list", null, preKeyNodes.ToArray(), null);
            ProtocolTreeNode sid          = new ProtocolTreeNode("id", null, null, adjustId(signedPreKey.getId().ToString()));
            ProtocolTreeNode value        = new ProtocolTreeNode("value", null, null, signedPreKey.getKeyPair().getPublicKey().serialize().Skip(1).ToArray());
            ProtocolTreeNode signature    = new ProtocolTreeNode("signature", null, null, signedPreKey.getSignature());
            ProtocolTreeNode secretKey    = new ProtocolTreeNode("skey", null, new[] { sid, value, signature }, null);

            String id = TicketManager.GenerateId();

            Helper.DebugAdapter.Instance.fireOnPrintDebug(string.Format("axolotl id = {0}", id));

            ProtocolTreeNode Node = new ProtocolTreeNode("iq", new[] {
                new KeyValue("id", id),
                new KeyValue("xmlns", "encrypt"),
                new KeyValue("type", "set"),
                new KeyValue("to", "s.whatsapp.net")
            }, new ProtocolTreeNode[] { identity, registration, type, list, secretKey }, null);

            this.SendNode(Node);
            return(true);
        }
Esempio n. 5
0
        /// <summary>
        /// Generate a signed PreKey
        /// </summary>
        /// <param name="identityKeyPair">The local client's identity key pair.</param>
        /// <param name="signedPreKeyId">The PreKey id to assign the generated signed PreKey</param>
        /// <returns>the generated signed PreKey</returns>
        /// <exception cref="InvalidKeyException">when the provided identity key is invalid</exception>
        public static SignedPreKeyRecord generateSignedPreKey(IdentityKeyPair identityKeyPair, uint signedPreKeyId)
        {
            ECKeyPair keyPair = Curve.generateKeyPair();

            byte[] signature = Curve.calculateSignature(identityKeyPair.getPrivateKey(), keyPair.getPublicKey().serialize());

            return(new SignedPreKeyRecord(signedPreKeyId, getTime(), keyPair, signature));
        }
Esempio n. 6
0
        private static Task <SignedPreKeyRecord> generateSignedPreKey(IdentityKeyPair identityKeyPair, uint signedPreKeyId)
        {
            return(Task.Run(() =>
            {
                ECKeyPair keyPair = Curve.generateKeyPair();
                byte[] signature = Curve.calculateSignature(identityKeyPair.getPrivateKey(), keyPair.getPublicKey().serialize());
                SignedPreKeyRecord record = new SignedPreKeyRecord(signedPreKeyId, KeyHelper.getTime(), keyPair, signature);

                return record;
            }));
        }
Esempio n. 7
0
        private static SignedPreKeyRecord generateSignedPreKey(IdentityKeyPair identityKeyPair, uint signedPreKeyId)
        {
            //return Task.Run(() =>
            //{
            ECKeyPair keyPair = Curve.generateKeyPair();

            byte[]             signature = Curve.calculateSignature(identityKeyPair.getPrivateKey(), keyPair.getPublicKey().serialize());
            SignedPreKeyRecord record    = new SignedPreKeyRecord(signedPreKeyId, (ulong)TimeUtil.GetUnixTimestampMillis(), keyPair, signature);

            return(record);
            // });
        }
        public async void addDevice(string deviceIdentifier,
                                    ECPublicKey deviceKey,
                                    IdentityKeyPair identityKeyPair,
                                    string code)//throws InvalidKeyException, IOException
        {
            ProvisioningCipher cipher  = new ProvisioningCipher(deviceKey);
            ProvisionMessage   message = ProvisionMessage.CreateBuilder()
                                         .SetIdentityKeyPublic(ByteString.CopyFrom(identityKeyPair.getPublicKey().serialize()))
                                         .SetIdentityKeyPrivate(ByteString.CopyFrom(identityKeyPair.getPrivateKey().serialize()))
                                         .SetNumber(user)
                                         .SetProvisioningCode(code)
                                         .Build();

            byte[] ciphertext = cipher.encrypt(message);
            await this.pushServiceSocket.sendProvisioningMessage(deviceIdentifier, ciphertext);
        }
Esempio n. 9
0
        private static SignedPreKeyRecord generateSignedPreKey(IdentityKeyPair identityKeyPair)
        {
            try
            {
                ECKeyPair          keyPair   = Curve.generateKeyPair();
                byte[]             signature = Curve.calculateSignature(identityKeyPair.getPrivateKey(), keyPair.getPublicKey().serialize());
                SignedPreKeyRecord record    = new SignedPreKeyRecord(App.Store.NextSignedPreKeyId, (ulong)DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond, keyPair, signature);

                StoreSignedPreKey(App.Store.NextSignedPreKeyId, record);
                UpdateNextSignedPreKeyId((App.Store.NextSignedPreKeyId + 1) % Medium.MAX_VALUE);
                return(record);
            }
            catch (InvalidKeyException e)
            {
                throw e;
            }
        }
        public void setPendingKeyExchange(uint sequence,
                                          ECKeyPair ourBaseKey,
                                          ECKeyPair ourRatchetKey,
                                          IdentityKeyPair ourIdentityKey)
        {
            PendingKeyExchange structure = new PendingKeyExchange
            {
                LocalBaseKey            = ByteString.CopyFrom(ourBaseKey.getPublicKey().serialize()),
                LocalBaseKeyPrivate     = ByteString.CopyFrom(ourBaseKey.getPrivateKey().serialize()),
                LocalRatchetKey         = ByteString.CopyFrom(ourRatchetKey.getPublicKey().serialize()),
                LocalRatchetKeyPrivate  = ByteString.CopyFrom(ourRatchetKey.getPrivateKey().serialize()),
                LocalIdentityKey        = ByteString.CopyFrom(ourIdentityKey.getPublicKey().serialize()),
                LocalIdentityKeyPrivate = ByteString.CopyFrom(ourIdentityKey.getPrivateKey().serialize())
            };

            this.sessionStructure.PendingKeyExchange = structure;
        }
Esempio n. 11
0
        public void addDevice(string deviceIdentifier,
                              ECPublicKey deviceKey,
                              IdentityKeyPair identityKeyPair,
                              string code)//throws InvalidKeyException, IOException
        {
            ProvisioningCipher cipher  = new ProvisioningCipher(deviceKey);
            ProvisionMessage   message = new ProvisionMessage
            {
                IdentityKeyPublic  = ByteString.CopyFrom(identityKeyPair.getPublicKey().serialize()),
                IdentityKeyPrivate = ByteString.CopyFrom(identityKeyPair.getPrivateKey().serialize()),
                Number             = user,
                ProvisioningCode   = code
            };

            byte[] ciphertext = cipher.encrypt(message);
            this.pushServiceSocket.sendProvisioningMessage(deviceIdentifier, ciphertext);
        }
Esempio n. 12
0
        public void setPendingKeyExchange(uint sequence,
                                          ECKeyPair ourBaseKey,
                                          ECKeyPair ourRatchetKey,
                                          IdentityKeyPair ourIdentityKey)
        {
            PendingKeyExchange structure =
                PendingKeyExchange.CreateBuilder()
                .SetSequence(sequence)
                .SetLocalBaseKey(ByteString.CopyFrom(ourBaseKey.getPublicKey().serialize()))
                .SetLocalBaseKeyPrivate(ByteString.CopyFrom(ourBaseKey.getPrivateKey().serialize()))
                .SetLocalRatchetKey(ByteString.CopyFrom(ourRatchetKey.getPublicKey().serialize()))
                .SetLocalRatchetKeyPrivate(ByteString.CopyFrom(ourRatchetKey.getPrivateKey().serialize()))
                .SetLocalIdentityKey(ByteString.CopyFrom(ourIdentityKey.getPublicKey().serialize()))
                .SetLocalIdentityKeyPrivate(ByteString.CopyFrom(ourIdentityKey.getPrivateKey().serialize()))
                .Build();

            this.sessionStructure = this.sessionStructure.ToBuilder()
                                    .SetPendingKeyExchange(structure)
                                    .Build();
        }
Esempio n. 13
0
        public byte[] Encrypt(SignalProtocolAddress destinationAddress, SenderCertificate senderCertificate, byte[] paddedPlaintext)
        {
            CiphertextMessage message       = new SessionCipher(SignalProtocolStore, destinationAddress).encrypt(paddedPlaintext);
            IdentityKeyPair   ourIdentity   = SignalProtocolStore.GetIdentityKeyPair();
            ECPublicKey       theirIdentity = SignalProtocolStore.GetIdentity(destinationAddress).getPublicKey();

            ECKeyPair ephemeral = Curve.generateKeyPair();

            byte[]        ephemeralSalt = ByteUtil.combine(Encoding.ASCII.GetBytes("UnidentifiedDelivery"), theirIdentity.serialize(), ephemeral.getPublicKey().serialize());
            EphemeralKeys ephemeralKeys = CalculateEphemeralKeys(theirIdentity, ephemeral.getPrivateKey(), ephemeralSalt);

            byte[] staticKeyCiphertext = Encrypt(ephemeralKeys.CipherKey, ephemeralKeys.MacKey, ourIdentity.getPublicKey().getPublicKey().serialize());

            byte[]     staticSalt = ByteUtil.combine(ephemeralKeys.ChainKey, staticKeyCiphertext);
            StaticKeys staticKeys = CalculateStaticKeys(theirIdentity, ourIdentity.getPrivateKey(), staticSalt);
            UnidentifiedSenderMessageContent content = new UnidentifiedSenderMessageContent((int)message.getType(), senderCertificate, message.serialize());

            byte[] messageBytes = Encrypt(staticKeys.CipherKey, staticKeys.MacKey, content.Serialized);

            return(new UnidentifiedSenderMessage(ephemeral.getPublicKey(), staticKeyCiphertext, messageBytes).Serialized);
        }
Esempio n. 14
0
        /// <summary>
        /// TODO
        /// </summary>
        /// <param name="token"></param>
        /// <param name="deviceIdentifier"></param>
        /// <param name="deviceKey"></param>
        /// <param name="identityKeyPair"></param>
        /// <param name="profileKey"></param>
        /// <param name="code"></param>
        public async Task AddDevice(CancellationToken token,
                                    string deviceIdentifier,
                                    ECPublicKey deviceKey,
                                    IdentityKeyPair identityKeyPair,
                                    byte[] profileKey,
                                    string code)//throws InvalidKeyException, IOException
        {
            ProvisioningCipher cipher  = new ProvisioningCipher(deviceKey);
            ProvisionMessage   message = new ProvisionMessage
            {
                IdentityKeyPublic  = ByteString.CopyFrom(identityKeyPair.getPublicKey().serialize()),
                IdentityKeyPrivate = ByteString.CopyFrom(identityKeyPair.getPrivateKey().serialize()),
                Number             = User,
                ProvisioningCode   = code
            };

            if (profileKey != null)
            {
                message.ProfileKey = ByteString.CopyFrom(profileKey);
            }

            byte[] ciphertext = cipher.encrypt(message);
            await PushServiceSocket.SendProvisioningMessage(token, deviceIdentifier, ciphertext);
        }
Esempio n. 15
0
        /**
         * Generate a signed PreKey
         *
         * @param identityKeyPair The local client's identity key pair.
         * @param signedPreKeyId The PreKey id to assign the generated signed PreKey
         *
         * @return the generated signed PreKey
         * @throws InvalidKeyException when the provided identity key is invalid
         */
        public static SignedPreKeyRecord generateSignedPreKey(IdentityKeyPair identityKeyPair, uint signedPreKeyId)
        {
            ECKeyPair keyPair = Curve.generateKeyPair();
            byte[] signature = Curve.calculateSignature(identityKeyPair.getPrivateKey(), keyPair.getPublicKey().serialize());

            return new SignedPreKeyRecord(signedPreKeyId, getTime(), keyPair, signature);
        }
Esempio n. 16
0
		public void setPendingKeyExchange(uint sequence,
										  ECKeyPair ourBaseKey,
										  ECKeyPair ourRatchetKey,
										  IdentityKeyPair ourIdentityKey)
		{
			PendingKeyExchange structure =
				PendingKeyExchange.CreateBuilder()
								  .SetSequence(sequence)
								  .SetLocalBaseKey(ByteString.CopyFrom(ourBaseKey.getPublicKey().serialize()))
								  .SetLocalBaseKeyPrivate(ByteString.CopyFrom(ourBaseKey.getPrivateKey().serialize()))
								  .SetLocalRatchetKey(ByteString.CopyFrom(ourRatchetKey.getPublicKey().serialize()))
								  .SetLocalRatchetKeyPrivate(ByteString.CopyFrom(ourRatchetKey.getPrivateKey().serialize()))
								  .SetLocalIdentityKey(ByteString.CopyFrom(ourIdentityKey.getPublicKey().serialize()))
								  .SetLocalIdentityKeyPrivate(ByteString.CopyFrom(ourIdentityKey.getPrivateKey().serialize()))
								  .Build();

			this.sessionStructure = this.sessionStructure.ToBuilder()
														 .SetPendingKeyExchange(structure)
														 .Build();
		}
Esempio n. 17
0
        public (SignalProtocolAddress, byte[]) Decrypt(CertificateValidator validator, byte[] ciphertext, long timestamp)
        {
            UnidentifiedSenderMessageContent content;

            try
            {
                IdentityKeyPair           ourIdentity = SignalProtocolStore.GetIdentityKeyPair();
                UnidentifiedSenderMessage wrapper     = new UnidentifiedSenderMessage(ciphertext);
                byte[]        ephemeralSalt           = ByteUtil.combine(Encoding.ASCII.GetBytes("UnidentifiedDelivery"), ourIdentity.getPublicKey().getPublicKey().serialize(), wrapper.Ephemeral.serialize());
                EphemeralKeys ephemeralKeys           = CalculateEphemeralKeys(wrapper.Ephemeral, ourIdentity.getPrivateKey(), ephemeralSalt);
                byte[]        staticKeyBytes          = Decrypt(ephemeralKeys.CipherKey, ephemeralKeys.MacKey, wrapper.EncryptedStatic);

                ECPublicKey staticKey    = Curve.decodePoint(staticKeyBytes, 0);
                byte[]      staticSalt   = ByteUtil.combine(ephemeralKeys.ChainKey, wrapper.EncryptedStatic);
                StaticKeys  staticKeys   = CalculateStaticKeys(staticKey, ourIdentity.getPrivateKey(), staticSalt);
                byte[]      messageBytes = Decrypt(staticKeys.CipherKey, staticKeys.MacKey, wrapper.EncryptedMessage);

                content = new UnidentifiedSenderMessageContent(messageBytes);
                validator.Validate(content.SenderCertificate, timestamp);

                if (!Enumerable.SequenceEqual(content.SenderCertificate.Key.serialize(), staticKeyBytes))
                {
                    throw new libsignal.InvalidKeyException("Sender's certificate key does not match key used in message");
                }

                if (content.SenderCertificate.Sender == LocalAddress.Name &&
                    content.SenderCertificate.SenderDeviceId == LocalAddress.DeviceId)
                {
                    throw new SelfSendException();
                }
            }
            catch (libsignal.InvalidKeyException e)
            {
                throw new InvalidMetadataMessageException(e);
            }
            catch (InvalidCertificateException e)
            {
                throw new InvalidMetadataMessageException(e);
            }
            catch (InvalidMacException e)
            {
                throw new InvalidMetadataMessageException(e);
            }

            try
            {
                return(new SignalProtocolAddress(content.SenderCertificate.Sender, (uint)content.SenderCertificate.SenderDeviceId),
                       Decrypt(content));
            }
            catch (InvalidMessageException e)
            {
                throw new ProtocolInvalidMessageException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId);
            }
            catch (libsignal.InvalidKeyException e)
            {
                throw new ProtocolInvalidKeyException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId);
            }
            catch (NoSessionException e)
            {
                throw new ProtocolNoSessionException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId);
            }
            catch (LegacyMessageException e)
            {
                throw new ProtocolLegacyMessageException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId);
            }
            catch (InvalidVersionException e)
            {
                throw new ProtocolInvalidVersionException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId);
            }
            catch (DuplicateMessageException e)
            {
                throw new ProtocolDuplicateMessageException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId);
            }
            catch (InvalidKeyIdException e)
            {
                throw new ProtocolInvalidKeyIdException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId);
            }
            catch (UntrustedIdentityException e)
            {
                throw new ProtocolUntrustedIdentityException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId);
            }
        }