org.thoughtcrime.securesms.util.Hex Java Examples
The following examples show how to use
org.thoughtcrime.securesms.util.Hex.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: PinHashing_hashPin_Test.java From mollyim-android with GNU General Public License v3.0 | 6 votes |
@Test public void argon2_hashed_pin_password_with_spaces_diacritics_and_non_arabic_numerals() throws IOException { String pin = " Pass६örd "; byte[] backupId = Hex.fromStringCondensed("cba811749042b303a6a7efa5ccd160aea5e3ea243c8d2692bd13d515732f51a8"); MasterKey masterKey = new MasterKey(Hex.fromStringCondensed("9571f3fde1e58588ba49bcf82be1b301ca3859a6f59076f79a8f47181ef952bf")); HashedPin hashedPin = PinHashing.hashPin(pin, () -> backupId); KbsData kbsData = hashedPin.createNewKbsData(masterKey); assertArrayEquals(hashedPin.getKbsAccessKey(), kbsData.getKbsAccessKey()); assertArrayEquals(Hex.fromStringCondensed("ab645acdccc1652a48a34b2ac6926340ff35c03034013f68760f20013f028dd8"), kbsData.getKbsAccessKey()); assertArrayEquals(Hex.fromStringCondensed("11c0ba1834db15e47c172f6c987c64bd4cfc69c6047dd67a022afeec0165a10943f204d5b8f37b3cb7bab21c6dfc39c8"), kbsData.getCipherText()); assertEquals(masterKey, kbsData.getMasterKey()); assertEquals("577939bccb2b6638c39222d5a97998a867c5e154e30b82cc120f2dd07a3de987", kbsData.getMasterKey().deriveRegistrationLock()); String localPinHash = PinHashing.localPinHash(pin); assertTrue(PinHashing.verifyLocalPinHash(localPinHash, pin)); }
Example #2
Source File: PushProcessMessageJob.java From mollyim-android with GNU General Public License v3.0 | 6 votes |
private void handleSynchronizeStickerPackOperation(@NonNull List<StickerPackOperationMessage> stickerPackOperations) { JobManager jobManager = ApplicationDependencies.getJobManager(); for (StickerPackOperationMessage operation : stickerPackOperations) { if (operation.getPackId().isPresent() && operation.getPackKey().isPresent() && operation.getType().isPresent()) { String packId = Hex.toStringCondensed(operation.getPackId().get()); String packKey = Hex.toStringCondensed(operation.getPackKey().get()); switch (operation.getType().get()) { case INSTALL: jobManager.add(StickerPackDownloadJob.forInstall(packId, packKey, false)); break; case REMOVE: DatabaseFactory.getStickerDatabase(context).uninstallPack(packId); break; } } else { Log.w(TAG, "Received incomplete sticker pack operation sync."); } } }
Example #3
Source File: MultiDeviceStickerPackOperationJob.java From mollyim-android with GNU General Public License v3.0 | 6 votes |
@Override protected void onRun() throws Exception { if (!TextSecurePreferences.isMultiDevice(context)) { Log.i(TAG, "Not multi device, aborting..."); return; } byte[] packIdBytes = Hex.fromStringCondensed(packId); byte[] packKeyBytes = Hex.fromStringCondensed(packKey); StickerPackOperationMessage.Type remoteType; switch (type) { case INSTALL: remoteType = StickerPackOperationMessage.Type.INSTALL; break; case REMOVE: remoteType = StickerPackOperationMessage.Type.REMOVE; break; default: throw new AssertionError("No matching type?"); } SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); StickerPackOperationMessage stickerPackOperation = new StickerPackOperationMessage(packIdBytes, packKeyBytes, remoteType); messageSender.sendMessage(SignalServiceSyncMessage.forStickerPackOperations(Collections.singletonList(stickerPackOperation)), UnidentifiedAccessUtil.getAccessForSync(context)); }
Example #4
Source File: UpdateApkJob.java From mollyim-android with GNU General Public License v3.0 | 6 votes |
private void handleDownloadStart(String uri, String versionName, byte[] digest) { clearPreviousDownloads(context); DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); DownloadManager.Request downloadRequest = new DownloadManager.Request(Uri.parse(uri)); downloadRequest.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI); downloadRequest.setTitle("Downloading Signal update"); downloadRequest.setDescription("Downloading Signal " + versionName); downloadRequest.setVisibleInDownloadsUi(false); downloadRequest.setDestinationInExternalFilesDir(context, null, "signal-update.apk"); downloadRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN); long downloadId = downloadManager.enqueue(downloadRequest); TextSecurePreferences.setUpdateApkDownloadId(context, downloadId); TextSecurePreferences.setUpdateApkDigest(context, Hex.toStringCondensed(digest)); }
Example #5
Source File: PinHashing_hashPin_Test.java From mollyim-android with GNU General Public License v3.0 | 6 votes |
@Test public void argon2_hashed_pin_password() throws IOException { String pin = "password"; byte[] backupId = Hex.fromStringCondensed("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"); MasterKey masterKey = new MasterKey(Hex.fromStringCondensed("202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f")); HashedPin hashedPin = PinHashing.hashPin(pin, () -> backupId); KbsData kbsData = hashedPin.createNewKbsData(masterKey); assertArrayEquals(hashedPin.getKbsAccessKey(), kbsData.getKbsAccessKey()); assertArrayEquals(Hex.fromStringCondensed("ab7e8499d21f80a6600b3b9ee349ac6d72c07e3359fe885a934ba7aa844429f8"), kbsData.getKbsAccessKey()); assertArrayEquals(Hex.fromStringCondensed("3f33ce58eb25b40436592a30eae2a8fabab1899095f4e2fba6e2d0dc43b4a2d9cac5a3931748522393951e0e54dec769"), kbsData.getCipherText()); assertEquals(masterKey, kbsData.getMasterKey()); String localPinHash = PinHashing.localPinHash(pin); assertTrue(PinHashing.verifyLocalPinHash(localPinHash, pin)); }
Example #6
Source File: PinHashing_hashPin_Test.java From mollyim-android with GNU General Public License v3.0 | 6 votes |
@Test public void argon2_hashed_pin_another_password() throws IOException { String pin = "anotherpassword"; byte[] backupId = Hex.fromStringCondensed("202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"); MasterKey masterKey = new MasterKey(Hex.fromStringCondensed("88a787415a2ecd79da0d1016a82a27c5c695c9a19b88b0aa1d35683280aa9a67")); HashedPin hashedPin = PinHashing.hashPin(pin, () -> backupId); KbsData kbsData = hashedPin.createNewKbsData(masterKey); assertArrayEquals(hashedPin.getKbsAccessKey(), kbsData.getKbsAccessKey()); assertArrayEquals(Hex.fromStringCondensed("301d9dd1e96f20ce51083f67d3298fd37b97525de8324d5e12ed2d407d3d927b"), kbsData.getKbsAccessKey()); assertArrayEquals(Hex.fromStringCondensed("9d9b05402ea39c17ff1c9298c8a0e86784a352aa02a74943bf8bcf07ec0f4b574a5b786ad0182c8d308d9eb06538b8c9"), kbsData.getCipherText()); assertEquals(masterKey, kbsData.getMasterKey()); String localPinHash = PinHashing.localPinHash(pin); assertTrue(PinHashing.verifyLocalPinHash(localPinHash, pin)); }
Example #7
Source File: StickerDownloadJob.java From mollyim-android with GNU General Public License v3.0 | 6 votes |
@Override protected void onRun() throws Exception { StickerDatabase db = DatabaseFactory.getStickerDatabase(context); if (db.getSticker(sticker.getPackId(), sticker.getStickerId(), sticker.isCover()) != null) { Log.w(TAG, "Sticker already downloaded."); return; } if (!db.isPackInstalled(sticker.getPackId()) && !sticker.isCover()) { Log.w(TAG, "Pack is no longer installed."); return; } SignalServiceMessageReceiver receiver = ApplicationDependencies.getSignalServiceMessageReceiver(); byte[] packIdBytes = Hex.fromStringCondensed(sticker.getPackId ()); byte[] packKeyBytes = Hex.fromStringCondensed(sticker.getPackKey()); InputStream stream = receiver.retrieveSticker(packIdBytes, packKeyBytes, sticker.getStickerId()); db.insertSticker(sticker, stream, notify); }
Example #8
Source File: PushSendJob.java From mollyim-android with GNU General Public License v3.0 | 6 votes |
protected Optional<SignalServiceDataMessage.Sticker> getStickerFor(OutgoingMediaMessage message) { Attachment stickerAttachment = Stream.of(message.getAttachments()).filter(Attachment::isSticker).findFirst().orElse(null); if (stickerAttachment == null) { return Optional.absent(); } try { byte[] packId = Hex.fromStringCondensed(stickerAttachment.getSticker().getPackId()); byte[] packKey = Hex.fromStringCondensed(stickerAttachment.getSticker().getPackKey()); int stickerId = stickerAttachment.getSticker().getStickerId(); SignalServiceAttachment attachment = getAttachmentPointerFor(stickerAttachment); return Optional.of(new SignalServiceDataMessage.Sticker(packId, packKey, stickerId, attachment)); } catch (IOException e) { Log.w(TAG, "Failed to decode sticker id/key", e); return Optional.absent(); } }
Example #9
Source File: MultiDeviceStickerPackSyncJob.java From mollyim-android with GNU General Public License v3.0 | 6 votes |
@Override protected void onRun() throws Exception { if (!TextSecurePreferences.isMultiDevice(context)) { Log.i(TAG, "Not multi device, aborting..."); return; } List<StickerPackOperationMessage> operations = new LinkedList<>(); try (StickerPackRecordReader reader = new StickerPackRecordReader(DatabaseFactory.getStickerDatabase(context).getInstalledStickerPacks())) { StickerPackRecord pack; while ((pack = reader.getNext()) != null) { byte[] packIdBytes = Hex.fromStringCondensed(pack.getPackId()); byte[] packKeyBytes = Hex.fromStringCondensed(pack.getPackKey()); operations.add(new StickerPackOperationMessage(packIdBytes, packKeyBytes, StickerPackOperationMessage.Type.INSTALL)); } } SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); messageSender.sendMessage(SignalServiceSyncMessage.forStickerPackOperations(operations), UnidentifiedAccessUtil.getAccessForSync(context)); }
Example #10
Source File: PinHashing_hashPin_Test.java From mollyim-android with GNU General Public License v3.0 | 6 votes |
@Test public void argon2_hashed_pin_password_with_just_non_arabic_numerals() throws IOException { String pin = " ६१८ "; byte[] backupId = Hex.fromStringCondensed("717dc111a98423a57196512606822fca646c653facd037c10728f14ba0be2ab3"); MasterKey masterKey = new MasterKey(Hex.fromStringCondensed("0432d735b32f66d0e3a70d4f9cc821a8529521a4937d26b987715d8eff4e4c54")); HashedPin hashedPin = PinHashing.hashPin(pin, () -> backupId); KbsData kbsData = hashedPin.createNewKbsData(masterKey); assertArrayEquals(hashedPin.getKbsAccessKey(), kbsData.getKbsAccessKey()); assertArrayEquals(Hex.fromStringCondensed("d2fedabd0d4c17a371491c9722578843a26be3b4923e28d452ab2fc5491e794b"), kbsData.getKbsAccessKey()); assertArrayEquals(Hex.fromStringCondensed("877ef871ef1fc668401c717ef21aa12e8523579fb1ff4474b76f28c2293537c80cc7569996c9e0229bea7f378e3a824e"), kbsData.getCipherText()); assertEquals(masterKey, kbsData.getMasterKey()); assertEquals("23a75cb1df1a87df45cc2ed167c2bdc85ab1220b847c88761b0005cac907fce5", kbsData.getMasterKey().deriveRegistrationLock()); String localPinHash = PinHashing.localPinHash(pin); assertTrue(PinHashing.verifyLocalPinHash(localPinHash, pin)); }
Example #11
Source File: UpdateApkReadyListener.java From mollyim-android with GNU General Public License v3.0 | 6 votes |
private boolean isMatchingDigest(Context context, long downloadId, String theirEncodedDigest) { try { if (theirEncodedDigest == null) return false; byte[] theirDigest = Hex.fromStringCondensed(theirEncodedDigest); DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); FileInputStream fin = new FileInputStream(downloadManager.openDownloadedFile(downloadId).getFileDescriptor()); byte[] ourDigest = FileUtils.getFileDigest(fin); fin.close(); return MessageDigest.isEqual(ourDigest, theirDigest); } catch (IOException e) { Log.w(TAG, e); return false; } }
Example #12
Source File: AttachmentDownloadJob.java From mollyim-android with GNU General Public License v3.0 | 5 votes |
private SignalServiceAttachmentPointer createAttachmentPointer(Attachment attachment) throws InvalidPartException { if (TextUtils.isEmpty(attachment.getLocation())) { throw new InvalidPartException("empty content id"); } if (TextUtils.isEmpty(attachment.getKey())) { throw new InvalidPartException("empty encrypted key"); } try { final SignalServiceAttachmentRemoteId remoteId = SignalServiceAttachmentRemoteId.from(attachment.getLocation()); final byte[] key = Base64.decode(attachment.getKey()); if (attachment.getDigest() != null) { Log.i(TAG, "Downloading attachment with digest: " + Hex.toString(attachment.getDigest())); } else { Log.i(TAG, "Downloading attachment with no digest..."); } return new SignalServiceAttachmentPointer(attachment.getCdnNumber(), remoteId, null, key, Optional.of(Util.toIntExact(attachment.getSize())), Optional.absent(), 0, 0, Optional.fromNullable(attachment.getDigest()), Optional.fromNullable(attachment.getFileName()), attachment.isVoiceNote(), Optional.absent(), Optional.fromNullable(attachment.getBlurHash()).transform(BlurHash::getHash), attachment.getUploadTimestamp()); } catch (IOException | ArithmeticException e) { Log.w(TAG, e); throw new InvalidPartException(e); } }
Example #13
Source File: GroupIdTest.java From mollyim-android with GNU General Public License v3.0 | 5 votes |
@Test public void can_create_for_gv2_from_GroupIdentifier() throws IOException, InvalidInputException { GroupId.V2 groupId = GroupId.v2(new GroupIdentifier(Hex.fromStringCondensed("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"))); assertEquals("__signal_group__v2__!0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", groupId.toString()); assertFalse(groupId.isMms()); assertFalse(groupId.isV1()); assertTrue(groupId.isV2()); assertTrue(groupId.isPush()); }
Example #14
Source File: GroupIdTest.java From mollyim-android with GNU General Public License v3.0 | 5 votes |
@Test public void can_create_for_gv2_from_GroupMasterKey() throws IOException, InvalidInputException { assumeZkGroupSupportedOnOS(); GroupId.V2 groupId = GroupId.v2(new GroupMasterKey(Hex.fromStringCondensed("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"))); assertEquals("__signal_group__v2__!8c4a5ec277691282f64b965b1b9affc0285380c993c413f7560967d502dcf2e6", groupId.toString()); assertFalse(groupId.isMms()); assertFalse(groupId.isV1()); assertTrue(groupId.isV2()); assertTrue(groupId.isPush()); }
Example #15
Source File: GroupIdTest.java From mollyim-android with GNU General Public License v3.0 | 5 votes |
@Test public void can_parse_gv2() throws IOException { GroupId groupId = GroupId.parseOrThrow("__signal_group__v2__!9f475f59b2518bff6df22e820803f0e3585bd99e686fa7e7fbfc2f92fd5d953e"); assertEquals("__signal_group__v2__!9f475f59b2518bff6df22e820803f0e3585bd99e686fa7e7fbfc2f92fd5d953e", groupId.toString()); assertArrayEquals(Hex.fromStringCondensed("9f475f59b2518bff6df22e820803f0e3585bd99e686fa7e7fbfc2f92fd5d953e"), groupId.getDecodedId()); assertFalse(groupId.isMms()); assertFalse(groupId.isV1()); assertTrue(groupId.isV2()); assertTrue(groupId.isPush()); }
Example #16
Source File: JsonStickerPackOperationMessage.java From signald with GNU General Public License v3.0 | 5 votes |
JsonStickerPackOperationMessage(StickerPackOperationMessage message) { if(message.getPackId().isPresent()) { packID = Hex.toStringCondensed(message.getPackId().get()); } if(message.getPackKey().isPresent()) { packKey = Hex.toStringCondensed(message.getPackKey().get()); } if(message.getType().isPresent()) { type = message.getType().get().toString(); } }
Example #17
Source File: PushProcessMessageJob.java From mollyim-android with GNU General Public License v3.0 | 5 votes |
private Optional<Attachment> getStickerAttachment(Optional<SignalServiceDataMessage.Sticker> sticker) { if (!sticker.isPresent()) { return Optional.absent(); } if (sticker.get().getPackId() == null || sticker.get().getPackKey() == null || sticker.get().getAttachment() == null) { Log.w(TAG, "Malformed sticker!"); return Optional.absent(); } String packId = Hex.toStringCondensed(sticker.get().getPackId()); String packKey = Hex.toStringCondensed(sticker.get().getPackKey()); int stickerId = sticker.get().getStickerId(); StickerLocator stickerLocator = new StickerLocator(packId, packKey, stickerId); StickerDatabase stickerDatabase = DatabaseFactory.getStickerDatabase(context); StickerRecord stickerRecord = stickerDatabase.getSticker(stickerLocator.getPackId(), stickerLocator.getStickerId(), false); if (stickerRecord != null) { return Optional.of(new UriAttachment(stickerRecord.getUri(), stickerRecord.getUri(), MediaUtil.IMAGE_WEBP, AttachmentDatabase.TRANSFER_PROGRESS_DONE, stickerRecord.getSize(), StickerSlide.WIDTH, StickerSlide.HEIGHT, null, String.valueOf(new SecureRandom().nextLong()), false, false, null, stickerLocator, null, null, null)); } else { return Optional.of(PointerAttachment.forPointer(Optional.of(sticker.get().getAttachment()), stickerLocator).get()); } }
Example #18
Source File: AttachmentServer.java From deltachat-android with GNU General Public License v3.0 | 5 votes |
public AttachmentServer(Context context, Attachment attachment) throws IOException { try { this.context = context; this.attachment = attachment; this.socket = new ServerSocket(0, 0, InetAddress.getByAddress(new byte[]{127, 0, 0, 1})); this.port = socket.getLocalPort(); this.auth = Hex.toStringCondensed(Util.getSecretBytes(16)); this.socket.setSoTimeout(5000); } catch (UnknownHostException e) { throw new AssertionError(e); } }
Example #19
Source File: WakeGroupV2Job.java From mollyim-android with GNU General Public License v3.0 | 5 votes |
@Override public @NonNull WakeGroupV2Job create(@NonNull Parameters parameters, @NonNull Data data) { try { return new WakeGroupV2Job(parameters, new GroupMasterKey(Hex.fromStringCondensed(data.getString(KEY_GROUP_MASTER_KEY)))); } catch (InvalidInputException | IOException e) { throw new AssertionError(e); } }
Example #20
Source File: UpdateApkJob.java From mollyim-android with GNU General Public License v3.0 | 5 votes |
private @Nullable byte[] getPendingDigest(Context context) { try { String encodedDigest = TextSecurePreferences.getUpdateApkDigest(context); if (encodedDigest == null) return null; return Hex.fromStringCondensed(encodedDigest); } catch (IOException e) { Log.w(TAG, e); return null; } }
Example #21
Source File: UpdateApkJob.java From mollyim-android with GNU General Public License v3.0 | 5 votes |
@Override public void onRun() throws IOException, PackageManager.NameNotFoundException { if (!BuildConfig.AUTOMATIC_UPDATES) return; Log.i(TAG, "Checking for APK update..."); OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder().url(String.format("%s/latest.json", BuildConfig.NOPLAY_UPDATE_URL)).build(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) { throw new IOException("Bad response: " + response.message()); } UpdateDescriptor updateDescriptor = JsonUtils.fromJson(response.body().string(), UpdateDescriptor.class); byte[] digest = Hex.fromStringCondensed(updateDescriptor.getDigest()); Log.i(TAG, "Got descriptor: " + updateDescriptor); if (updateDescriptor.getVersionCode() > getVersionCode()) { DownloadStatus downloadStatus = getDownloadStatus(updateDescriptor.getUrl(), digest); Log.i(TAG, "Download status: " + downloadStatus.getStatus()); if (downloadStatus.getStatus() == DownloadStatus.Status.COMPLETE) { Log.i(TAG, "Download status complete, notifying..."); handleDownloadNotify(downloadStatus.getDownloadId()); } else if (downloadStatus.getStatus() == DownloadStatus.Status.MISSING) { Log.i(TAG, "Download status missing, starting download..."); handleDownloadStart(updateDescriptor.getUrl(), updateDescriptor.getVersionName(), digest); } } }
Example #22
Source File: PublicKey.java From mollyim-android with GNU General Public License v3.0 | 5 votes |
public byte[] serialize() { byte[] keyIdBytes = Conversions.mediumToByteArray(id); byte[] serializedPoint = publicKey.serialize(); Log.i(TAG, "Serializing public key point: " + Hex.toString(serializedPoint)); return Util.combine(keyIdBytes, serializedPoint); }
Example #23
Source File: GroupId.java From mollyim-android with GNU General Public License v3.0 | 4 votes |
private static byte[] extractDecodedId(@NonNull String encodedGroupId) throws IOException { return Hex.fromStringCondensed(encodedGroupId.split("!", 2)[1]); }
Example #24
Source File: GroupId.java From mollyim-android with GNU General Public License v3.0 | 4 votes |
private GroupId(@NonNull String prefix, @NonNull byte[] bytes) { this.encodedId = prefix + Hex.toStringCondensed(bytes); }
Example #25
Source File: DatabaseSecret.java From mollyim-android with GNU General Public License v3.0 | 4 votes |
public DatabaseSecret(@NonNull byte[] key) { this.key = key; this.encoded = Hex.toStringCondensed(key); }
Example #26
Source File: JsonSticker.java From signald with GNU General Public License v3.0 | 4 votes |
JsonSticker(SignalServiceDataMessage.Sticker sticker, String username) throws IOException, NoSuchAccountException { packID = Hex.toStringCondensed(sticker.getPackId()); packKey = Hex.toStringCondensed(sticker.getPackKey()); stickerID = sticker.getStickerId(); attachment = new JsonAttachment(sticker.getAttachment(), username); }
Example #27
Source File: HexDeserializer.java From mollyim-android with GNU General Public License v3.0 | 4 votes |
@Override public byte[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { return Hex.fromStringCondensed(p.getText()); }
Example #28
Source File: GroupIdTest.java From mollyim-android with GNU General Public License v3.0 | 4 votes |
@Test(expected = AssertionError.class) public void cannot_create_v2_with_a_v1_length_assert() throws IOException { GroupId.v2orThrow(Hex.fromStringCondensed("000102030405060708090a0b0c0d0e0f")); }
Example #29
Source File: GroupIdTest.java From mollyim-android with GNU General Public License v3.0 | 4 votes |
@Test(expected = BadGroupIdException.class) public void cannot_create_v2_with_a_v1_length() throws IOException, BadGroupIdException { GroupId.v2(Hex.fromStringCondensed("000102030405060708090a0b0c0d0e0f")); }
Example #30
Source File: GroupIdTest.java From mollyim-android with GNU General Public License v3.0 | 4 votes |
@Test(expected = AssertionError.class) public void cannot_create_v1_with_a_v2_length() throws IOException { GroupId.v1orThrow(Hex.fromStringCondensed("9f475f59b2518bff6df22e820803f0e3585bd99e686fa7e7fbfc2f92fd5d953e")); }