001package com.bitbucket.thinbus.srp6.js; 002 003import java.math.BigInteger; 004import java.nio.charset.Charset; 005import java.nio.file.Files; 006import java.nio.file.Paths; 007import java.security.MessageDigest; 008import java.util.ArrayList; 009import java.util.List; 010import java.util.regex.Matcher; 011import java.util.regex.Pattern; 012 013import com.nimbusds.srp6.SRP6Routines; 014 015/** 016 * A class to parse the output of 'openssl dhparam -text bits' where bits is the 017 * prime number bit length. Will output 'N', 'g', 'k' in bases 10, 10, 16 018 * respectively. Note that k is derived from 'N' and 'g' but Nimbus 1.4.x 019 * currently uses a the byte array constructor of BigInteger to computes 'k' 020 * which is not available in Javascript so the value genenerated by Java needs 021 * to be configure in the Javascript. 022 */ 023public class OpenSSLCryptoConfigConverter { 024 025 final SRP6Routines srp6Routines = new SRP6Routines(); 026 027 public List<String> run(String hash, List<String> lines) throws Exception { 028 int generator = 0; 029 StringBuilder hexparts = new StringBuilder(); 030 031 for (String line : lines) { 032 if (line.endsWith("prime:")) { 033 // skip this one 034 } else if (line.endsWith(":")) { 035 hexparts.append(line.trim()); 036 } else if (line.contains("generator")) { 037 try { 038 generator = generator(line.trim()); 039 } catch (Exception e) { 040 throw new AssertionError( 041 "could not parse 'generator: x' number out of line containing 'generator': " 042 + line); 043 } 044 } 045 } 046 047 if (generator <= 0) { 048 throw new AssertionError( 049 "could not parse 'generator: x' number out of line containing 'generator'"); 050 } 051 052 String primeHex = hexparts.toString().replace(":", ""); 053 054 List<String> output = new ArrayList<String>(); 055 056 BigInteger N = new BigInteger(primeHex, 16); 057 BigInteger g = new BigInteger(generator + ""); 058 059 output.add("hashing to create 'k' using " + hash); 060 061 MessageDigest digest = MessageDigest.getInstance(hash); 062 BigInteger k = srp6Routines.computeK(digest, N, g); 063 064 output.add("computing..."); 065 output.add("N base10: " + N.toString(10)); 066 output.add("g base10: " + g.toString(10)); 067 output.add("k base16: " + k.toString(16)); 068 069 return output; 070 } 071 072 public static void main(String[] args) throws Exception { 073 074 if (args.length != 2) { 075 System.err.println("Arguments: file hash "); 076 System.err.println("Example : /tmp/my_dhparam.txt SHA-256 "); 077 System.exit(1); 078 } 079 080 final String file = args[0]; 081 final String hash = args[1]; 082 083 System.out 084 .println(String 085 .format("Attempting to load 'openssl dhparam -text <bitlength>' output text file at: %s", 086 file)); 087 088 final List<String> lines = Files.readAllLines(Paths.get(args[0]), 089 Charset.forName("UTF8")); 090 091 System.out.println(String.format("Loaded %s lines.", lines.size())); 092 093 System.out.println(String.format( 094 "Creating configuration parmeters using hash algorithm %s.", 095 hash)); 096 097 for (String output : (new OpenSSLCryptoConfigConverter()).run(hash, 098 lines)) { 099 System.out.println(output); 100 } 101 } 102 103 static Pattern generatorPattern = Pattern 104 .compile(".*generator: (\\d*) \\(.*"); 105 106 private static int generator(String line) { 107 Matcher matcher = generatorPattern.matcher(line); 108 matcher.matches(); 109 String number = matcher.group(1); 110 return Integer.valueOf(number); 111 } 112}