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 public List<String> run(String hash, List<String> lines) throws Exception { 026 int generator = 0; 027 StringBuilder hexparts = new StringBuilder(); 028 029 for (String line : lines) { 030 if (line.endsWith("prime:")) { 031 // skip this one 032 } else if (line.endsWith(":")) { 033 hexparts.append(line.trim()); 034 } else if (line.contains("generator")) { 035 try { 036 generator = generator(line.trim()); 037 } catch (Exception e) { 038 throw new AssertionError( 039 "could not parse 'generator: x' number out of line containing 'generator': " 040 + line); 041 } 042 } 043 } 044 045 if (generator <= 0) { 046 throw new AssertionError( 047 "could not parse 'generator: x' number out of line containing 'generator'"); 048 } 049 050 String primeHex = hexparts.toString().replace(":", ""); 051 052 List<String> output = new ArrayList<String>(); 053 054 BigInteger N = new BigInteger(primeHex, 16); 055 BigInteger g = new BigInteger(generator + ""); 056 057 output.add("hashing to create 'k' using " + hash); 058 059 MessageDigest digest = MessageDigest.getInstance(hash); 060 BigInteger k = SRP6Routines.computeK(digest, N, g); 061 062 output.add("computing..."); 063 output.add("N base10: " + N.toString(10)); 064 output.add("g base10: " + g.toString(10)); 065 output.add("k base16: " + k.toString(16)); 066 067 return output; 068 } 069 070 public static void main(String[] args) throws Exception { 071 072 if (args.length != 2) { 073 System.err.println("Arguments: file hash "); 074 System.err.println("Example : /tmp/my_dhparam.txt SHA-256 "); 075 System.exit(1); 076 } 077 078 final String file = args[0]; 079 final String hash = args[1]; 080 081 System.out 082 .println(String 083 .format("Attempting to load 'openssl dhparam -text <bitlength>' output text file at: %s", 084 file)); 085 086 final List<String> lines = Files.readAllLines(Paths.get(args[0]), 087 Charset.forName("UTF8")); 088 089 System.out.println(String.format("Loaded %s lines.", lines.size())); 090 091 System.out.println(String.format( 092 "Creating configuration parmeters using hash algorithm %s.", 093 hash)); 094 095 for (String output : (new OpenSSLCryptoConfigConverter()).run(hash, 096 lines)) { 097 System.out.println(output); 098 } 099 } 100 101 static Pattern generatorPattern = Pattern 102 .compile(".*generator: (\\d*) \\(.*"); 103 104 private static int generator(String line) { 105 Matcher matcher = generatorPattern.matcher(line); 106 matcher.matches(); 107 String number = matcher.group(1); 108 return Integer.valueOf(number); 109 } 110}