Ejemplo n.º 1
0
 public ServerConnection(string baseUrl, Curve25519KeyPair deviceKey, string deviceUuid = null)
 {
     _client     = new HttpClient();
     _baseUrl    = baseUrl;
     _deviceKey  = deviceKey;
     _deviceUuid = deviceUuid;
 }
        public void testUniqueSignatures()
        {
            Curve25519KeyPair keys   = curve25519.generateKeyPair();
            Random            random = new Random();

            for (int i = 1; i <= 256; i++)
            {
                byte[] message = new byte[i];
                random.NextBytes(message);

                byte[] signature = curve25519.calculateVrfSignature(keys.getPrivateKey(), message);
                byte[] vrf       = curve25519.verifyVrfSignature(keys.getPublicKey(), message, signature);

                Assert.IsFalse(curve25519.verifySignature(keys.getPublicKey(), message, signature));

                message[Math.Abs(random.Next(int.MaxValue)) % message.Length] ^= 0x01;

                try
                {
                    curve25519.verifyVrfSignature(keys.getPublicKey(), message, signature);
                    throw new InvalidOperationException("Should have failed");
                }
                catch (VrfSignatureVerificationFailedException e)
                {
                    // good
                }
            }
        }
        private async void OnSetUpPressed(object sender, EventArgs e)
        {
            string serverUrl = ServerEntry.Text;

            string devicePrivateKeyBase64 = await _secureStorageService.GetAsync("devicePrivateKey");

            Curve25519KeyPair deviceKeyPair;

            if (devicePrivateKeyBase64 is null)
            {
                deviceKeyPair = new Curve25519KeyPair();
                await _secureStorageService.SetAsync("devicePrivateKey", Convert.ToBase64String(deviceKeyPair.EdPrivateKey));
            }
            else
            {
                deviceKeyPair = new Curve25519KeyPair(Convert.FromBase64String(devicePrivateKeyBase64), true, true);
            }

            _connection = new ServerConnection(serverUrl, deviceKeyPair);

            string deviceUuid = await _connection.RegisterDeviceAsync();

            string userUuid = await _connection.RegisterUserAsync(EmailEntry.Text, GlobalKeyStore.Instance.IdentityKeyPair, GlobalKeyStore.Instance.SignedPreKeyPairs[0], ":)", "Non-contradictory");

            await _connection.UploadOneTimePreKeysAsync(GlobalKeyStore.Instance.OneTimePreKeyPairs);

            await DisplayAlert("Information: ", $"Device ID: {deviceUuid}\nUser ID: {userUuid}", "Ok");

            EmailEntry.Text = userUuid;
        }
Ejemplo n.º 4
0
        public static async Task <Dictionary <string, RemoteAttestation> > GetAndVerifyMultiRemoteAttestation(PushServiceSocket socket,
                                                                                                              PushServiceSocket.ClientSet clientSet,
                                                                                                              string enclaveName,
                                                                                                              string mrenclave,
                                                                                                              string authorization)
        {
            Curve25519KeyPair keyPair = BuildKeyPair();
            ResponsePair      result  = await MakeAttestationRequestAsync(socket, clientSet, authorization, enclaveName, keyPair);

            MultiRemoteAttestationResponse         response     = JsonUtil.FromJson <MultiRemoteAttestationResponse>(result.body);
            Dictionary <string, RemoteAttestation> attestations = new Dictionary <string, RemoteAttestation>();

            if (response.Attestations !.Count == 0 || response.Attestations.Count > 3)
            {
                throw new MalformedResponseException($"Incorrect number of attestations: {response.Attestations.Count}");
            }

            foreach (var entry in response.Attestations)
            {
                attestations.Add(entry.Key,
                                 ValidateAndBuildRemoteAttestation(entry.Value, result.cookies, keyPair, mrenclave));
            }

            return(attestations);
        }
Ejemplo n.º 5
0
        public static EcKeyPair GenerateKeyPair()
        {
            Curve25519KeyPair keyPair = Curve25519.GetInstance(Curve25519ProviderType.Best).GenerateKeyPair();

            return(new EcKeyPair(new DjbEcPublicKey(keyPair.GetPublicKey()),
                                 new DjbEcPrivateKey(keyPair.GetPrivateKey())));
        }
Ejemplo n.º 6
0
        public static ECKeyPair generateKeyPair()
        {
            Curve25519KeyPair keyPair = Curve25519.getInstance(Curve25519ProviderType.BEST).generateKeyPair();

            return(new ECKeyPair(new DjbECPublicKey(keyPair.getPublicKey()),
                                 new DjbECPrivateKey(keyPair.getPrivateKey())));
        }
Ejemplo n.º 7
0
        public async Task <ChatPackage> GetChatPackage(string userUuid)
        {
            HttpResponseMessage response = await PostAuthenticatedAsync($"/users/{userUuid}/package");

            Dictionary <string, string> responseDict = await HandleResponse <string>(response).ConfigureAwait(false);

            // TODO check all keys are present in dictionary

            Curve25519KeyPair otherIdentityKey  = new Curve25519KeyPair(Convert.FromBase64String(responseDict["identity_key"]), false, true);
            Curve25519KeyPair otherSignedPreKey = new Curve25519KeyPair(Convert.FromBase64String(responseDict["signed_prekey"]), false, false);

            byte[]            otherSignedPreKeySignature = Convert.FromBase64String(responseDict["prekey_signature"]);
            Curve25519KeyPair otherOneTimePreKey         = new Curve25519KeyPair(Convert.FromBase64String(responseDict["onetime_key"]), false, false);

            if (!otherIdentityKey.Verify(otherSignedPreKey.XPublicKey, otherSignedPreKeySignature))
            {
                throw new ServerConnectionException($"The user's pre-key signature does not match their signed key: uuid = {userUuid}");
            }

            return(new ChatPackage
            {
                OtherIdentityKey = otherIdentityKey,
                OtherSignedPreKey = otherSignedPreKey,
                OtherOneTimePreKey = otherOneTimePreKey
            });
        }
        public void testUniqueSignatureVector()
        {
            Curve25519KeyPair keys = new Curve25519KeyPair(PUBLIC_KEY, PRIVATE_KEY);

            byte[] signature = curve25519.calculateVrfSignature(keys.getPrivateKey(), MESSAGE);
            byte[] vrf       = curve25519.verifyVrfSignature(keys.getPublicKey(), MESSAGE, signature);

            CollectionAssert.AreEqual(VRF, vrf);
        }
Ejemplo n.º 9
0
        public static async Task <RemoteAttestation> GetAndVerifyRemoteAttestationAsync(PushServiceSocket socket,
                                                                                        PushServiceSocket.ClientSet clientSet,
                                                                                        string enclaveName,
                                                                                        string mrenclave,
                                                                                        string authorization)
        {
            Curve25519KeyPair keyPair = BuildKeyPair();
            ResponsePair      result  = await MakeAttestationRequestAsync(socket, clientSet, authorization, enclaveName, keyPair);

            RemoteAttestationResponse response = JsonUtil.FromJson <RemoteAttestationResponse>(result.body);

            return(ValidateAndBuildRemoteAttestation(response, result.cookies, keyPair, mrenclave));
        }
Ejemplo n.º 10
0
        public RemoteAttestationKeys(Curve25519KeyPair keyPair, byte[] serverPublicEphemeral, byte[] serverPublicStatic)
        {
            byte[] ephemeralToEphemeral = Curve25519.getInstance(Curve25519.BEST).calculateAgreement(serverPublicEphemeral, keyPair.getPrivateKey());
            byte[] ephemeralToStatic    = Curve25519.getInstance(Curve25519.BEST).calculateAgreement(serverPublicStatic, keyPair.getPrivateKey());

            byte[] masterSecret = ByteUtil.combine(ephemeralToEphemeral, ephemeralToStatic);
            byte[] publicKeys   = ByteUtil.combine(keyPair.getPublicKey(), serverPublicEphemeral, serverPublicStatic);

            HkdfBytesGenerator generator = new HkdfBytesGenerator(new Sha256Digest());

            generator.Init(new HkdfParameters(masterSecret, publicKeys, null));
            generator.GenerateBytes(ClientKey, 0, ClientKey.Length);
            generator.GenerateBytes(ServerKey, 0, ServerKey.Length);
        }
        public MainPage()
        {
            InitializeComponent();

            Curve25519KeyPair identityKey   = new Curve25519KeyPair();
            Curve25519KeyPair signedPreKey  = new Curve25519KeyPair();
            Curve25519KeyPair oneTimePreKey = new Curve25519KeyPair();

            GlobalKeyStore.Initialise(identityKey, new List <Curve25519KeyPair> {
                signedPreKey
            }, new List <Curve25519KeyPair> {
                oneTimePreKey
            }, new Dictionary <string, ChatState>());
        }
Ejemplo n.º 12
0
        private static RemoteAttestation ValidateAndBuildRemoteAttestation(RemoteAttestationResponse response,
                                                                           List <string> cookies,
                                                                           Curve25519KeyPair keyPair,
                                                                           string mrenclave)
        {
            RemoteAttestationKeys keys = new RemoteAttestationKeys(keyPair, response.ServerEphemeralPublic, response.ServerStaticPublic);
            Quote quote = new Quote(response.Quote);

            byte[] requestId = RemoteAttestationCipher.GetRequestId(keys, response);

            RemoteAttestationCipher.VerifyServerQuote(quote, response.ServerStaticPublic, mrenclave);

            RemoteAttestationCipher.VerifyIasSignature(response.Certificates, response.SignatureBody, response.Signature, quote);

            return(new RemoteAttestation(requestId, keys, cookies));
        }
Ejemplo n.º 13
0
        private static async Task <ResponsePair> MakeAttestationRequestAsync(PushServiceSocket socket,
                                                                             PushServiceSocket.ClientSet clientSet,
                                                                             string authorization,
                                                                             string enclaveName,
                                                                             Curve25519KeyPair keyPair)
        {
            RemoteAttestationRequest attestationRequest = new RemoteAttestationRequest(keyPair.getPublicKey());
            HttpResponseMessage      response           = await socket.MakeRequestAsync(clientSet, authorization, new List <string>(), $"/v1/attestation/{enclaveName}", "PUT", JsonUtil.ToJson(attestationRequest));

            HttpContent body = response.Content;

            if (body == null)
            {
                throw new MalformedResponseException("Empty response!");
            }

            return(new ResponsePair(await body.ReadAsStringAsync(), ParseCookies(response)));
        }
Ejemplo n.º 14
0
        public static void Initialise(Curve25519KeyPair identityKeyPair, List <Curve25519KeyPair> signedPreKeyPairs,
                                      List <Curve25519KeyPair> oneTimePreKeyPairs, Dictionary <string, ChatState> chatStates)
        {
            lock (Locker)
            {
                if (!(_instance is null))
                {
                    throw new Exception("GlobalKeyStore has already been initialised");
                }

                _instance = new GlobalKeyStore
                {
                    IdentityKeyPair    = identityKeyPair,
                    SignedPreKeyPairs  = signedPreKeyPairs,
                    OneTimePreKeyPairs = oneTimePreKeyPairs,
                    ChatStates         = chatStates
                };
            }
        }
Ejemplo n.º 15
0
        // Returns the User UUID
        public async Task <string> RegisterUserAsync(string email, Curve25519KeyPair userKeyPair, Curve25519KeyPair signedPreKeyPair, string nickname = null,
                                                     string bio = null)
        {
            Dictionary <string, string> contentDict = new Dictionary <string, string>
            {
                { "email", email },
                { "identity_key", Convert.ToBase64String(userKeyPair.EdPublicKey) },
                { "signed_prekey", Convert.ToBase64String(signedPreKeyPair.XPublicKey) },
                { "prekey_signature", Convert.ToBase64String(userKeyPair.Sign(signedPreKeyPair.XPublicKey)) },
                { "nickname", nickname },
                { "bio", bio }
            };

            HttpResponseMessage response = await PostAuthenticatedAsync("/users/new", contentDict).ConfigureAwait(false);

            Dictionary <string, string> responseDict = await HandleResponse <string>(response).ConfigureAwait(false);

            if (!responseDict.ContainsKey("user_id"))
            {
                throw new ServerConnectionException($"User UUID not found in response content: {responseDict}");
            }

            return(responseDict["user_id"]);
        }
Ejemplo n.º 16
0
        public static MetaMessage ComposeInitialMessage(string recipientUuid, ChatPackage chatPackage, string text)
        {
            Curve25519KeyPair ephemeralKeyPair = new Curve25519KeyPair();

            byte[] secretKey = CryptoUtils.DeriveX3DhSecretSender(GlobalKeyStore.Instance.IdentityKeyPair,
                                                                  ephemeralKeyPair, chatPackage.OtherIdentityKey, chatPackage.OtherSignedPreKey,
                                                                  chatPackage.OtherOneTimePreKey);


            Curve25519KeyPair dhSendingKeyPair = new Curve25519KeyPair();

            (byte[] rootKey, byte[] sendingChainKey) = CryptoUtils.RatchetRootKey(secretKey,
                                                                                  dhSendingKeyPair.CalculateSharedSecret(chatPackage.OtherSignedPreKey));

            ChatState state = new ChatState
            {
                DhSendingKeyPair  = dhSendingKeyPair,
                DhReceivingKey    = chatPackage.OtherSignedPreKey,
                RootKey           = rootKey,
                SendingChainKey   = sendingChainKey,
                ReceivingChainKey = null,
                CountSent         = 0,
                CountReceived     = 0,
                PreviousCount     = 0,
                MissedMessages    = new Dictionary <string, (byte[], byte[])>()
            };

            GlobalKeyStore.Instance.ChatStates[recipientUuid] = state;

            byte[] initialAssociatedData = CryptoUtils.CalculateInitialAssociatedData(
                GlobalKeyStore.Instance.IdentityKeyPair,
                chatPackage.OtherIdentityKey);
            (byte[] encryptedText, MessageHeader header) = RatchetEncrypt(state, Encoding.UTF8.GetBytes(text), initialAssociatedData);

            NormalTextMessage innerPayload = new NormalTextMessage
            {
                AssociatedDataBase64 = Convert.ToBase64String(initialAssociatedData),
                DhKeyBase64          = Convert.ToBase64String(dhSendingKeyPair.XPublicKey),
                EncryptedTextBase64  = Convert.ToBase64String(encryptedText),
                MessageNumber        = header.MessageNumber,
                PreviousCount        = header.PreviousCount
            };

            string innerPayloadJson = JsonConvert.SerializeObject(innerPayload);

            InitialMessage payload = new InitialMessage
            {
                EphemeralKeyBase64           = Convert.ToBase64String(ephemeralKeyPair.XPublicKey),
                InnerMessagePayload          = innerPayloadJson,
                SenderIdentityKeyBase64      = Convert.ToBase64String(GlobalKeyStore.Instance.IdentityKeyPair.EdPublicKey),
                RecipientSignedPreKeyBase64  = Convert.ToBase64String(chatPackage.OtherSignedPreKey.XPublicKey),
                RecipientOneTimePreKeyBase64 = Convert.ToBase64String(chatPackage.OtherOneTimePreKey.XPublicKey)
            };

            string payloadJson = JsonConvert.SerializeObject(payload);

            return(new MetaMessage
            {
                OtherUuid = recipientUuid,
                Type = MessageType.InitialMessage,
                Payload = payloadJson
            });
        }
Ejemplo n.º 17
0
        private static void HandleInitialMessage(MetaMessage metaMessage)
        {
            // TODO actually do database stuff

            string senderUuid = metaMessage.OtherUuid;

            InitialMessage message = JsonConvert.DeserializeObject <InitialMessage>(metaMessage.Payload);

            Curve25519KeyPair otherIdentityKey = new Curve25519KeyPair(Convert.FromBase64String(message.SenderIdentityKeyBase64), false, true);
            Curve25519KeyPair ephemeralKey     = new Curve25519KeyPair(Convert.FromBase64String(message.EphemeralKeyBase64), false, false);

            Curve25519KeyPair receivedSignedPreKey = new Curve25519KeyPair(Convert.FromBase64String(message.RecipientSignedPreKeyBase64), false, false);
            Curve25519KeyPair signedPreKeyPair     = GlobalKeyStore.Instance.SignedPreKeyPairs.Find(pair => pair.XPublicKey.SequenceEqual(receivedSignedPreKey.XPublicKey));

            if (signedPreKeyPair is null)
            {
                throw new Exception("Matching signed prekey pair not found");
            }

            Curve25519KeyPair oneTimePreKeyPair;

            if (message.RecipientOneTimePreKeyBase64 is null)
            {
                oneTimePreKeyPair = null;
            }
            else
            {
                Curve25519KeyPair receivedOneTimePreKey = new Curve25519KeyPair(Convert.FromBase64String(message.RecipientOneTimePreKeyBase64), false, false);
                oneTimePreKeyPair = GlobalKeyStore.Instance.OneTimePreKeyPairs.Find(pair => pair.XPublicKey.SequenceEqual(receivedOneTimePreKey.XPublicKey));

                if (oneTimePreKeyPair is null)
                {
                    throw new Exception("Matching one-time prekey pair not found");
                }

                // Remove the one-time key, never to be used again
                GlobalKeyStore.Instance.SignedPreKeyPairs.Remove(oneTimePreKeyPair);
            }

            byte[] secretKey = CryptoUtils.DeriveX3DhSecretReceiver(GlobalKeyStore.Instance.IdentityKeyPair,
                                                                    signedPreKeyPair, otherIdentityKey, ephemeralKey, oneTimePreKeyPair);

            GlobalKeyStore.Instance.ChatStates[senderUuid] = new ChatState
            {
                DhSendingKeyPair  = signedPreKeyPair,
                DhReceivingKey    = null,
                RootKey           = secretKey,
                SendingChainKey   = null,
                ReceivingChainKey = null,
                CountSent         = 0,
                CountReceived     = 0,
                PreviousCount     = 0,
                MissedMessages    = new Dictionary <string, (byte[], byte[])>()
            };

            MetaMessage innerMetaMessage = new MetaMessage
            {
                OtherUuid = metaMessage.OtherUuid,
                Type      = MessageType.NormalTextMessage,
                Payload   = message.InnerMessagePayload,
                Timestamp = metaMessage.Timestamp
            };

            NormalTextMessage innerMessage = JsonConvert.DeserializeObject <NormalTextMessage>(innerMetaMessage.Payload);
            string            requiredAssociatedDataBase64 = Convert.ToBase64String(
                CryptoUtils.CalculateInitialAssociatedData(otherIdentityKey, GlobalKeyStore.Instance.IdentityKeyPair));

            if (innerMessage.AssociatedDataBase64 != requiredAssociatedDataBase64)
            {
                throw new Exception($"Associated data for the initial message isn't what it should be: {innerMessage.AssociatedDataBase64} != {requiredAssociatedDataBase64}");
            }

            HandleNormalTextMessage(innerMetaMessage);
        }