001package com.bitbucket.thinbus.srp6.js; 002 003import static com.nimbusds.srp6.BigIntegerUtils.toHex; 004 005import java.math.BigInteger; 006import java.nio.charset.Charset; 007import java.security.MessageDigest; 008 009/** 010 * Secure Remote Password (SRP-6a) hashing routine for Java compatible with 011 * browser implementations by using hashing of string concatenated hex strings. 012 * 013 * <p> 014 * Specification RFC 2945 015 * 016 * @author Simon Massey 017 */ 018public class HexHashedRoutines { 019 020 public final static Charset utf8 = utf8(); 021 022 static Charset utf8() { 023 return Charset.forName("UTF8"); 024 } 025 026 public static BigInteger hashValues(final MessageDigest digest, final String... values) { 027 final StringBuilder builder = new StringBuilder(); 028 for (String v : values) { 029 builder.append(v); 030 } 031 final byte[] bytes = builder.toString().getBytes(utf8); 032 digest.update(bytes, 0, bytes.length); 033 return new BigInteger(1, digest.digest()); 034 } 035 036 private HexHashedRoutines() { 037 // empty 038 } 039 040 public static String leadingZerosPad(String value, int desiredLength) { 041 StringBuilder builder = new StringBuilder(); 042 int difference = desiredLength - value.length(); 043 for (int i = 0; i < difference; i++) { 044 builder.append('0'); 045 } 046 builder.append(value); 047 return builder.toString(); 048 } 049 050 public static String hashCredentials(MessageDigest digest, String salt, 051 String identity, String password) { 052 digest.reset(); 053 054 String concat = identity + ":" + password; 055 056 digest.update(concat.getBytes(utf8)); 057 byte[] output = digest.digest(); 058 digest.reset(); 059 060 final String hash1 = toHex(new BigInteger(1, output)); 061 concat = (salt + hash1).toUpperCase(); 062 063 digest.update(concat.getBytes(utf8)); 064 output = digest.digest(); 065 066 return toHexString(output); 067 } 068 069 final private static char[] hexArray = "0123456789abcdef".toCharArray(); 070 071 /** 072 * http://stackoverflow.com/a/9855338 073 * 074 * Compute a String in HexDigit from the input. Note that this string may 075 * have leading zeros but hex strings created by toString(16) of BigInteger 076 * would strip leading zeros. 077 * 078 * @param bytes 079 * Raw byte array 080 * @return Hex encoding of the input 081 */ 082 public static String toHexString(final byte[] bytes) { 083 char[] hexChars = new char[bytes.length * 2]; 084 for (int j = 0; j < bytes.length; j++) { 085 int v = bytes[j] & 0xFF; 086 hexChars[j * 2] = hexArray[v >>> 4]; 087 hexChars[j * 2 + 1] = hexArray[v & 0x0F]; 088 } 089 return new String(hexChars); 090 } 091}