use of org.whispersystems.signalservice.internal.contacts.entities.DiscoveryRequest in project Signal-Android by WhisperSystems.
the class ContactDiscoveryCipher method createDiscoveryRequest.
public static DiscoveryRequest createDiscoveryRequest(List<String> addressBook, Map<String, RemoteAttestation> remoteAttestations) {
byte[] queryDataKey = Util.getSecretBytes(32);
byte[] queryData = buildQueryData(addressBook);
AESEncryptedResult encryptedQueryData = AESCipher.encrypt(queryDataKey, null, queryData);
byte[] commitment = CryptoUtil.sha256(queryData);
Map<String, QueryEnvelope> envelopes = new HashMap<>(remoteAttestations.size());
for (Map.Entry<String, RemoteAttestation> entry : remoteAttestations.entrySet()) {
envelopes.put(entry.getKey(), buildQueryEnvelope(entry.getValue().getRequestId(), entry.getValue().getKeys().getClientKey(), queryDataKey));
}
return new DiscoveryRequest(addressBook.size(), commitment, encryptedQueryData.iv, encryptedQueryData.data, encryptedQueryData.mac, envelopes);
}
use of org.whispersystems.signalservice.internal.contacts.entities.DiscoveryRequest in project libsignal-service-java by signalapp.
the class SignalServiceAccountManager method getRegisteredUsers.
public List<String> getRegisteredUsers(KeyStore iasKeyStore, Set<String> e164numbers, String mrenclave) throws IOException, Quote.InvalidQuoteFormatException, UnauthenticatedQuoteException, SignatureException, UnauthenticatedResponseException {
try {
String authorization = this.pushServiceSocket.getContactDiscoveryAuthorization();
Curve25519 curve = Curve25519.getInstance(Curve25519.BEST);
Curve25519KeyPair keyPair = curve.generateKeyPair();
ContactDiscoveryCipher cipher = new ContactDiscoveryCipher();
RemoteAttestationRequest attestationRequest = new RemoteAttestationRequest(keyPair.getPublicKey());
Pair<RemoteAttestationResponse, List<String>> attestationResponse = this.pushServiceSocket.getContactDiscoveryRemoteAttestation(authorization, attestationRequest, mrenclave);
RemoteAttestationKeys keys = new RemoteAttestationKeys(keyPair, attestationResponse.first().getServerEphemeralPublic(), attestationResponse.first().getServerStaticPublic());
Quote quote = new Quote(attestationResponse.first().getQuote());
byte[] requestId = cipher.getRequestId(keys, attestationResponse.first());
cipher.verifyServerQuote(quote, attestationResponse.first().getServerStaticPublic(), mrenclave);
cipher.verifyIasSignature(iasKeyStore, attestationResponse.first().getCertificates(), attestationResponse.first().getSignatureBody(), attestationResponse.first().getSignature(), quote);
RemoteAttestation remoteAttestation = new RemoteAttestation(requestId, keys);
List<String> addressBook = new LinkedList<>();
for (String e164number : e164numbers) {
addressBook.add(e164number.substring(1));
}
DiscoveryRequest request = cipher.createDiscoveryRequest(addressBook, remoteAttestation);
DiscoveryResponse response = this.pushServiceSocket.getContactDiscoveryRegisteredUsers(authorization, request, attestationResponse.second(), mrenclave);
byte[] data = cipher.getDiscoveryResponseData(response, remoteAttestation);
Iterator<String> addressBookIterator = addressBook.iterator();
List<String> results = new LinkedList<>();
for (byte aData : data) {
String candidate = addressBookIterator.next();
if (aData != 0)
results.add('+' + candidate);
}
return results;
} catch (InvalidCiphertextException e) {
throw new UnauthenticatedResponseException(e);
}
}
use of org.whispersystems.signalservice.internal.contacts.entities.DiscoveryRequest in project Signal-Android by WhisperSystems.
the class SignalServiceAccountManager method getRegisteredUsers.
@SuppressWarnings("SameParameterValue")
public Map<String, ACI> getRegisteredUsers(KeyStore iasKeyStore, Set<String> e164numbers, String mrenclave) throws IOException, Quote.InvalidQuoteFormatException, UnauthenticatedQuoteException, SignatureException, UnauthenticatedResponseException, InvalidKeyException {
if (e164numbers.isEmpty()) {
return Collections.emptyMap();
}
try {
String authorization = this.pushServiceSocket.getContactDiscoveryAuthorization();
Map<String, RemoteAttestation> attestations = RemoteAttestationUtil.getAndVerifyMultiRemoteAttestation(pushServiceSocket, PushServiceSocket.ClientSet.ContactDiscovery, iasKeyStore, mrenclave, mrenclave, authorization);
List<String> addressBook = new ArrayList<>(e164numbers.size());
for (String e164number : e164numbers) {
addressBook.add(e164number.substring(1));
}
List<String> cookies = attestations.values().iterator().next().getCookies();
DiscoveryRequest request = ContactDiscoveryCipher.createDiscoveryRequest(addressBook, attestations);
DiscoveryResponse response = this.pushServiceSocket.getContactDiscoveryRegisteredUsers(authorization, request, cookies, mrenclave);
byte[] data = ContactDiscoveryCipher.getDiscoveryResponseData(response, attestations.values());
HashMap<String, ACI> results = new HashMap<>(addressBook.size());
DataInputStream uuidInputStream = new DataInputStream(new ByteArrayInputStream(data));
for (String candidate : addressBook) {
long candidateUuidHigh = uuidInputStream.readLong();
long candidateUuidLow = uuidInputStream.readLong();
if (candidateUuidHigh != 0 || candidateUuidLow != 0) {
results.put('+' + candidate, ACI.from(new UUID(candidateUuidHigh, candidateUuidLow)));
}
}
return results;
} catch (InvalidCiphertextException e) {
throw new UnauthenticatedResponseException(e);
}
}
use of org.whispersystems.signalservice.internal.contacts.entities.DiscoveryRequest in project Signal-Android by signalapp.
the class SignalServiceAccountManager method getRegisteredUsers.
@SuppressWarnings("SameParameterValue")
public Map<String, ACI> getRegisteredUsers(KeyStore iasKeyStore, Set<String> e164numbers, String mrenclave) throws IOException, Quote.InvalidQuoteFormatException, UnauthenticatedQuoteException, SignatureException, UnauthenticatedResponseException, InvalidKeyException {
if (e164numbers.isEmpty()) {
return Collections.emptyMap();
}
try {
String authorization = this.pushServiceSocket.getContactDiscoveryAuthorization();
Map<String, RemoteAttestation> attestations = RemoteAttestationUtil.getAndVerifyMultiRemoteAttestation(pushServiceSocket, PushServiceSocket.ClientSet.ContactDiscovery, iasKeyStore, mrenclave, mrenclave, authorization);
List<String> addressBook = new ArrayList<>(e164numbers.size());
for (String e164number : e164numbers) {
addressBook.add(e164number.substring(1));
}
List<String> cookies = attestations.values().iterator().next().getCookies();
DiscoveryRequest request = ContactDiscoveryCipher.createDiscoveryRequest(addressBook, attestations);
DiscoveryResponse response = this.pushServiceSocket.getContactDiscoveryRegisteredUsers(authorization, request, cookies, mrenclave);
byte[] data = ContactDiscoveryCipher.getDiscoveryResponseData(response, attestations.values());
HashMap<String, ACI> results = new HashMap<>(addressBook.size());
DataInputStream uuidInputStream = new DataInputStream(new ByteArrayInputStream(data));
for (String candidate : addressBook) {
long candidateUuidHigh = uuidInputStream.readLong();
long candidateUuidLow = uuidInputStream.readLong();
if (candidateUuidHigh != 0 || candidateUuidLow != 0) {
results.put('+' + candidate, ACI.from(new UUID(candidateUuidHigh, candidateUuidLow)));
}
}
return results;
} catch (InvalidCiphertextException e) {
throw new UnauthenticatedResponseException(e);
}
}
use of org.whispersystems.signalservice.internal.contacts.entities.DiscoveryRequest in project libsignal-service-java by signalapp.
the class ContactDiscoveryCipher method createDiscoveryRequest.
public DiscoveryRequest createDiscoveryRequest(List<String> addressBook, RemoteAttestation remoteAttestation) {
try {
ByteArrayOutputStream requestDataStream = new ByteArrayOutputStream();
for (String address : addressBook) {
requestDataStream.write(ByteUtil.longToByteArray(Long.parseLong(address)));
}
byte[] requestData = requestDataStream.toByteArray();
byte[] nonce = Util.getSecretBytes(12);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(remoteAttestation.getKeys().getClientKey(), "AES"), new GCMParameterSpec(TAG_LENGTH_BITS, nonce));
cipher.updateAAD(remoteAttestation.getRequestId());
byte[] cipherText = cipher.doFinal(requestData);
byte[][] parts = ByteUtil.split(cipherText, cipherText.length - TAG_LENGTH_BYTES, TAG_LENGTH_BYTES);
return new DiscoveryRequest(addressBook.size(), remoteAttestation.getRequestId(), nonce, parts[0], parts[1]);
} catch (IOException | NoSuchAlgorithmException | InvalidKeyException | NoSuchPaddingException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
throw new AssertionError(e);
}
}
Aggregations