]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/util/ProfileUtils.java
Fix error message
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / util / ProfileUtils.java
1 package org.asamk.signal.manager.util;
2
3 import org.asamk.signal.manager.storage.recipients.Profile;
4 import org.signal.zkgroup.profiles.ProfileKey;
5 import org.whispersystems.libsignal.util.Pair;
6 import org.whispersystems.signalservice.api.crypto.InvalidCiphertextException;
7 import org.whispersystems.signalservice.api.crypto.ProfileCipher;
8 import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
9
10 import java.util.Base64;
11 import java.util.Date;
12 import java.util.HashSet;
13
14 public class ProfileUtils {
15
16 public static Profile decryptProfile(
17 final ProfileKey profileKey, final SignalServiceProfile encryptedProfile
18 ) {
19 var profileCipher = new ProfileCipher(profileKey);
20 try {
21 var name = decrypt(encryptedProfile.getName(), profileCipher);
22 var about = decrypt(encryptedProfile.getAbout(), profileCipher);
23 var aboutEmoji = decrypt(encryptedProfile.getAboutEmoji(), profileCipher);
24
25 final var nameParts = splitName(name);
26 return new Profile(new Date().getTime(),
27 nameParts.first(),
28 nameParts.second(),
29 about,
30 aboutEmoji,
31 getUnidentifiedAccessMode(encryptedProfile, profileCipher),
32 getCapabilities(encryptedProfile));
33 } catch (InvalidCiphertextException e) {
34 return null;
35 }
36 }
37
38 public static Profile.UnidentifiedAccessMode getUnidentifiedAccessMode(
39 final SignalServiceProfile encryptedProfile, final ProfileCipher profileCipher
40 ) {
41 if (encryptedProfile.isUnrestrictedUnidentifiedAccess()) {
42 return Profile.UnidentifiedAccessMode.UNRESTRICTED;
43 }
44
45 if (encryptedProfile.getUnidentifiedAccess() != null && profileCipher != null) {
46 final var unidentifiedAccessVerifier = Base64.getDecoder().decode(encryptedProfile.getUnidentifiedAccess());
47 if (profileCipher.verifyUnidentifiedAccess(unidentifiedAccessVerifier)) {
48 return Profile.UnidentifiedAccessMode.ENABLED;
49 }
50 }
51
52 return Profile.UnidentifiedAccessMode.DISABLED;
53 }
54
55 public static HashSet<Profile.Capability> getCapabilities(final SignalServiceProfile encryptedProfile) {
56 final var capabilities = new HashSet<Profile.Capability>();
57 if (encryptedProfile.getCapabilities().isGv1Migration()) {
58 capabilities.add(Profile.Capability.gv1Migration);
59 }
60 if (encryptedProfile.getCapabilities().isGv2()) {
61 capabilities.add(Profile.Capability.gv2);
62 }
63 if (encryptedProfile.getCapabilities().isStorage()) {
64 capabilities.add(Profile.Capability.storage);
65 }
66 return capabilities;
67 }
68
69 private static String decrypt(
70 final String encryptedName, final ProfileCipher profileCipher
71 ) throws InvalidCiphertextException {
72 try {
73 return encryptedName == null
74 ? null
75 : new String(profileCipher.decrypt(Base64.getDecoder().decode(encryptedName)));
76 } catch (IllegalArgumentException e) {
77 return null;
78 }
79 }
80
81 private static Pair<String, String> splitName(String name) {
82 if (name == null) {
83 return new Pair<>(null, null);
84 }
85 String[] parts = name.split("\0");
86
87 switch (parts.length) {
88 case 0:
89 return new Pair<>(null, null);
90 case 1:
91 return new Pair<>(parts[0], null);
92 default:
93 return new Pair<>(parts[0], parts[1]);
94 }
95 }
96 }