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