]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.util/src/org/argeo/util/directory/DirectoryDigestUtils.java
Introduce argeo-desktop-open
[lgpl/argeo-commons.git] / org.argeo.util / src / org / argeo / util / directory / DirectoryDigestUtils.java
1 package org.argeo.util.directory;
2
3 import java.math.BigInteger;
4 import java.nio.ByteBuffer;
5 import java.nio.CharBuffer;
6 import java.nio.charset.StandardCharsets;
7 import java.security.MessageDigest;
8 import java.security.NoSuchAlgorithmException;
9 import java.security.spec.InvalidKeySpecException;
10 import java.security.spec.KeySpec;
11 import java.util.Arrays;
12
13 import javax.crypto.SecretKeyFactory;
14 import javax.crypto.spec.PBEKeySpec;
15
16 /** Utilities around digests, mostly those related to passwords. */
17 public class DirectoryDigestUtils {
18 public final static String PASSWORD_SCHEME_SHA = "SHA";
19 public final static String PASSWORD_SCHEME_PBKDF2_SHA256 = "PBKDF2_SHA256";
20
21 public static byte[] sha1(byte[] bytes) {
22 try {
23 MessageDigest digest = MessageDigest.getInstance("SHA1");
24 digest.update(bytes);
25 byte[] checksum = digest.digest();
26 return checksum;
27 } catch (NoSuchAlgorithmException e) {
28 throw new IllegalStateException("Cannot SHA1 digest", e);
29 }
30 }
31
32 public static byte[] toPasswordScheme(String passwordScheme, char[] password, byte[] salt, Integer iterations,
33 Integer keyLength) {
34 try {
35 if (PASSWORD_SCHEME_SHA.equals(passwordScheme)) {
36 MessageDigest digest = MessageDigest.getInstance("SHA1");
37 byte[] bytes = charsToBytes(password);
38 digest.update(bytes);
39 return digest.digest();
40 } else if (PASSWORD_SCHEME_PBKDF2_SHA256.equals(passwordScheme)) {
41 KeySpec spec = new PBEKeySpec(password, salt, iterations, keyLength);
42
43 SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
44 final int ITERATION_LENGTH = 4;
45 byte[] key = f.generateSecret(spec).getEncoded();
46 byte[] result = new byte[ITERATION_LENGTH + salt.length + key.length];
47 byte iterationsArr[] = new BigInteger(iterations.toString()).toByteArray();
48 if (iterationsArr.length < ITERATION_LENGTH) {
49 Arrays.fill(result, 0, ITERATION_LENGTH - iterationsArr.length, (byte) 0);
50 System.arraycopy(iterationsArr, 0, result, ITERATION_LENGTH - iterationsArr.length,
51 iterationsArr.length);
52 } else {
53 System.arraycopy(iterationsArr, 0, result, 0, ITERATION_LENGTH);
54 }
55 System.arraycopy(salt, 0, result, ITERATION_LENGTH, salt.length);
56 System.arraycopy(key, 0, result, ITERATION_LENGTH + salt.length, key.length);
57 return result;
58 } else {
59 throw new UnsupportedOperationException("Unkown password scheme " + passwordScheme);
60 }
61 } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
62 throw new IllegalStateException("Cannot digest", e);
63 }
64 }
65
66 public static char[] bytesToChars(Object obj) {
67 if (obj instanceof char[])
68 return (char[]) obj;
69 if (!(obj instanceof byte[]))
70 throw new IllegalArgumentException(obj.getClass() + " is not a byte array");
71 ByteBuffer fromBuffer = ByteBuffer.wrap((byte[]) obj);
72 CharBuffer toBuffer = StandardCharsets.UTF_8.decode(fromBuffer);
73 char[] res = Arrays.copyOfRange(toBuffer.array(), toBuffer.position(), toBuffer.limit());
74 // Arrays.fill(fromBuffer.array(), (byte) 0); // clear sensitive data
75 // Arrays.fill((byte[]) obj, (byte) 0); // clear sensitive data
76 // Arrays.fill(toBuffer.array(), '\u0000'); // clear sensitive data
77 return res;
78 }
79
80 public static byte[] charsToBytes(char[] chars) {
81 CharBuffer charBuffer = CharBuffer.wrap(chars);
82 ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(charBuffer);
83 byte[] bytes = Arrays.copyOfRange(byteBuffer.array(), byteBuffer.position(), byteBuffer.limit());
84 // Arrays.fill(charBuffer.array(), '\u0000'); // clear sensitive data
85 // Arrays.fill(byteBuffer.array(), (byte) 0); // clear sensitive data
86 return bytes;
87 }
88
89 public static String sha1str(String str) {
90 byte[] hash = sha1(str.getBytes(StandardCharsets.UTF_8));
91 return encodeHexString(hash);
92 }
93
94 final private static char[] hexArray = "0123456789abcdef".toCharArray();
95
96 /**
97 * From
98 * http://stackoverflow.com/questions/9655181/how-to-convert-a-byte-array-to
99 * -a-hex-string-in-java
100 */
101 public static String encodeHexString(byte[] bytes) {
102 char[] hexChars = new char[bytes.length * 2];
103 for (int j = 0; j < bytes.length; j++) {
104 int v = bytes[j] & 0xFF;
105 hexChars[j * 2] = hexArray[v >>> 4];
106 hexChars[j * 2 + 1] = hexArray[v & 0x0F];
107 }
108 return new String(hexChars);
109 }
110
111 /** singleton */
112 private DirectoryDigestUtils() {
113 }
114 }