Add some more tests

This adds tests for all of the importers, a new scrypt test and some more OTP tests. More to come.
This commit is contained in:
Alexander Bakker 2020-12-16 21:44:37 +01:00
parent dea13f56f5
commit 4f8a0b9020
40 changed files with 974 additions and 321 deletions

View file

@ -1,43 +0,0 @@
package com.beemdevelopment.aegis;
import com.beemdevelopment.aegis.crypto.CryptoUtils;
import com.beemdevelopment.aegis.crypto.SCryptParameters;
import com.beemdevelopment.aegis.encoding.EncodingException;
import com.beemdevelopment.aegis.encoding.Hex;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import javax.crypto.SecretKey;
import static org.junit.jupiter.api.Assertions.*;
public class SCryptTest {
@Test
public void testTrailingNullCollision() throws EncodingException {
byte[] salt = new byte[0];
SCryptParameters params = new SCryptParameters(
CryptoUtils.CRYPTO_SCRYPT_N,
CryptoUtils.CRYPTO_SCRYPT_p,
CryptoUtils.CRYPTO_SCRYPT_r,
salt
);
byte[] head = new byte[]{'t', 'e', 's', 't'};
byte[] expectedKey = Hex.decode("41cd8110d0c66ede16f97ce84fd8e2bd2269c9318532a01437789dfbadd1392e");
for (int i = 0; i < 128; i += 4) {
byte[] input = new byte[head.length + i];
System.arraycopy(head, 0, input, 0, head.length);
// once the length of the input is over 64 bytes, trailing nulls do not cause a collision anymore
SecretKey key = CryptoUtils.deriveKey(input, params);
if (input.length <= 64) {
assertArrayEquals(expectedKey, key.getEncoded());
} else {
assertFalse(Arrays.equals(expectedKey, key.getEncoded()));
}
}
}
}

View file

@ -0,0 +1,88 @@
package com.beemdevelopment.aegis.crypto;
import com.beemdevelopment.aegis.encoding.EncodingException;
import com.beemdevelopment.aegis.encoding.Hex;
import org.bouncycastle.crypto.generators.SCrypt;
import org.junit.Test;
import java.util.Arrays;
import javax.crypto.SecretKey;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertFalse;
public class SCryptTest {
private static class Vector {
private final byte[] _key;
private final char[] _password;
private final byte[] _salt;
private final int _n;
private final int _r;
private final int _p;
private final int _len;
public Vector(String key, String password, String salt, int n, int r, int p, int len) throws EncodingException {
_key = Hex.decode(key);
_password = password.toCharArray();
_salt = CryptoUtils.toBytes(salt.toCharArray());
_n = n;
_r = r;
_p = p;
_len = len;
}
public void validate() {
SCryptParameters params = new SCryptParameters(_n, _r, _p, _salt);
byte[] key = SCrypt.generate(CryptoUtils.toBytes(_password), params.getSalt(), params.getN(), params.getR(), params.getP(), _len);
assertArrayEquals(_key, key);
}
}
@Test
public void vectorsMatch() throws EncodingException {
// https://tools.ietf.org/html/rfc7914.html#section-12
final Vector[] vectors = new Vector[]{
new Vector("77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906",
"", "", 1 << 4, 1, 1, 64),
new Vector("fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640",
"password", "NaCl", 1 << 10, 8, 16, 64),
new Vector("7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887",
"pleaseletmein", "SodiumChloride", 1 << 14, 8, 1, 64),
new Vector("2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049e8a952fbcbf45c6fa77a41a4",
"pleaseletmein", "SodiumChloride", 1 << 20, 8, 1, 64)
};
for (Vector vector : vectors) {
vector.validate();
}
}
@Test
public void testTrailingNullCollision() throws EncodingException {
byte[] salt = new byte[0];
SCryptParameters params = new SCryptParameters(
CryptoUtils.CRYPTO_SCRYPT_N,
CryptoUtils.CRYPTO_SCRYPT_p,
CryptoUtils.CRYPTO_SCRYPT_r,
salt
);
byte[] head = new byte[]{'t', 'e', 's', 't'};
byte[] expectedKey = Hex.decode("41cd8110d0c66ede16f97ce84fd8e2bd2269c9318532a01437789dfbadd1392e");
for (int i = 0; i < 128; i += 4) {
byte[] input = new byte[head.length + i];
System.arraycopy(head, 0, input, 0, head.length);
// once the length of the input is over 64 bytes, trailing nulls do not cause a collision anymore
SecretKey key = CryptoUtils.deriveKey(input, params);
if (input.length <= 64) {
assertArrayEquals(expectedKey, key.getEncoded());
} else {
assertFalse(Arrays.equals(expectedKey, key.getEncoded()));
}
}
}
}

View file

@ -1,18 +1,15 @@
package com.beemdevelopment.aegis;
package com.beemdevelopment.aegis.crypto.otp;
import com.beemdevelopment.aegis.crypto.otp.HOTP;
import com.beemdevelopment.aegis.crypto.otp.OTP;
import org.junit.jupiter.api.Test;
import org.junit.Test;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.Assert.assertEquals;
public class HOTPTest {
// https://tools.ietf.org/html/rfc4226#page-32
private final String[] _vectors = {
public static final String[] VECTORS = {
"755224", "287082",
"359152", "969429",
"338314", "254676",
@ -20,16 +17,16 @@ public class HOTPTest {
"399871", "520489"
};
private final byte[] _secret = new byte[]{
public static final byte[] SECRET = new byte[]{
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30,
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30
};
@Test
public void vectorsMatch() throws InvalidKeyException, NoSuchAlgorithmException {
for (int i = 0; i < _vectors.length; i++) {
OTP otp = HOTP.generateOTP(_secret, "HmacSHA1", 6, i);
assertEquals(_vectors[i], otp.toString());
for (int i = 0; i < VECTORS.length; i++) {
OTP otp = HOTP.generateOTP(SECRET, "HmacSHA1", 6, i);
assertEquals(VECTORS[i], otp.toString());
}
}
}

View file

@ -1,18 +1,14 @@
package com.beemdevelopment.aegis;
package com.beemdevelopment.aegis.crypto.otp;
import com.beemdevelopment.aegis.crypto.otp.OTP;
import com.beemdevelopment.aegis.crypto.otp.TOTP;
import org.junit.jupiter.api.Test;
import org.junit.Test;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.Assert.assertEquals;
public class TOTPTest {
private static class Vector {
public static class Vector {
public long Time;
public String OTP;
public String Algo;
@ -25,7 +21,7 @@ public class TOTPTest {
}
// https://tools.ietf.org/html/rfc6238#appendix-B
private final Vector[] _vectors = {
public static final Vector[] VECTORS = {
new Vector(59, "94287082", "HmacSHA1"),
new Vector(59, "46119246", "HmacSHA256"),
new Vector(59, "90693936", "HmacSHA512"),
@ -46,19 +42,19 @@ public class TOTPTest {
new Vector(20000000000L, "47863826", "HmacSHA512")
};
private final byte[] _seed = new byte[]{
private static final byte[] SEED = new byte[]{
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30,
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30
};
private final byte[] _seed32 = new byte[]{
private static final byte[] SEED32 = new byte[]{
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34,
0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32
};
private final byte[] _seed64 = new byte[]{
private static final byte[] SEED64 = new byte[]{
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32,
0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
@ -67,26 +63,23 @@ public class TOTPTest {
@Test
public void vectorsMatch() throws NoSuchAlgorithmException, InvalidKeyException {
for (Vector vector : _vectors) {
byte[] seed;
switch (vector.Algo) {
case "HmacSHA1":
seed = _seed;
break;
case "HmacSHA256":
seed = _seed32;
break;
case "HmacSHA512":
seed = _seed64;
break;
default:
fail("unsupported mode");
return;
}
for (Vector vector : VECTORS) {
byte[] seed = getSeed(vector.Algo);
OTP otp = TOTP.generateOTP(seed, vector.Algo, 8, 30, vector.Time);
assertEquals(vector.OTP, otp.toString());
}
}
public static byte[] getSeed(String algorithm) {
switch (algorithm) {
case "HmacSHA1":
return SEED;
case "HmacSHA256":
return SEED32;
case "HmacSHA512":
return SEED64;
default:
throw new RuntimeException(String.format("Unsupported algorithm: %s", algorithm));
}
}
}

View file

@ -0,0 +1,331 @@
package com.beemdevelopment.aegis.importers;
import android.content.Context;
import android.os.Build;
import androidx.test.core.app.ApplicationProvider;
import com.beemdevelopment.aegis.encoding.Base32;
import com.beemdevelopment.aegis.encoding.EncodingException;
import com.beemdevelopment.aegis.otp.HotpInfo;
import com.beemdevelopment.aegis.otp.OtpInfoException;
import com.beemdevelopment.aegis.otp.SteamInfo;
import com.beemdevelopment.aegis.otp.TotpInfo;
import com.beemdevelopment.aegis.util.UUIDMap;
import com.beemdevelopment.aegis.vault.VaultEntry;
import com.google.common.collect.Lists;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@Config(sdk = { Build.VERSION_CODES.P })
@RunWith(RobolectricTestRunner.class)
public class DatabaseImporterTest {
private List<VaultEntry> _vectors;
/**
* The procedure for adding new importer tests is as follows:
* 1. Generate QR codes for each test vector:
* -> while read line; do (qrencode "$line" -o - | feh -); done < ./app/src/test/resources/com/beemdevelopment/aegis/importers/plain
* 2. Scan the QR codes with the app we want to test our import functionality of
* 3. Create an export and add the file to the importers resource directory.
* 4. Add a new test for it here.
*/
@Before
public void initVectors() throws EncodingException, OtpInfoException {
_vectors = Lists.newArrayList(
new VaultEntry(new TotpInfo(Base32.decode("4SJHB4GSD43FZBAI7C2HLRJGPQ")), "Mason", "Deno"),
new VaultEntry(new TotpInfo(Base32.decode("5OM4WOOGPLQEF6UGN3CPEOOLWU"), "SHA256", 7, 20), "James", "SPDX"),
new VaultEntry(new TotpInfo(Base32.decode("7ELGJSGXNCCTV3O6LKJWYFV2RA"), "SHA512", 8, 50), "Elijah", "Airbnb"),
new VaultEntry(new HotpInfo(Base32.decode("YOOMIXWS5GN6RTBPUFFWKTW5M4"), "SHA1", 6, 1), "James", "Issuu"),
new VaultEntry(new HotpInfo(Base32.decode("KUVJJOM753IHTNDSZVCNKL7GII"), "SHA256", 7, 50), "Benjamin", "Air Canada"),
new VaultEntry(new HotpInfo(Base32.decode("5VAML3X35THCEBVRLV24CGBKOY"), "SHA512", 8, 10300), "Mason", "WWE"),
new VaultEntry(new SteamInfo(Base32.decode("JRZCL47CMXVOQMNPZR2F7J4RGI"), "SHA1", 5, 30), "Sophia", "Boeing")
);
}
@Test
public void testImportPlainText() throws IOException, DatabaseImporterException {
List<VaultEntry> entries = importPlain(GoogleAuthUriImporter.class, "plain.txt");
checkImportedEntries(entries);
}
@Test
public void testImportAegisPlain() throws IOException, DatabaseImporterException {
List<VaultEntry> entries = importPlain(AegisImporter.class, "aegis_plain.json");
checkImportedEntries(entries);
}
@Test
public void testImportAegisEncrypted() throws IOException, DatabaseImporterException {
List<VaultEntry> entries = importEncrypted(AegisImporter.class, "aegis_encrypted.json", encryptedState -> {
final char[] password = "test".toCharArray();
return ((AegisImporter.EncryptedState) encryptedState).decrypt(password);
});
checkImportedEntries(entries);
}
@Test
public void testImportWinAuth() throws IOException, DatabaseImporterException {
List<VaultEntry> entries = importPlain(WinAuthImporter.class, "plain.txt");
for (VaultEntry entry : entries) {
VaultEntry entryVector = getEntryVectorBySecret(entry.getInfo().getSecret());
entryVector.setIssuer(entryVector.getName());
entryVector.setName("WinAuth");
checkImportedEntry(entryVector, entry);
}
}
@Test
public void testImportAndOTP() throws IOException, DatabaseImporterException {
List<VaultEntry> entries = importPlain(AndOtpImporter.class, "andotp_plain.json");
checkImportedEntries(entries);
}
@Test
public void testImportAndOTPEncrypted() throws IOException, DatabaseImporterException {
List<VaultEntry> entries = importEncrypted(AndOtpImporter.class, "andotp_encrypted.bin", encryptedState -> {
final char[] password = "test".toCharArray();
return ((AndOtpImporter.EncryptedState) encryptedState).decryptNewFormat(password);
});
checkImportedEntries(entries);
}
@Test
public void testImportAndOTPEncryptedOld() throws IOException, DatabaseImporterException {
List<VaultEntry> entries = importEncrypted(AndOtpImporter.class, "andotp_encrypted_old.bin", encryptedState -> {
final char[] password = "test".toCharArray();
return ((AndOtpImporter.EncryptedState) encryptedState).decryptOldFormat(password);
});
for (VaultEntry entry : entries) {
// old versions of andOTP have a bug where the issuer/name is not parsed correctly, so account for that here
VaultEntry entryVector = getEntryVectorBySecret(entry.getInfo().getSecret());
entryVector.setName(String.format("%s:%s", entryVector.getIssuer(), entryVector.getName()));
checkImportedEntry(entryVector, entry);
}
}
@Test
public void testImportTotpAuthenticator() throws IOException, DatabaseImporterException, OtpInfoException {
List<VaultEntry> entries = importEncrypted(TotpAuthenticatorImporter.class, "totp_authenticator.bin", encryptedState -> {
final char[] password = "Testtest1".toCharArray();
return ((TotpAuthenticatorImporter.EncryptedState) encryptedState).decrypt(password);
});
checkImportedTotpAuthenticatorEntries(entries);
}
@Test
public void testImportTotpAuthenticatorInternal() throws IOException, DatabaseImporterException, OtpInfoException {
List<VaultEntry> entries = importPlain(TotpAuthenticatorImporter.class, "totp_authenticator_internal.xml", true);
checkImportedTotpAuthenticatorEntries(entries);
}
@Test
public void testImportAuthy() throws IOException, DatabaseImporterException, OtpInfoException {
List<VaultEntry> entries = importPlain(AuthyImporter.class, "authy_plain.xml");
checkImportedAuthyEntries(entries);
}
@Test
public void testImportAuthyEncrypted() throws IOException, DatabaseImporterException, OtpInfoException {
List<VaultEntry> entries = importEncrypted(AuthyImporter.class, "authy_encrypted.xml", encryptedState -> {
final char[] password = "testtest".toCharArray();
return ((AuthyImporter.EncryptedState) encryptedState).decrypt(password);
});
checkImportedAuthyEntries(entries);
}
@Test
public void testImportFreeOtp() throws IOException, DatabaseImporterException, OtpInfoException {
List<VaultEntry> entries = importPlain(FreeOtpImporter.class, "freeotp.xml");
checkImportedFreeOtpEntries(entries);
}
@Test
public void testImportFreeOtpPlus() throws IOException, DatabaseImporterException, OtpInfoException {
List<VaultEntry> entries = importPlain(FreeOtpPlusImporter.class, "freeotp_plus.json");
checkImportedFreeOtpEntries(entries);
}
@Test
public void testImportFreeOtpPlusInternal() throws IOException, DatabaseImporterException, OtpInfoException {
List<VaultEntry> entries = importPlain(FreeOtpPlusImporter.class, "freeotp_plus_internal.xml", true);
checkImportedFreeOtpEntries(entries);
}
@Test
public void testImportGoogleAuthenticator() throws IOException, DatabaseImporterException, OtpInfoException {
List<VaultEntry> entries = importPlain(GoogleAuthImporter.class, "google_authenticator.sqlite");
for (VaultEntry entry : entries) {
// Google Authenticator doesn't support different hash algorithms, periods or digits, so fix those up here
VaultEntry entryVector = getEntryVectorBySecret(entry.getInfo().getSecret());
entryVector.getInfo().setDigits(6);
if (entryVector.getInfo() instanceof TotpInfo) {
((TotpInfo) entryVector.getInfo()).setPeriod(30);
}
entryVector.getInfo().setAlgorithm("SHA1");
checkImportedEntry(entryVector, entry);
}
}
@Test
public void testImportMicrosoftAuthenticator() throws IOException, DatabaseImporterException, OtpInfoException {
List<VaultEntry> entries = importPlain(MicrosoftAuthImporter.class, "microsoft_authenticator.sqlite");
for (VaultEntry entry : entries) {
// Microsoft Authenticator doesn't support HOTP, different hash algorithms, periods or digits, so fix those up here
VaultEntry entryVector = getEntryVectorBySecret(entry.getInfo().getSecret());
entryVector.setInfo(new TotpInfo(entryVector.getInfo().getSecret()));
checkImportedEntry(entryVector, entry);
}
}
@Test
public void testImportSteam() throws IOException, DatabaseImporterException {
List<VaultEntry> entries = importPlain(SteamImporter.class, "steam.json");
for (VaultEntry entry : entries) {
VaultEntry entryVector = getEntryVectorBySecret(entry.getInfo().getSecret());
entryVector.setIssuer("Steam");
checkImportedEntry(entryVector, entry);
}
}
@Test
public void testImportAuthenticatorPlus() throws IOException, DatabaseImporterException, OtpInfoException {
List<VaultEntry> entries = importEncrypted(AuthenticatorPlusImporter.class, "authenticator_plus.zip", encryptedState -> {
final char[] password = "testtesttest".toCharArray();
return ((AuthenticatorPlusImporter.EncryptedState) encryptedState).decrypt(password);
});
checkImportedEntries(entries);
}
private List<VaultEntry> importPlain(Class<? extends DatabaseImporter> type, String resName)
throws IOException, DatabaseImporterException {
return importPlain(type, resName, false);
}
private List<VaultEntry> importPlain(Class<? extends DatabaseImporter> type, String resName, boolean isInternal)
throws IOException, DatabaseImporterException {
Context context = ApplicationProvider.getApplicationContext();
DatabaseImporter importer = DatabaseImporter.create(context, type);
try (InputStream stream = openResource(resName)) {
DatabaseImporter.State state = importer.read(stream, isInternal);
assertFalse(state.isEncrypted());
DatabaseImporter.Result result = state.convert();
return Lists.newArrayList(getEntries(result));
}
}
private List<VaultEntry> importEncrypted(Class<? extends DatabaseImporter> type, String resName, Decryptor decryptor)
throws IOException, DatabaseImporterException {
return importEncrypted(type, resName, false, decryptor);
}
private List<VaultEntry> importEncrypted(Class<? extends DatabaseImporter> type, String resName, boolean isInternal, Decryptor decryptor)
throws IOException, DatabaseImporterException {
Context context = ApplicationProvider.getApplicationContext();
DatabaseImporter importer = DatabaseImporter.create(context, type);
try (InputStream stream = openResource(resName)) {
DatabaseImporter.State state = importer.read(stream, isInternal);
assertTrue(state.isEncrypted());
DatabaseImporter.Result result = decryptor.decrypt(state).convert();
return Lists.newArrayList(getEntries(result));
}
}
private static UUIDMap<VaultEntry> getEntries(DatabaseImporter.Result result) {
for (DatabaseImporterEntryException e : result.getErrors()) {
fail(e.toString());
}
return result.getEntries();
}
private void checkImportedAuthyEntries(List<VaultEntry> entries) throws OtpInfoException {
for (VaultEntry entry : entries) {
// Authy doesn't support different hash algorithms or periods, so fix those up here
VaultEntry entryVector = getEntryVectorBySecret(entry.getInfo().getSecret());
entryVector.getInfo().setAlgorithm("SHA1");
((TotpInfo) entry.getInfo()).setPeriod(((TotpInfo) entryVector.getInfo()).getPeriod());
checkImportedEntry(entryVector, entry);
}
}
private void checkImportedTotpAuthenticatorEntries(List<VaultEntry> entries) throws OtpInfoException {
for (VaultEntry entry : entries) {
// TOTP Authenticator doesn't support different hash algorithms, periods or digits, so fix those up here
VaultEntry entryVector = getEntryVectorBySecret(entry.getInfo().getSecret());
entryVector.getInfo().setDigits(6);
((TotpInfo) entryVector.getInfo()).setPeriod(30);
entryVector.getInfo().setAlgorithm("SHA1");
entryVector.setName(entryVector.getName().toLowerCase());
checkImportedEntry(entryVector, entry);
}
}
private void checkImportedFreeOtpEntries(List<VaultEntry> entries) throws OtpInfoException {
for (VaultEntry entry : entries) {
// for some reason, FreeOTP adds -1 to the counter
VaultEntry entryVector = getEntryVectorBySecret(entry.getInfo().getSecret());
if (entryVector.getInfo() instanceof HotpInfo) {
((HotpInfo) entryVector.getInfo()).setCounter(((HotpInfo) entryVector.getInfo()).getCounter() - 1);
}
checkImportedEntry(entryVector, entry);
}
}
private void checkImportedEntries(List<VaultEntry> entries) {
for (VaultEntry entry : entries) {
checkImportedEntry(entry);
}
}
private void checkImportedEntry(VaultEntry entry) {
VaultEntry entryVector = getEntryVectorBySecret(entry.getInfo().getSecret());
checkImportedEntry(entryVector, entry);
}
private void checkImportedEntry(VaultEntry entryVector, VaultEntry entry) {
String message = String.format("Entries are not equivalent: (%s) (%s)", entryVector.toJson().toString(), entry.toJson().toString());
assertTrue(message, entryVector.equivalates(entry));
assertEquals(message, entryVector.getInfo().getOtp(), entry.getInfo().getOtp());
}
private VaultEntry getEntryVectorBySecret(byte[] secret) {
for (VaultEntry entry : _vectors) {
if (Arrays.equals(entry.getInfo().getSecret(), secret)) {
return entry;
}
}
fail(String.format("No entry found for secret: %s", Base32.encode(secret)));
return null;
}
private InputStream openResource(String name) {
return getClass().getResourceAsStream(name);
}
private interface Decryptor {
DatabaseImporter.State decrypt(DatabaseImporter.State encryptedState) throws DatabaseImporterException;
}
}

View file

@ -0,0 +1,27 @@
package com.beemdevelopment.aegis.otp;
import com.beemdevelopment.aegis.crypto.otp.HOTPTest;
import com.beemdevelopment.aegis.crypto.otp.TOTPTest;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class OtpTest {
@Test
public void testHotpInfoOtp() throws OtpInfoException {
for (int i = 0; i < HOTPTest.VECTORS.length; i++) {
HotpInfo info = new HotpInfo(HOTPTest.SECRET, "SHA1", 6, i);
assertEquals(HOTPTest.VECTORS[i], info.getOtp());
}
}
@Test
public void testTotpInfoOtp() throws OtpInfoException {
for (TOTPTest.Vector vector : TOTPTest.VECTORS) {
byte[] seed = TOTPTest.getSeed(vector.Algo);
TotpInfo info = new TotpInfo(seed, vector.Algo, 8, 30);
assertEquals(vector.OTP, info.getOtp(vector.Time));
}
}
}

View file

@ -1,22 +1,25 @@
package com.beemdevelopment.aegis;
package com.beemdevelopment.aegis.util;
import com.beemdevelopment.aegis.util.Cloner;
import com.beemdevelopment.aegis.util.UUIDMap;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
public class UUIDMapTest {
private UUIDMap<Value> _map;
@BeforeEach
@Before
public void init() {
_map = new UUIDMap<>();
}
@ -87,7 +90,7 @@ public class UUIDMapTest {
// swap the values and see if the lists are equal now
_map.swap(value1, value4);
_map.swap(value2, value3);
assertIterableEquals(values, ref);
assertArrayEquals(values.toArray(), ref.toArray());
}
private Value addNewValue() {

View file

@ -1,15 +1,11 @@
package com.beemdevelopment.aegis;
package com.beemdevelopment.aegis.vault.slots;
import com.beemdevelopment.aegis.crypto.CryptoUtils;
import com.beemdevelopment.aegis.crypto.MasterKey;
import com.beemdevelopment.aegis.crypto.SCryptParameters;
import com.beemdevelopment.aegis.vault.slots.PasswordSlot;
import com.beemdevelopment.aegis.vault.slots.RawSlot;
import com.beemdevelopment.aegis.vault.slots.SlotException;
import com.beemdevelopment.aegis.vault.slots.SlotIntegrityException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.Before;
import org.junit.Test;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
@ -20,13 +16,13 @@ import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertThrows;
public class SlotTest {
private MasterKey _masterKey;
@BeforeEach
@Before
public void init() {
_masterKey = MasterKey.generate();
}
@ -75,18 +71,26 @@ public class SlotTest {
public void testSlotIntegrity() throws
InvalidAlgorithmParameterException, NoSuchAlgorithmException,
InvalidKeyException, NoSuchPaddingException,
SlotException {
SlotException, SlotIntegrityException {
RawSlot slot = new RawSlot();
SecretKey rawKey = CryptoUtils.generateKey();
Cipher cipher = CryptoUtils.createEncryptCipher(rawKey);
slot.setKey(_masterKey, cipher);
// garble the first byte of the key
byte[] rawKeyBytes = rawKey.getEncoded();
rawKeyBytes[0] = (byte) ~rawKeyBytes[0];
rawKey = new SecretKeySpec(rawKeyBytes, "AES");
// try to decrypt with good key/ciphertext first
final Cipher decryptCipher = slot.createDecryptCipher(rawKey);
slot.getKey(decryptCipher);
Cipher decryptCipher = slot.createDecryptCipher(rawKey);
// garble the first byte of the key and try to decrypt
byte[] garbledKeyBytes = rawKey.getEncoded();
garbledKeyBytes[0] = (byte) ~garbledKeyBytes[0];
SecretKey garbledKey = new SecretKeySpec(garbledKeyBytes, "AES");
final Cipher garbledDecryptCipher = slot.createDecryptCipher(garbledKey);
assertThrows(SlotIntegrityException.class, () -> slot.getKey(garbledDecryptCipher));
// garble the first byte of the ciphertext and try to decrypt
byte[] garbledCiphertext = slot.getEncryptedMasterKey();
garbledCiphertext[0] = (byte) ~garbledCiphertext[0];
assertThrows(SlotIntegrityException.class, () -> slot.getKey(decryptCipher));
}
}

View file

@ -0,0 +1,26 @@
{
"version": 1,
"header": {
"slots": [
{
"type": 1,
"uuid": "a8325752-c1be-458a-9b3e-5e0a8154d9ec",
"key": "491d44550430ba248986b904b8cffd3a6c5755d176ac877bd11b82c934225017",
"key_params": {
"nonce": "e9705513ba4951fa7a0608d2",
"tag": "931237af257b83c693ddb8f9a7eddaf0"
},
"n": 32768,
"r": 8,
"p": 1,
"salt": "27ea9ae53fa2f08a8dcd201615a8229422647b3058f9f36b08f9457e62888be1",
"repaired": true
}
],
"params": {
"nonce": "095fd13dee336fa56b4634ff",
"tag": "5db2470edf2d12f82a89ae7f48ccd50c"
}
},
"db": "RtGfUrZ01nzRnvHjPJGyWjfa6shQ7NYwa491CgAWNBM8OeGZVIHhnDAVlVWNlSoq2V097p5Yq5m+SFl5g9nBBBQBNePQnj6CCvu1NfNtoA6R3hyp77gd+e+O2MRnOGH1Z1laV2Tl6p3q8IUHWgAJ36LbUxiCXmfh7bWm198uA4bgLwrEmo04MrqeYXggLuXrJrp6dUJQFD72dgoPbHijlSycY5GLel3ZbAXRsUHszd+xdywpj7\/TYa4OYFel0M0QcCpsKA1LRQz365X9OXPJdTsmVyR4dJ6x5RIVeh39lAYKUf7T4w7BLC8taST5m4J\/VXDueKbvg8R13bNWF0aRHUgeuI9BNzMZINJlzKFKNRknTaJ\/1kEUU0sLkgcaVkX\/DVTGG+pWi5MHijicrK0i4LHN3CUwV2\/\/ZNJCGXM5ErsKMOnJfma52gMdifPiXU317Klvc5oOZFYGnhbhJ2WtPIuqjdvnfuLat2JxA7Xx3LqquRWGL2113yjzVzGBDCVY6iIdedBEgH8CGD826\/3R3m6dR5sfSggQ2SbtQA\/DZNhLSNSU+bfNScVQvUWfR2Lf7Q\/4FR\/xATAQJ9IIBeL+w2ErLUPjURocFXup5YOBHxFdDjZ2FqhbAq4h3Zn\/BJ57xUcYEA+YtP5uOP2lQwUh\/0vFWizDVotzraO8tZiBZBsODyb69eJrXNwFbIjeUczY6wrJs1+676IilbCsmtoYvWEpUZF4hIi7TYAD+nyXX\/olrkog9omWZk8R7hJ9KRDfckXEc\/XSzWhk3Kmfa7pRNh9wYZsaR7VPZGZebQMuUKfRRci2qMsZOJvQsDBJvVze0xW9SqiySDgGyRX\/DwzuaZEGZZriaLf6ox7LwY2Qi6QpYOYbAaEaXAesCR1DPxFfGKsUHVjF8hKA6ZBXDXdqM3Y+14naIOH9S7UzYn32botoVLOykSjnW6z6M0ZPkz3dwowMJiVQcyD7p+9p4J6f1S81pFS7DP+jF+PTyC3c3q\/dwFhNdoG6iV9eQEAxjUi6MpzvFRsk9RsLcQqYgzJGmRjYeXlKH8k8tTu1A4puo6w3Daz8hZz9NafMgMsuqY0oKVLgdNqFz8yVMsxYfBW\/oW56SuQyyVWyxXjXmbk1vpYCTL5kXvIZWoTmBRRDb0ay5S\/dlD6z\/WR45\/C4AwcCE9m4Yf3zisRNa7AqWLVgkmJxFdfJxjiuPtUIK79s+lIJkyRENEqkvm809qIxDhkQzY8zcCt4oXCEbJUfSG4awBs1VvilJIwe6qi0bNtqXtAb5TctgxTh29A9oGlsRG4o8sHqA1mtjp5QiLWp5Hh6rOH95W6+fnBiOW+Iw0evBTduroWvx37HBTktJz79zGe0l3c0Y6VmiFvB7knmT2CrgP7woRkxGbXxdE9zMPQJM9ursD538MVDdD\/0tdkxHxilt47f1DPo2CKUWU8Q1KMm1zLXfVO8BbGUWIv4YeDKHfMUL\/HcStv5VJY+LbnOEjzGT4e1\/avSQmqBL4G9XNkYmyMhC8tlLQcmMMH4bNfPOO3vi5Pb5E7XveSgxlOHs4F0+nqxnFOAu8494MEtx6u5+B7d8LI\/DhEO5zTDwE+THiKej6vCsFxTZ519rm67HycOwRR4LKrwfDeUEK3X1PzryOD5zcv3PMcSBgZ8EWvTfZ9ygKP8BmRQRpydTbSt8Hj5fTUuajADCP0Ggw+6G7n+5FhExJNd+o9D8d4KgLPOe08M8InW7pLB389TWtSo4v3VNjcmmJNQ26wlPkhO\/xBU1URFR0fXU3eCO+w++IMt\/fOSqSpNF9bWElfWHIQ23ntxVke\/hR9j\/GG3tHGxYS5pL42sJF\/Re\/UlUJTGSQP6up2xVYs6gncQ0zACDOPjLQmQzYhz\/hr8S6EjYfK++yLZmRTjEI7xT9u\/B5YLyOQCYVTaF\/pDEegjsehXM3qJBfsA+XY7F9TRsmM\/MSVaPDkdIJ7zvL9xtaF6bXdZoZ6po3ml8uu41pSkNmMKgyEy5E0UQUTWMPLC8drUoQ\/KWQnVIN6HUXGBjYy6aax\/LYZaBcbZi97FHK0h+wsx3WN\/uQozNkQjwGYE8fwYxRYh1RaFi5PkiCM505ib7e82Yuts0l+cBb6nG1IruDplg9BD\/G9w4vVDePEikhcPyY\/p7AZ4i7u\/bL2YKlbE3HyJa+7dkbWJgGidtRZgu+Fdl2T\/rrRJ4+lVaKPVKGKT7ItZdIeitIYUdRxCzrOf1ItZCC8BWa4PElDAjj2yDNmMYRpXJBe3gQHWs\/H5SZgFuwsfCu23uzNRQYib8SuwIJQDvPiXo7m4oIySO8VyvemcExlbXSlbZbvwVxYavTVfcUpAXI6qlsg2jjk+JZahfKrWNC5COZPdVjdAXCoiKU+HBPmEFCwQv\/7zlSBEiI2piyqd+MPwnP63RdGO+oXYid6hn4Nm8kcOhtRyvYm95p66jzGlEugsfxJCED7MTh3XShqa2tt4lFG25icllzTvIJboRkz5oIB4dZVS9+q2TgGUoX7UCpobD8WkHo\/y0cpTuZr8vzXqx2fObxzPNoVgxJmp9E06G2bhMVHPpT17xbfq\/KhJJn7k1S0sfXPG+SmYlX4U7zNSe1M7JXtLf3uVOLz7Ccjp3yvcdq8nRmVym3Zwsz+vv57FA2A0dy3Db97ypJa9HGaxnnYIZHHzep0gJCeeIKE9L32zGCoUg+cPu9B2lPEgIr64iGiuvKSRwNQpOBktM6qqjQntE0Me6mh426irFQ\/3tcfH9a4lZEwwuU1X+lUBUWQp3n5Ej4BSJEs8E6H0EjBvyk69q3qjy5yi7ROVRis6y6S1v4er77RHQUf3phK5354VJHrp9pR926t5qngH5RVF4eljwtXDs3MkejADJ6stBHa\/w7FcbUClO8U+S4Bidxb3mZCiZkUVTpbzvBfYAiQvAfdkMa49o3a5DXKsbXyUPrmr6fWRfM1fS0Ehp0lUv6BDj0yR13CLMpKDU4GfDrl8UEvwh7gwtBRkuaBFzyMtd3NeE7kIGf9vFs6MEl2dmMDFSDid7MdVSDVTlhaAtp+zsRejKW3OQr5n051FzkUsIFGty9AWOkwjZCbstHYCOtyJnsnXP1i9lRDFBgPpFgmDD+bzzg0g9AOAxzqTiLF7bb1jejfe5qVr5V9+7zLpwRLiYaLkNOmpsqvNMuYVwdqTp6nyoougdgBlvve3EG0k09sFKi2Ep9lq+QkS7zGre2jJDrqgdC08+V4PXHYkP3V3Zjgn1x6RfQ2PE+2zvk1GGEgzcNww3byoYw0Ra5qS5yftMy\/2WahbA8fjUYvtmksFH8VjN3yasZt3sdQLWtv8qXxZscy+pCyjTdyxW+ddFnrWuqMIV3jbGMvngq6dL\/n5+DumjbA1gmBJVOpmyEsc1iwHDS36cNnyi1htGFO\/6\/Va4YPYK7dG6LY387UoBUU9Q9ijrBrSGpzPWYmXBLZ8e1MMPfHIN1WsaTgYO9leg3MAJTjQFTFrQ5dguYpWhlm2sWJT45jrda4uWqduB+aQLzYRWhEDBFzPV3ZgIe0SB+7h04Vm0Pu\/LDRvqaolpZ86CEm+zgjBOKeEGFwzTXxH\/5pBoca1bZ6wvsbVZxJNBeH8\/w=="
}

View file

@ -0,0 +1,103 @@
{
"version": 1,
"header": {
"slots": null,
"params": null
},
"db": {
"version": 1,
"entries": [
{
"type": "totp",
"uuid": "3ae6f1ad-2e65-4ed2-a953-1ec0dff2386d",
"name": "Mason",
"issuer": "Deno",
"icon": null,
"info": {
"secret": "4SJHB4GSD43FZBAI7C2HLRJGPQ",
"algo": "SHA1",
"digits": 6,
"period": 30
}
},
{
"type": "totp",
"uuid": "84b55971-a3d2-4173-a5bb-0aea113dbc17",
"name": "James",
"issuer": "SPDX",
"icon": null,
"info": {
"secret": "5OM4WOOGPLQEF6UGN3CPEOOLWU",
"algo": "SHA256",
"digits": 7,
"period": 20
}
},
{
"type": "totp",
"uuid": "3deaff2e-f181-4837-80e1-fdf0c54e9363",
"name": "Elijah",
"issuer": "Airbnb",
"icon": null,
"info": {
"secret": "7ELGJSGXNCCTV3O6LKJWYFV2RA",
"algo": "SHA512",
"digits": 8,
"period": 50
}
},
{
"type": "hotp",
"uuid": "0a8c0571-ff6f-4b02-aa4b-50553b4fb4fe",
"name": "James",
"issuer": "Issuu",
"icon": null,
"info": {
"secret": "YOOMIXWS5GN6RTBPUFFWKTW5M4",
"algo": "SHA1",
"digits": 6,
"counter": 1
}
},
{
"type": "hotp",
"uuid": "03e572f2-8ebd-44b0-a57e-e958af74815d",
"name": "Benjamin",
"issuer": "Air Canada",
"icon": null,
"info": {
"secret": "KUVJJOM753IHTNDSZVCNKL7GII",
"algo": "SHA256",
"digits": 7,
"counter": 50
}
},
{
"type": "hotp",
"uuid": "b25f8815-007f-40f7-a700-ce058ac05435",
"name": "Mason",
"issuer": "WWE",
"icon": null,
"info": {
"secret": "5VAML3X35THCEBVRLV24CGBKOY",
"algo": "SHA512",
"digits": 8,
"counter": 10300
}
},
{
"type": "steam",
"uuid": "5b11ae3b-6fc3-4d46-8ca7-cf0aea7de920",
"name": "Sophia",
"issuer": "Boeing",
"icon": null,
"info": {
"secret": "JRZCL47CMXVOQMNPZR2F7J4RGI",
"algo": "SHA1",
"digits": 5,
"period": 30
}
}
]
}
}

View file

@ -0,0 +1 @@
[{"secret":"4SJHB4GSD43FZBAI7C2HLRJGPQ======","issuer":"Deno","label":"Mason","digits":6,"type":"TOTP","algorithm":"SHA1","thumbnail":"Default","last_used":1608146844162,"used_frequency":0,"period":30,"tags":[]},{"secret":"5OM4WOOGPLQEF6UGN3CPEOOLWU======","issuer":"SPDX","label":"James","digits":7,"type":"TOTP","algorithm":"SHA256","thumbnail":"Default","last_used":1608146848740,"used_frequency":0,"period":20,"tags":[]},{"secret":"7ELGJSGXNCCTV3O6LKJWYFV2RA======","issuer":"Airbnb","label":"Elijah","digits":8,"type":"TOTP","algorithm":"SHA512","thumbnail":"AirBNB","last_used":1608146856099,"used_frequency":0,"period":50,"tags":[]},{"secret":"YOOMIXWS5GN6RTBPUFFWKTW5M4======","issuer":"Issuu","label":"James","digits":6,"type":"HOTP","algorithm":"SHA1","thumbnail":"Default","last_used":1608146859856,"used_frequency":0,"counter":1,"tags":[]},{"secret":"KUVJJOM753IHTNDSZVCNKL7GII======","issuer":"Air Canada","label":"Benjamin","digits":7,"type":"HOTP","algorithm":"SHA256","thumbnail":"Default","last_used":1608146866733,"used_frequency":0,"counter":50,"tags":[]},{"secret":"5VAML3X35THCEBVRLV24CGBKOY======","issuer":"WWE","label":"Mason","digits":8,"type":"HOTP","algorithm":"SHA512","thumbnail":"Default","last_used":1608146871644,"used_frequency":0,"counter":10300,"tags":[]},{"secret":"JRZCL47CMXVOQMNPZR2F7J4RGI======","issuer":"Boeing","label":"Sophia","digits":5,"type":"STEAM","algorithm":"SHA1","thumbnail":"Default","last_used":1608146877325,"used_frequency":0,"tags":[]}]

View file

@ -0,0 +1,5 @@
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<int name="key_version" value="121" />
<string name="com.authy.storage.tokens.authenticator.key">[{&quot;accountType&quot;:&quot;authenticator&quot;,&quot;digits&quot;:6,&quot;encryptedSecret&quot;:&quot;94mk0erEKRYU7UKn4o6WAPWR/gQkyrNIxPWIZcXHeWc\u003d&quot;,&quot;logo&quot;:&quot;Deno&quot;,&quot;originalIssuer&quot;:&quot;Deno&quot;,&quot;originalName&quot;:&quot;Deno:Mason&quot;,&quot;timestamp&quot;:1608377908,&quot;salt&quot;:&quot;z01fjH2vyzYks49nxaOTp8M39eMOjxT4&quot;,&quot;upload_state&quot;:&quot;uploaded&quot;,&quot;hidden&quot;:false,&quot;id&quot;:&quot;1608374963&quot;,&quot;isNew&quot;:false,&quot;name&quot;:&quot;Deno: Mason&quot;},{&quot;accountType&quot;:&quot;authenticator&quot;,&quot;digits&quot;:7,&quot;encryptedSecret&quot;:&quot;0fdhb8g0FBqjZL9mSi13d0+gQ7myUsxllKIHwzxJB08\u003d&quot;,&quot;logo&quot;:&quot;SPDX&quot;,&quot;originalIssuer&quot;:&quot;SPDX&quot;,&quot;originalName&quot;:&quot;SPDX:James&quot;,&quot;timestamp&quot;:1608377908,&quot;salt&quot;:&quot;AVqSXXFR6WGdRyXutRhS2qqtJKMxUmfN&quot;,&quot;upload_state&quot;:&quot;uploaded&quot;,&quot;hidden&quot;:false,&quot;id&quot;:&quot;1608374991&quot;,&quot;isNew&quot;:false,&quot;name&quot;:&quot;SPDX: James&quot;},{&quot;accountType&quot;:&quot;authenticator&quot;,&quot;digits&quot;:8,&quot;encryptedSecret&quot;:&quot;SRtA3xEj1iD9Bh1aHITCtPW6wcbURAsWwWs00oH4SZ8\u003d&quot;,&quot;logo&quot;:&quot;Airbnb&quot;,&quot;originalIssuer&quot;:&quot;Airbnb&quot;,&quot;originalName&quot;:&quot;Airbnb:Elijah&quot;,&quot;timestamp&quot;:1608377908,&quot;salt&quot;:&quot;oXag8rjuljcU5XWhT2FQXgM9alkIvguT&quot;,&quot;upload_state&quot;:&quot;uploaded&quot;,&quot;hidden&quot;:false,&quot;id&quot;:&quot;1608375004&quot;,&quot;isNew&quot;:false,&quot;name&quot;:&quot;Airbnb: Elijah&quot;}]</string>
</map>

View file

@ -0,0 +1,5 @@
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<int name="key_version" value="121" />
<string name="com.authy.storage.tokens.authenticator.key">[{&quot;accountType&quot;:&quot;authenticator&quot;,&quot;decryptedSecret&quot;:&quot;4SJHB4GSD43FZBAI7C2HLRJGPQ&quot;,&quot;digits&quot;:6,&quot;logo&quot;:&quot;Deno&quot;,&quot;originalIssuer&quot;:&quot;Deno&quot;,&quot;originalName&quot;:&quot;Deno:Mason&quot;,&quot;timestamp&quot;:1608374963,&quot;upload_state&quot;:&quot;notUploaded&quot;,&quot;hidden&quot;:false,&quot;id&quot;:&quot;1608374963&quot;,&quot;isNew&quot;:false,&quot;name&quot;:&quot;Deno: Mason&quot;},{&quot;accountType&quot;:&quot;authenticator&quot;,&quot;decryptedSecret&quot;:&quot;5OM4WOOGPLQEF6UGN3CPEOOLWU&quot;,&quot;digits&quot;:7,&quot;logo&quot;:&quot;SPDX&quot;,&quot;originalIssuer&quot;:&quot;SPDX&quot;,&quot;originalName&quot;:&quot;SPDX:James&quot;,&quot;timestamp&quot;:1608374963,&quot;upload_state&quot;:&quot;notUploaded&quot;,&quot;hidden&quot;:false,&quot;id&quot;:&quot;1608374991&quot;,&quot;isNew&quot;:false,&quot;name&quot;:&quot;SPDX: James&quot;},{&quot;accountType&quot;:&quot;authenticator&quot;,&quot;decryptedSecret&quot;:&quot;7ELGJSGXNCCTV3O6LKJWYFV2RA&quot;,&quot;digits&quot;:8,&quot;logo&quot;:&quot;Airbnb&quot;,&quot;originalIssuer&quot;:&quot;Airbnb&quot;,&quot;originalName&quot;:&quot;Airbnb:Elijah&quot;,&quot;timestamp&quot;:1608374963,&quot;upload_state&quot;:&quot;notUploaded&quot;,&quot;hidden&quot;:false,&quot;id&quot;:&quot;1608375004&quot;,&quot;isNew&quot;:false,&quot;name&quot;:&quot;Airbnb: Elijah&quot;}]</string>
</map>

View file

@ -0,0 +1,8 @@
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="WWE:Mason">{&quot;algo&quot;:&quot;SHA512&quot;,&quot;counter&quot;:10299,&quot;digits&quot;:8,&quot;issuerExt&quot;:&quot;WWE&quot;,&quot;issuerInt&quot;:&quot;WWE&quot;,&quot;label&quot;:&quot;Mason&quot;,&quot;period&quot;:30,&quot;secret&quot;:[-19,64,-59,-18,-5,-20,-50,34,6,-79,93,117,-63,24,42,118],&quot;type&quot;:&quot;HOTP&quot;}</string>
<string name="Airbnb:Elijah">{&quot;algo&quot;:&quot;SHA512&quot;,&quot;counter&quot;:0,&quot;digits&quot;:8,&quot;issuerExt&quot;:&quot;Airbnb&quot;,&quot;issuerInt&quot;:&quot;Airbnb&quot;,&quot;label&quot;:&quot;Elijah&quot;,&quot;period&quot;:50,&quot;secret&quot;:[-7,22,100,-56,-41,104,-123,58,-19,-34,90,-109,108,22,-70,-120],&quot;type&quot;:&quot;TOTP&quot;}</string>
<string name="Deno:Mason">{&quot;algo&quot;:&quot;SHA1&quot;,&quot;counter&quot;:0,&quot;digits&quot;:6,&quot;issuerExt&quot;:&quot;Deno&quot;,&quot;issuerInt&quot;:&quot;Deno&quot;,&quot;label&quot;:&quot;Mason&quot;,&quot;period&quot;:30,&quot;secret&quot;:[-28,-110,112,-16,-46,31,54,92,-124,8,-8,-76,117,-59,38,124],&quot;type&quot;:&quot;TOTP&quot;}</string>
<string name="Issuu:James">{&quot;algo&quot;:&quot;SHA1&quot;,&quot;counter&quot;:0,&quot;digits&quot;:6,&quot;issuerExt&quot;:&quot;Issuu&quot;,&quot;issuerInt&quot;:&quot;Issuu&quot;,&quot;label&quot;:&quot;James&quot;,&quot;period&quot;:30,&quot;secret&quot;:[-61,-100,-60,94,-46,-23,-101,-24,-52,47,-95,75,101,78,-35,103],&quot;type&quot;:&quot;HOTP&quot;}</string>
<string name="tokenOrder">[&quot;WWE:Mason&quot;,&quot;Issuu:James&quot;,&quot;Airbnb:Elijah&quot;,&quot;Deno:Mason&quot;]</string>
</map>

View file

@ -0,0 +1 @@
{"tokenOrder":["WWE:Mason","Air Canada:Benjamin","Issuu:James","Airbnb:Elijah","SPDX:James","Deno:Mason"],"tokens":[{"algo":"SHA512","counter":10299,"digits":8,"issuerExt":"WWE","issuerInt":"WWE","label":"Mason","period":30,"secret":[-19,64,-59,-18,-5,-20,-50,34,6,-79,93,117,-63,24,42,118],"type":"HOTP"},{"algo":"SHA256","counter":49,"digits":7,"issuerExt":"Air Canada","issuerInt":"Air Canada","label":"Benjamin","period":30,"secret":[85,42,-108,-71,-97,-18,-48,121,-76,114,-51,68,-43,47,-26,66],"type":"HOTP"},{"algo":"SHA1","counter":0,"digits":6,"issuerExt":"Issuu","issuerInt":"Issuu","label":"James","period":30,"secret":[-61,-100,-60,94,-46,-23,-101,-24,-52,47,-95,75,101,78,-35,103],"type":"HOTP"},{"algo":"SHA512","counter":0,"digits":8,"issuerExt":"Airbnb","issuerInt":"Airbnb","label":"Elijah","period":50,"secret":[-7,22,100,-56,-41,104,-123,58,-19,-34,90,-109,108,22,-70,-120],"type":"TOTP"},{"algo":"SHA256","counter":0,"digits":7,"issuerExt":"SPDX","issuerInt":"SPDX","label":"James","period":20,"secret":[-21,-103,-53,57,-58,122,-32,66,-6,-122,110,-60,-14,57,-53,-75],"type":"TOTP"},{"algo":"SHA1","counter":0,"digits":6,"issuerExt":"Deno","issuerInt":"Deno","label":"Mason","period":30,"secret":[-28,-110,112,-16,-46,31,54,92,-124,8,-8,-76,117,-59,38,124],"type":"TOTP"}]}

View file

@ -0,0 +1,10 @@
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="WWE:Mason">{&quot;algo&quot;:&quot;SHA512&quot;,&quot;counter&quot;:10299,&quot;digits&quot;:8,&quot;issuerExt&quot;:&quot;WWE&quot;,&quot;issuerInt&quot;:&quot;WWE&quot;,&quot;label&quot;:&quot;Mason&quot;,&quot;period&quot;:30,&quot;secret&quot;:[-19,64,-59,-18,-5,-20,-50,34,6,-79,93,117,-63,24,42,118],&quot;type&quot;:&quot;HOTP&quot;}</string>
<string name="Airbnb:Elijah">{&quot;algo&quot;:&quot;SHA512&quot;,&quot;counter&quot;:0,&quot;digits&quot;:8,&quot;issuerExt&quot;:&quot;Airbnb&quot;,&quot;issuerInt&quot;:&quot;Airbnb&quot;,&quot;label&quot;:&quot;Elijah&quot;,&quot;period&quot;:50,&quot;secret&quot;:[-7,22,100,-56,-41,104,-123,58,-19,-34,90,-109,108,22,-70,-120],&quot;type&quot;:&quot;TOTP&quot;}</string>
<string name="Air Canada:Benjamin">{&quot;algo&quot;:&quot;SHA256&quot;,&quot;counter&quot;:49,&quot;digits&quot;:7,&quot;issuerExt&quot;:&quot;Air Canada&quot;,&quot;issuerInt&quot;:&quot;Air Canada&quot;,&quot;label&quot;:&quot;Benjamin&quot;,&quot;period&quot;:30,&quot;secret&quot;:[85,42,-108,-71,-97,-18,-48,121,-76,114,-51,68,-43,47,-26,66],&quot;type&quot;:&quot;HOTP&quot;}</string>
<string name="SPDX:James">{&quot;algo&quot;:&quot;SHA256&quot;,&quot;counter&quot;:0,&quot;digits&quot;:7,&quot;issuerExt&quot;:&quot;SPDX&quot;,&quot;issuerInt&quot;:&quot;SPDX&quot;,&quot;label&quot;:&quot;James&quot;,&quot;period&quot;:20,&quot;secret&quot;:[-21,-103,-53,57,-58,122,-32,66,-6,-122,110,-60,-14,57,-53,-75],&quot;type&quot;:&quot;TOTP&quot;}</string>
<string name="Deno:Mason">{&quot;algo&quot;:&quot;SHA1&quot;,&quot;counter&quot;:0,&quot;digits&quot;:6,&quot;issuerExt&quot;:&quot;Deno&quot;,&quot;issuerInt&quot;:&quot;Deno&quot;,&quot;label&quot;:&quot;Mason&quot;,&quot;period&quot;:30,&quot;secret&quot;:[-28,-110,112,-16,-46,31,54,92,-124,8,-8,-76,117,-59,38,124],&quot;type&quot;:&quot;TOTP&quot;}</string>
<string name="Issuu:James">{&quot;algo&quot;:&quot;SHA1&quot;,&quot;counter&quot;:0,&quot;digits&quot;:6,&quot;issuerExt&quot;:&quot;Issuu&quot;,&quot;issuerInt&quot;:&quot;Issuu&quot;,&quot;label&quot;:&quot;James&quot;,&quot;period&quot;:30,&quot;secret&quot;:[-61,-100,-60,94,-46,-23,-101,-24,-52,47,-95,75,101,78,-35,103],&quot;type&quot;:&quot;HOTP&quot;}</string>
<string name="tokenOrder">[&quot;WWE:Mason&quot;,&quot;Air Canada:Benjamin&quot;,&quot;Issuu:James&quot;,&quot;Airbnb:Elijah&quot;,&quot;SPDX:James&quot;,&quot;Deno:Mason&quot;]</string>
</map>

View file

@ -0,0 +1,7 @@
otpauth://totp/Deno:Mason?secret=4SJHB4GSD43FZBAI7C2HLRJGPQ&issuer=Deno&algorithm=SHA1&digits=6&period=30
otpauth://totp/SPDX:James?secret=5OM4WOOGPLQEF6UGN3CPEOOLWU&issuer=SPDX&algorithm=SHA256&digits=7&period=20
otpauth://totp/Airbnb:Elijah?secret=7ELGJSGXNCCTV3O6LKJWYFV2RA&issuer=Airbnb&algorithm=SHA512&digits=8&period=50
otpauth://hotp/Issuu:James?secret=YOOMIXWS5GN6RTBPUFFWKTW5M4&issuer=Issuu&algorithm=SHA1&digits=6&counter=1
otpauth://hotp/Air%20Canada:Benjamin?secret=KUVJJOM753IHTNDSZVCNKL7GII&issuer=Air+Canada&algorithm=SHA256&digits=7&counter=50
otpauth://hotp/WWE:Mason?secret=5VAML3X35THCEBVRLV24CGBKOY&issuer=WWE&algorithm=SHA512&digits=8&counter=10300
otpauth://steam/Boeing:Sophia?secret=JRZCL47CMXVOQMNPZR2F7J4RGI&issuer=Boeing&algorithm=SHA1&digits=5&period=30

View file

@ -0,0 +1 @@
{"steamid":"1234","shared_secret":"THIl8+Jl6ugxr8x0X6eRMg==","serial_number":"12345678901234567890","revocation_code":"R1234","uri":"otpauth:\/\/totp\/Steam:Sophia?secret=JRZCL47CMXVOQMNPZR2F7J4RGI&issuer=Steam","server_time":"0","account_name":"Sophia","token_gid":"894820a474c9","identity_secret":"dGhpcyBpcyBhIHRlc3Qgc3RyaW5n","secret_1":"eWV0IGFub3RoZXIgdGVzdCBzdHJpbmc=","status":1,"steamguard_scheme":"2"}

View file

@ -0,0 +1 @@
u51d1LQbPDtXbvihHPguTkF6klbc5rJgSpA6KX7oUM4Lt0GLO027ypc2/LvGJDH6zvmfQ4tASN4Iv/bZBllzMQpmrieyWtKBCA+wlQFR1007CqHQssjfkRs0mrkwd4ENkrnJCVDNG+0+wrCUKn0Kf5Ie7KUjVTcHk01Vo5dUozaXgF20jNHb0q2z4030+2kZ/1g+0+RQZLRtNOErrTacH8hlnPzEY/wHk3mWwaxwtesUQfuSlg4DgUyiot7sCV3hDVIgp378r1REhinSbRe0X/7jklCdPrrAXnT73+ok9kxnMOQglQBjIutXO7dy+bC5EZqk0lxIjcbvga7wQj7zizW75avJw6gpi0ksVtuypp+DEtRSjhMQYSwZY8xWZFloOX8jmHwEmyYJkIdrDep00SmuV8B9qZupBRqqKzaPCS1/fJ1oWrxfgRsDR2W7bH5p3ExSEMtXs6Fv8GSiqAnx0n9K/muVV559XFjOwiNXRnbjCvcuHKtCPNFrLEy9lANlwLGBJLLaOhaGOuwQ+6V7xVC7sGyB79atcg6GSQdmZMCYdic6rGPqK+XcyBp7g0Mc/mGUR7h5PCGMrreIImb7O+XFHyXNbrONN3f31fGHmhuLn3HUe8B3ylqEKajTUFytR7q9fZOjNUhQQj5ev/3UmRAIJpGQxHK5D/qbmslBlWuSB8fAXKly9XiUE3Ui2Jfs2XlZn4s8g5LUGvMvZqqUkGhNJk7eDfNWL/DlYdbdsNTMExp4/KonH3/iMFqtXHHaOIHXMZp5LnaXPF2KeQZJq5utxnXKBzjfFgAfLGXXZQdwOcqlmwFrDNtn+e/Fe8pOmFDsyqkiUwkPAO38cAs+xYrf9MUjtGo08t7IUgDkSEY70hziskbVbBinqJ4aQW7pWaD7slSLw2Qn0bpDw1lXHIoz8TMw9ZiNKql514+ZYcKXJBiMXtK+DASRlC9vcye9KxOnP+rSS3GtcE2YUu0pburNZN5ZhOXPWYWg0XTxvC5anIZ2VL/zs/NbOypix0eGd1LLP9JdjzX6a99jNIcZJzT+4X8RgeRX5d5GrD6Ui243XzaceyrS/cc2UHX/PQHn4IZXC82JmfJ+ic04NB9l8cimygZB0QcCfAbtqoqRYs1WeNa+xkXV7kS1QrgH4hwY/jUU0TPY5s4m6oRAKgBua6wwtV8doO3dOwjZrCTxJzduD3Te9os9IPZXB31Vp1lGAqzUuc4hozdCagrnl675BJJKrZ57Jh8l5LGALIZjEr3R8lKp2V+M54Z2+zO3SIkCzGzdrXwZcU4Vs2MG+rKfi5R9EChU2J8Fjy5R1Iga5a43J88h0M6dlH91EqPjtVDTmdfeNaoZqS5k9A8IzVt5OImFaDCKw2WkA57BuP2BU339NczpuUm7yEUx0gBYiXITk9JDwfdsO0N6BAyc2OYobN19BA1erUjlQW4H7L29h/VvGt4E8E2ncWvFf4Abh/H5WKJykbsvLCTDFSf8RGg8w4sYRaAfX90XC9QAotKiKVFCV8Q4uj9Is707NRn+JTKYtN6qS1n4sc5B7h079fDsXssFpLfrqjp3X8P4wMdEiM6W9N2WsZvGOER/K2IdvU3V8ottGitsQDHaxMZcaTuNx6KwIirP4r7Zrt2uSq/5fzKClMJSBx9aczPLe3A+LIw8

View file

@ -0,0 +1,20 @@
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<int name="RATE_US_COUNTER" value="13" />
<boolean name="SHOWCASE_FIREST_RUN" value="false" />
<boolean name="FIRST_ACCOUNT_ADDED_BACKUP" value="true" />
<boolean name="SHOULD_SHOW_RATE_US_DIALOG" value="false" />
<int name="BLACK_FRIDAY_MODAL" value="13" />
<string name="STATIC_TOTP_CODES_LIST">[{&quot;accountHeaderLabel&quot;:&quot;&quot;,&quot;allowNotifications&quot;:false,&quot;base&quot;:16,&quot;digits&quot;:&quot;6&quot;,&quot;fileName&quot;:&quot;&quot;,&quot;iconLabel&quot;:&quot;&quot;,&quot;iconPath&quot;:&quot;&quot;,&quot;isFavorite&quot;:false,&quot;isSelected&quot;:false,&quot;isWidgetActive&quot;:false,&quot;issuer&quot;:&quot;Deno&quot;,&quot;key&quot;:&quot;E49270F0D21F365C8408F8B475C5267C&quot;,&quot;name&quot;:&quot;mason&quot;,&quot;period&quot;:&quot;30&quot;,&quot;setIconFromDrawable&quot;:true,&quot;source&quot;:0,&quot;timeRemaining&quot;:0,&quot;totpCode&quot;:&quot;&quot;,&quot;widgetId&quot;:0},{&quot;accountHeaderLabel&quot;:&quot;&quot;,&quot;allowNotifications&quot;:false,&quot;base&quot;:16,&quot;digits&quot;:&quot;7&quot;,&quot;fileName&quot;:&quot;&quot;,&quot;iconLabel&quot;:&quot;&quot;,&quot;iconPath&quot;:&quot;&quot;,&quot;isFavorite&quot;:false,&quot;isSelected&quot;:false,&quot;isWidgetActive&quot;:false,&quot;issuer&quot;:&quot;SPDX&quot;,&quot;key&quot;:&quot;EB99CB39C67AE042FA866EC4F239CBB5&quot;,&quot;name&quot;:&quot;james&quot;,&quot;period&quot;:&quot;20&quot;,&quot;setIconFromDrawable&quot;:true,&quot;source&quot;:0,&quot;timeRemaining&quot;:0,&quot;totpCode&quot;:&quot;&quot;,&quot;widgetId&quot;:0},{&quot;accountHeaderLabel&quot;:&quot;&quot;,&quot;allowNotifications&quot;:false,&quot;base&quot;:16,&quot;digits&quot;:&quot;8&quot;,&quot;fileName&quot;:&quot;&quot;,&quot;iconLabel&quot;:&quot;&quot;,&quot;iconPath&quot;:&quot;&quot;,&quot;isFavorite&quot;:false,&quot;isSelected&quot;:false,&quot;isWidgetActive&quot;:false,&quot;issuer&quot;:&quot;Airbnb&quot;,&quot;key&quot;:&quot;F91664C8D768853AEDDE5A936C16BA88&quot;,&quot;name&quot;:&quot;elijah&quot;,&quot;period&quot;:&quot;50&quot;,&quot;setIconFromDrawable&quot;:true,&quot;source&quot;:0,&quot;timeRemaining&quot;:0,&quot;totpCode&quot;:&quot;&quot;,&quot;widgetId&quot;:0}]</string>
<boolean name="WIDGET_SERVICE_RELOAD_FLAG" value="false" />
<boolean name="SCREENSHOT_FLAG" value="true" />
<boolean name="ASK_FOR_VERIFICATION" value="true" />
<boolean name="FORCE_SYNC_FIRST_TIME_V3" value="false" />
<boolean name="NOTIFICATION_SERVICE_RELOAD_FLAG" value="true" />
<string name="SET_SCREENSHOT_FLAG">COMPLETED</string>
<boolean name="ADD_LABEL" value="true" />
<string name="SORT_ACCOUNT_BY">CUSTOM</string>
<string name="DEFAULT_ENCRYPTION_KEY">Testtest1</string>
<string name="FCM_CLOUD_ID">dU9OMKiERmSSHuXTbuYkkr:APA91bH7yW4Pw-z9QnWYpSWr2Cwrd8aV7OtY-JOTAj0jcar3V_ZvLvFlks37NUV7R2vyl9M47dGAD2iE7ud_IlVgaxo0VWZicY8qKGVT6w-DlrE0Vgre7IX-n69T0bNEykoJpTK_hsmz</string>
<int name="CHANGE_LOG_VERSION" value="55" />
</map>