use of org.whispersystems.libsignal.InvalidKeyIdException in project toshi-android-client by toshiapp.
the class PreKeyUtil method generateLastResortKey.
public static PreKeyRecord generateLastResortKey(Context context) {
PreKeyStore preKeyStore = new SignalPreKeyStore();
if (preKeyStore.containsPreKey(Medium.MAX_VALUE)) {
try {
return preKeyStore.loadPreKey(Medium.MAX_VALUE);
} catch (InvalidKeyIdException e) {
LogUtil.exception("Error while generating last resort key", e);
preKeyStore.removePreKey(Medium.MAX_VALUE);
}
}
ECKeyPair keyPair = Curve.generateKeyPair();
PreKeyRecord record = new PreKeyRecord(Medium.MAX_VALUE, keyPair);
preKeyStore.storePreKey(Medium.MAX_VALUE, record);
return record;
}
use of org.whispersystems.libsignal.InvalidKeyIdException in project Pix-Art-Messenger by kriztan.
the class AxolotlService method publishBundlesIfNeeded.
public void publishBundlesIfNeeded(final boolean announce, final boolean wipe) {
if (pepBroken) {
Log.d(Config.LOGTAG, getLogprefix(account) + "publishBundlesIfNeeded called, but PEP is broken. Ignoring... ");
return;
}
if (account.getXmppConnection().getFeatures().pepPublishOptions()) {
this.changeAccessMode.set(account.isOptionSet(Account.OPTION_REQUIRES_ACCESS_MODE_CHANGE));
} else {
if (account.setOption(Account.OPTION_REQUIRES_ACCESS_MODE_CHANGE, true)) {
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": server doesn’t support publish-options. setting for later access mode change");
mXmppConnectionService.databaseBackend.updateAccount(account);
}
}
if (this.changeAccessMode.get()) {
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": server gained publish-options capabilities. changing access model");
}
IqPacket packet = mXmppConnectionService.getIqGenerator().retrieveBundlesForDevice(account.getJid().toBareJid(), getOwnDeviceId());
mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() {
@Override
public void onIqPacketReceived(Account account, IqPacket packet) {
if (packet.getType() == IqPacket.TYPE.TIMEOUT) {
// ignore timeout. do nothing
return;
}
if (packet.getType() == IqPacket.TYPE.ERROR) {
Element error = packet.findChild("error");
if (error == null || !error.hasChild("item-not-found")) {
pepBroken = true;
Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "request for device bundles came back with something other than item-not-found" + packet);
return;
}
}
PreKeyBundle bundle = mXmppConnectionService.getIqParser().bundle(packet);
Map<Integer, ECPublicKey> keys = mXmppConnectionService.getIqParser().preKeyPublics(packet);
boolean flush = false;
if (bundle == null) {
Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received invalid bundle:" + packet);
bundle = new PreKeyBundle(-1, -1, -1, null, -1, null, null, null);
flush = true;
}
if (keys == null) {
Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received invalid prekeys:" + packet);
}
try {
boolean changed = false;
// Validate IdentityKey
IdentityKeyPair identityKeyPair = axolotlStore.getIdentityKeyPair();
if (flush || !identityKeyPair.getPublicKey().equals(bundle.getIdentityKey())) {
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding own IdentityKey " + identityKeyPair.getPublicKey() + " to PEP.");
changed = true;
}
// Validate signedPreKeyRecord + ID
SignedPreKeyRecord signedPreKeyRecord;
int numSignedPreKeys = axolotlStore.getSignedPreKeysCount();
try {
signedPreKeyRecord = axolotlStore.loadSignedPreKey(bundle.getSignedPreKeyId());
if (flush || !bundle.getSignedPreKey().equals(signedPreKeyRecord.getKeyPair().getPublicKey()) || !Arrays.equals(bundle.getSignedPreKeySignature(), signedPreKeyRecord.getSignature())) {
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding new signedPreKey with ID " + (numSignedPreKeys + 1) + " to PEP.");
signedPreKeyRecord = KeyHelper.generateSignedPreKey(identityKeyPair, numSignedPreKeys + 1);
axolotlStore.storeSignedPreKey(signedPreKeyRecord.getId(), signedPreKeyRecord);
changed = true;
}
} catch (InvalidKeyIdException e) {
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding new signedPreKey with ID " + (numSignedPreKeys + 1) + " to PEP.");
signedPreKeyRecord = KeyHelper.generateSignedPreKey(identityKeyPair, numSignedPreKeys + 1);
axolotlStore.storeSignedPreKey(signedPreKeyRecord.getId(), signedPreKeyRecord);
changed = true;
}
// Validate PreKeys
Set<PreKeyRecord> preKeyRecords = new HashSet<>();
if (keys != null) {
for (Integer id : keys.keySet()) {
try {
PreKeyRecord preKeyRecord = axolotlStore.loadPreKey(id);
if (preKeyRecord.getKeyPair().getPublicKey().equals(keys.get(id))) {
preKeyRecords.add(preKeyRecord);
}
} catch (InvalidKeyIdException ignored) {
}
}
}
int newKeys = NUM_KEYS_TO_PUBLISH - preKeyRecords.size();
if (newKeys > 0) {
List<PreKeyRecord> newRecords = KeyHelper.generatePreKeys(axolotlStore.getCurrentPreKeyId() + 1, newKeys);
preKeyRecords.addAll(newRecords);
for (PreKeyRecord record : newRecords) {
axolotlStore.storePreKey(record.getId(), record);
}
changed = true;
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding " + newKeys + " new preKeys to PEP.");
}
if (changed || changeAccessMode.get()) {
if (account.getPrivateKeyAlias() != null && Config.X509_VERIFICATION) {
mXmppConnectionService.publishDisplayName(account);
publishDeviceVerificationAndBundle(signedPreKeyRecord, preKeyRecords, announce, wipe);
} else {
publishDeviceBundle(signedPreKeyRecord, preKeyRecords, announce, wipe);
}
} else {
Log.d(Config.LOGTAG, getLogprefix(account) + "Bundle " + getOwnDeviceId() + " in PEP was current");
if (wipe) {
wipeOtherPepDevices();
} else if (announce) {
Log.d(Config.LOGTAG, getLogprefix(account) + "Announcing device " + getOwnDeviceId());
publishOwnDeviceIdIfNeeded();
}
}
} catch (InvalidKeyException e) {
Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Failed to publish bundle " + getOwnDeviceId() + ", reason: " + e.getMessage());
}
}
});
}
use of org.whispersystems.libsignal.InvalidKeyIdException in project Smack by igniterealtime.
the class SignalOmemoRatchet method doubleRatchetDecrypt.
@Override
public byte[] doubleRatchetDecrypt(OmemoDevice sender, byte[] encryptedKey) throws CorruptedOmemoKeyException, NoRawSessionException, CryptoFailedException, UntrustedOmemoIdentityException, IOException {
SessionCipher cipher = getCipher(sender);
byte[] decryptedKey;
// Try to handle the message as a PreKeySignalMessage...
try {
PreKeySignalMessage preKeyMessage = new PreKeySignalMessage(encryptedKey);
if (!preKeyMessage.getPreKeyId().isPresent()) {
throw new CryptoFailedException("PreKeyMessage did not contain a preKeyId.");
}
IdentityKey messageIdentityKey = preKeyMessage.getIdentityKey();
IdentityKey previousIdentityKey = store.loadOmemoIdentityKey(storeConnector.getOurDevice(), sender);
if (previousIdentityKey != null && !previousIdentityKey.getFingerprint().equals(messageIdentityKey.getFingerprint())) {
throw new UntrustedOmemoIdentityException(sender, store.keyUtil().getFingerprintOfIdentityKey(previousIdentityKey), store.keyUtil().getFingerprintOfIdentityKey(messageIdentityKey));
}
try {
decryptedKey = cipher.decrypt(preKeyMessage);
} catch (UntrustedIdentityException e) {
throw new AssertionError("Signals trust management MUST be disabled.");
} catch (LegacyMessageException | InvalidKeyException e) {
throw new CryptoFailedException(e);
} catch (InvalidKeyIdException e) {
throw new NoRawSessionException(sender, e);
} catch (DuplicateMessageException e) {
LOGGER.log(Level.INFO, "Decryption of PreKeyMessage from " + sender + " failed, since the message has been decrypted before.");
return null;
}
} catch (InvalidVersionException | InvalidMessageException noPreKeyMessage) {
// ...if that fails, handle it as a SignalMessage
try {
SignalMessage message = new SignalMessage(encryptedKey);
decryptedKey = getCipher(sender).decrypt(message);
} catch (UntrustedIdentityException e) {
throw new AssertionError("Signals trust management MUST be disabled.");
} catch (InvalidMessageException | NoSessionException e) {
throw new NoRawSessionException(sender, e);
} catch (LegacyMessageException e) {
throw new CryptoFailedException(e);
} catch (DuplicateMessageException e1) {
LOGGER.log(Level.INFO, "Decryption of SignalMessage from " + sender + " failed, since the message has been decrypted before.");
return null;
}
}
return decryptedKey;
}
use of org.whispersystems.libsignal.InvalidKeyIdException in project Conversations by siacs.
the class XmppAxolotlSession method processReceiving.
@Nullable
byte[] processReceiving(List<AxolotlKey> possibleKeys) throws CryptoFailedException {
byte[] plaintext = null;
FingerprintStatus status = getTrust();
if (!status.isCompromised()) {
Iterator<AxolotlKey> iterator = possibleKeys.iterator();
while (iterator.hasNext()) {
AxolotlKey encryptedKey = iterator.next();
try {
if (encryptedKey.prekey) {
PreKeySignalMessage preKeySignalMessage = new PreKeySignalMessage(encryptedKey.key);
Optional<Integer> optionalPreKeyId = preKeySignalMessage.getPreKeyId();
IdentityKey identityKey = preKeySignalMessage.getIdentityKey();
if (!optionalPreKeyId.isPresent()) {
if (iterator.hasNext()) {
continue;
}
throw new CryptoFailedException("PreKeyWhisperMessage did not contain a PreKeyId");
}
preKeyId = optionalPreKeyId.get();
if (this.identityKey != null && !this.identityKey.equals(identityKey)) {
if (iterator.hasNext()) {
continue;
}
throw new CryptoFailedException("Received PreKeyWhisperMessage but preexisting identity key changed.");
}
this.identityKey = identityKey;
plaintext = cipher.decrypt(preKeySignalMessage);
} else {
SignalMessage signalMessage = new SignalMessage(encryptedKey.key);
try {
plaintext = cipher.decrypt(signalMessage);
} catch (InvalidMessageException | NoSessionException e) {
if (iterator.hasNext()) {
Log.w(Config.LOGTAG, account.getJid().asBareJid() + ": ignoring crypto exception because possible keys left to try", e);
continue;
}
throw new BrokenSessionException(this.remoteAddress, e);
}
// better safe than sorry because we use that to do special after prekey handling
preKeyId = null;
}
} catch (InvalidVersionException | InvalidKeyException | LegacyMessageException | InvalidMessageException | DuplicateMessageException | InvalidKeyIdException | UntrustedIdentityException e) {
if (iterator.hasNext()) {
Log.w(Config.LOGTAG, account.getJid().asBareJid() + ": ignoring crypto exception because possible keys left to try", e);
continue;
}
throw new CryptoFailedException("Error decrypting SignalMessage", e);
}
if (iterator.hasNext()) {
break;
}
}
if (!status.isActive()) {
setTrust(status.toActive());
// TODO: also (re)add to device list?
}
} else {
throw new CryptoFailedException("not encrypting omemo message from fingerprint " + getFingerprint() + " because it was marked as compromised");
}
return plaintext;
}
use of org.whispersystems.libsignal.InvalidKeyIdException in project Signal-Android by WhisperSystems.
the class PreKeyUtil method cleanSignedPreKeys.
/**
* Finds all of the signed prekeys that are older than the archive age, and archive all but the youngest of those.
*/
public static synchronized void cleanSignedPreKeys(@NonNull SignalProtocolStore protocolStore, @NonNull PreKeyMetadataStore metadataStore) {
Log.i(TAG, "Cleaning signed prekeys...");
int activeSignedPreKeyId = metadataStore.getActiveSignedPreKeyId();
if (activeSignedPreKeyId < 0) {
return;
}
try {
long now = System.currentTimeMillis();
SignedPreKeyRecord currentRecord = protocolStore.loadSignedPreKey(activeSignedPreKeyId);
List<SignedPreKeyRecord> allRecords = protocolStore.loadSignedPreKeys();
allRecords.stream().filter(r -> r.getId() != currentRecord.getId()).filter(r -> (now - r.getTimestamp()) > ARCHIVE_AGE).sorted(Comparator.comparingLong(SignedPreKeyRecord::getTimestamp).reversed()).skip(1).forEach(record -> {
Log.i(TAG, "Removing signed prekey record: " + record.getId() + " with timestamp: " + record.getTimestamp());
protocolStore.removeSignedPreKey(record.getId());
});
} catch (InvalidKeyIdException e) {
Log.w(TAG, e);
}
}
Aggregations