1package eu.siacs.conversations.utils;
2
3import java.security.SecureRandom;
4import java.text.Normalizer;
5import java.util.Arrays;
6import java.util.Collection;
7import java.util.LinkedHashSet;
8import java.util.List;
9
10import eu.siacs.conversations.Config;
11
12public final class CryptoHelper {
13 public static final String FILETRANSFER = "?FILETRANSFERv1:";
14 private final static char[] hexArray = "0123456789abcdef".toCharArray();
15 private final static char[] vowels = "aeiou".toCharArray();
16 private final static char[] consonants = "bcdfghjklmnpqrstvwxyz".toCharArray();
17 final public static byte[] ONE = new byte[] { 0, 0, 0, 1 };
18
19 public static String bytesToHex(byte[] bytes) {
20 char[] hexChars = new char[bytes.length * 2];
21 for (int j = 0; j < bytes.length; j++) {
22 int v = bytes[j] & 0xFF;
23 hexChars[j * 2] = hexArray[v >>> 4];
24 hexChars[j * 2 + 1] = hexArray[v & 0x0F];
25 }
26 return new String(hexChars);
27 }
28
29 public static byte[] hexToBytes(String hexString) {
30 int len = hexString.length();
31 byte[] array = new byte[len / 2];
32 for (int i = 0; i < len; i += 2) {
33 array[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character
34 .digit(hexString.charAt(i + 1), 16));
35 }
36 return array;
37 }
38
39 public static String hexToString(final String hexString) {
40 return new String(hexToBytes(hexString));
41 }
42
43 public static byte[] concatenateByteArrays(byte[] a, byte[] b) {
44 byte[] result = new byte[a.length + b.length];
45 System.arraycopy(a, 0, result, 0, a.length);
46 System.arraycopy(b, 0, result, a.length, b.length);
47 return result;
48 }
49
50 public static String randomMucName(SecureRandom random) {
51 return randomWord(3, random) + "." + randomWord(7, random);
52 }
53
54 private static String randomWord(int lenght, SecureRandom random) {
55 StringBuilder builder = new StringBuilder(lenght);
56 for (int i = 0; i < lenght; ++i) {
57 if (i % 2 == 0) {
58 builder.append(consonants[random.nextInt(consonants.length)]);
59 } else {
60 builder.append(vowels[random.nextInt(vowels.length)]);
61 }
62 }
63 return builder.toString();
64 }
65
66 /**
67 * Escapes usernames or passwords for SASL.
68 */
69 public static String saslEscape(final String s) {
70 final StringBuilder sb = new StringBuilder((int) (s.length() * 1.1));
71 for (int i = 0; i < s.length(); i++) {
72 char c = s.charAt(i);
73 switch (c) {
74 case ',':
75 sb.append("=2C");
76 break;
77 case '=':
78 sb.append("=3D");
79 break;
80 default:
81 sb.append(c);
82 break;
83 }
84 }
85 return sb.toString();
86 }
87
88 public static String saslPrep(final String s) {
89 return Normalizer.normalize(s, Normalizer.Form.NFKC);
90 }
91
92 public static String prettifyFingerprint(String fingerprint) {
93 StringBuilder builder = new StringBuilder(fingerprint);
94 builder.insert(8, " ");
95 builder.insert(17, " ");
96 builder.insert(26, " ");
97 builder.insert(35, " ");
98 return builder.toString();
99 }
100
101 public static String[] getOrderedCipherSuites(final String[] platformSupportedCipherSuites) {
102 final Collection<String> cipherSuites = new LinkedHashSet<>(Arrays.asList(Config.ENABLED_CIPHERS));
103 final List<String> platformCiphers = Arrays.asList(platformSupportedCipherSuites);
104 cipherSuites.retainAll(platformCiphers);
105 cipherSuites.addAll(platformCiphers);
106 return cipherSuites.toArray(new String[cipherSuites.size()]);
107 }
108}