That fuck shit the fascists are using
at master 239 lines 7.7 kB view raw
1package org.tm.archive.keyvalue; 2 3import androidx.annotation.NonNull; 4import androidx.annotation.Nullable; 5 6import org.signal.core.util.StringStringSerializer; 7import org.tm.archive.util.JsonUtils; 8import org.whispersystems.signalservice.api.kbs.MasterKey; 9import org.whispersystems.signalservice.api.kbs.PinHashUtil; 10import org.whispersystems.signalservice.internal.contacts.entities.TokenResponse; 11 12import java.io.IOException; 13import java.security.SecureRandom; 14import java.util.ArrayList; 15import java.util.List; 16import java.util.stream.Collectors; 17import java.util.stream.Stream; 18 19public final class SvrValues extends SignalStoreValues { 20 21 public static final String REGISTRATION_LOCK_ENABLED = "kbs.v2_lock_enabled"; 22 private static final String MASTER_KEY = "kbs.registration_lock_master_key"; 23 private static final String TOKEN_RESPONSE = "kbs.token_response"; 24 private static final String PIN = "kbs.pin"; 25 private static final String LOCK_LOCAL_PIN_HASH = "kbs.registration_lock_local_pin_hash"; 26 private static final String LAST_CREATE_FAILED_TIMESTAMP = "kbs.last_create_failed_timestamp"; 27 public static final String OPTED_OUT = "kbs.opted_out"; 28 private static final String PIN_FORGOTTEN_OR_SKIPPED = "kbs.pin.forgotten.or.skipped"; 29 private static final String SVR_AUTH_TOKENS = "kbs.kbs_auth_tokens"; 30 private static final String SVR_LAST_AUTH_REFRESH_TIMESTAMP = "kbs.kbs_auth_tokens.last_refresh_timestamp"; 31 32 SvrValues(KeyValueStore store) { 33 super(store); 34 } 35 36 @Override 37 void onFirstEverAppLaunch() { 38 } 39 40 @Override 41 @NonNull 42 List<String> getKeysToIncludeInBackup() { 43 return List.of(SVR_AUTH_TOKENS); 44 } 45 46 /** 47 * Deliberately does not clear the {@link #MASTER_KEY}. 48 */ 49 public void clearRegistrationLockAndPin() { 50 getStore().beginWrite() 51 .remove(REGISTRATION_LOCK_ENABLED) 52 .remove(TOKEN_RESPONSE) 53 .remove(LOCK_LOCAL_PIN_HASH) 54 .remove(PIN) 55 .remove(LAST_CREATE_FAILED_TIMESTAMP) 56 .remove(OPTED_OUT) 57 .remove(SVR_AUTH_TOKENS) 58 .remove(SVR_LAST_AUTH_REFRESH_TIMESTAMP) 59 .commit(); 60 } 61 62 public synchronized void setMasterKey(@NonNull MasterKey masterKey, @NonNull String pin) { 63 getStore().beginWrite() 64 .putBlob(MASTER_KEY, masterKey.serialize()) 65 .putString(LOCK_LOCAL_PIN_HASH, PinHashUtil.localPinHash(pin)) 66 .putString(PIN, pin) 67 .putLong(LAST_CREATE_FAILED_TIMESTAMP, -1) 68 .putBoolean(OPTED_OUT, false) 69 .commit(); 70 } 71 72 synchronized void setPinIfNotPresent(@NonNull String pin) { 73 if (getStore().getString(PIN, null) == null) { 74 getStore().beginWrite().putString(PIN, pin).commit(); 75 } 76 } 77 78 public synchronized void setRegistrationLockEnabled(boolean enabled) { 79 putBoolean(REGISTRATION_LOCK_ENABLED, enabled); 80 } 81 82 /** 83 * Whether or not registration lock V2 is enabled. 84 */ 85 public synchronized boolean isRegistrationLockEnabled() { 86 return getBoolean(REGISTRATION_LOCK_ENABLED, false); 87 } 88 89 public synchronized void onPinCreateFailure() { 90 putLong(LAST_CREATE_FAILED_TIMESTAMP, System.currentTimeMillis()); 91 } 92 93 /** 94 * Whether or not the last time the user attempted to create a PIN, it failed. 95 */ 96 public synchronized boolean lastPinCreateFailed() { 97 return getLong(LAST_CREATE_FAILED_TIMESTAMP, -1) > 0; 98 } 99 100 /** 101 * Finds or creates the master key. Therefore this will always return a master key whether backed 102 * up or not. 103 * <p> 104 * If you only want a key when it's backed up, use {@link #getPinBackedMasterKey()}. 105 */ 106 public synchronized @NonNull MasterKey getOrCreateMasterKey() { 107 byte[] blob = getStore().getBlob(MASTER_KEY, null); 108 109 if (blob == null) { 110 getStore().beginWrite() 111 .putBlob(MASTER_KEY, MasterKey.createNew(new SecureRandom()).serialize()) 112 .commit(); 113 blob = getBlob(MASTER_KEY, null); 114 } 115 116 return new MasterKey(blob); 117 } 118 119 /** 120 * Returns null if master key is not backed up by a pin. 121 */ 122 public synchronized @Nullable MasterKey getPinBackedMasterKey() { 123 if (!isRegistrationLockEnabled()) return null; 124 return getMasterKey(); 125 } 126 127 private synchronized @Nullable MasterKey getMasterKey() { 128 byte[] blob = getBlob(MASTER_KEY, null); 129 return blob != null ? new MasterKey(blob) : null; 130 } 131 132 public @Nullable String getRegistrationLockToken() { 133 MasterKey masterKey = getPinBackedMasterKey(); 134 if (masterKey == null) { 135 return null; 136 } else { 137 return masterKey.deriveRegistrationLock(); 138 } 139 } 140 141 public synchronized @Nullable String getRecoveryPassword() { 142 MasterKey masterKey = getMasterKey(); 143 if (masterKey != null && hasPin()) { 144 return masterKey.deriveRegistrationRecoveryPassword(); 145 } else { 146 return null; 147 } 148 } 149 150 public synchronized @Nullable String getPin() { 151 return getString(PIN, null); 152 } 153 154 public synchronized @Nullable String getLocalPinHash() { 155 return getString(LOCK_LOCAL_PIN_HASH, null); 156 } 157 158 public synchronized boolean hasPin() { 159 return getLocalPinHash() != null; 160 } 161 162 public synchronized boolean isPinForgottenOrSkipped() { 163 return getBoolean(PIN_FORGOTTEN_OR_SKIPPED, false); 164 } 165 166 public synchronized void setPinForgottenOrSkipped(boolean value) { 167 putBoolean(PIN_FORGOTTEN_OR_SKIPPED, value); 168 } 169 170 public synchronized void putAuthTokenList(List<String> tokens) { 171 putList(SVR_AUTH_TOKENS, tokens, StringStringSerializer.INSTANCE); 172 setLastRefreshAuthTimestamp(System.currentTimeMillis()); 173 } 174 175 public synchronized List<String> getAuthTokenList() { 176 return getList(SVR_AUTH_TOKENS, StringStringSerializer.INSTANCE); 177 } 178 179 /** 180 * Keeps the 10 most recent KBS auth tokens. 181 * @param token 182 * @return whether the token was added (new) or ignored (already existed) 183 */ 184 public synchronized boolean appendAuthTokenToList(String token) { 185 List<String> tokens = getAuthTokenList(); 186 if (tokens.contains(token)) { 187 return false; 188 } else { 189 final List<String> result = Stream.concat(Stream.of(token), tokens.stream()).limit(10).collect(Collectors.toList()); 190 putAuthTokenList(result); 191 return true; 192 } 193 } 194 195 public boolean removeAuthTokens(@NonNull List<String> invalid) { 196 List<String> tokens = new ArrayList<>(getAuthTokenList()); 197 if (tokens.removeAll(invalid)) { 198 putAuthTokenList(tokens); 199 return true; 200 } 201 202 return false; 203 } 204 205 public synchronized void optOut() { 206 getStore().beginWrite() 207 .putBoolean(OPTED_OUT, true) 208 .remove(TOKEN_RESPONSE) 209 .putBlob(MASTER_KEY, MasterKey.createNew(new SecureRandom()).serialize()) 210 .remove(LOCK_LOCAL_PIN_HASH) 211 .remove(PIN) 212 .putLong(LAST_CREATE_FAILED_TIMESTAMP, -1) 213 .commit(); 214 } 215 216 public synchronized boolean hasOptedOut() { 217 return getBoolean(OPTED_OUT, false); 218 } 219 220 public synchronized @Nullable TokenResponse getRegistrationLockTokenResponse() { 221 String token = getStore().getString(TOKEN_RESPONSE, null); 222 223 if (token == null) return null; 224 225 try { 226 return JsonUtils.fromJson(token, TokenResponse.class); 227 } catch (IOException e) { 228 throw new AssertionError(e); 229 } 230 } 231 232 private void setLastRefreshAuthTimestamp(long timestamp) { 233 putLong(SVR_LAST_AUTH_REFRESH_TIMESTAMP, timestamp); 234 } 235 236 public long getLastRefreshAuthTimestamp() { 237 return getLong(SVR_LAST_AUTH_REFRESH_TIMESTAMP, 0L); 238 } 239}