@@ -21,6 +21,7 @@ import java.lang.reflect.Array; | |||
import java.math.BigDecimal; | |||
import java.math.BigInteger; | |||
import java.math.RoundingMode; | |||
import java.security.SecureRandom; | |||
import java.util.*; | |||
import java.util.concurrent.Callable; | |||
import java.util.concurrent.atomic.AtomicLong; | |||
@@ -31,6 +32,7 @@ import static java.lang.Long.toHexString; | |||
import static java.util.concurrent.TimeUnit.SECONDS; | |||
import static java.util.stream.LongStream.range; | |||
import static org.apache.commons.collections.CollectionUtils.collect; | |||
import static org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric; | |||
import static org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace; | |||
import static org.cobbzilla.util.error.ExceptionHandler.DEFAULT_EX_RUNNABLE; | |||
import static org.cobbzilla.util.io.FileUtil.abs; | |||
@@ -291,6 +293,17 @@ public class ZillaRuntime { | |||
public static BigInteger bigint(int val) { return new BigInteger(String.valueOf(val)); } | |||
public static BigInteger bigint(byte val) { return new BigInteger(String.valueOf(val)); } | |||
public static BigInteger random_bigint(BigInteger limit) { return random_bigint(limit, RANDOM); } | |||
// adapted from https://stackoverflow.com/a/2290089/1251543 | |||
public static BigInteger random_bigint(BigInteger limit, SecureRandom rand) { | |||
BigInteger randomNumber; | |||
do { | |||
randomNumber = new BigInteger(limit.bitLength(), rand); | |||
} while (randomNumber.compareTo(limit) >= 0); | |||
return randomNumber; | |||
} | |||
public static BigDecimal big(String val) { return new BigDecimal(val); } | |||
public static BigDecimal big(double val) { return new BigDecimal(String.valueOf(val)); } | |||
public static BigDecimal big(float val) { return new BigDecimal(String.valueOf(val)); } | |||
@@ -310,7 +323,10 @@ public class ZillaRuntime { | |||
public static String uuid() { return UUID.randomUUID().toString(); } | |||
private static AtomicLong systemTimeOffset = new AtomicLong(0L); | |||
private static final AtomicLong systemTimeOffset = new AtomicLong(0L); | |||
public static final SecureRandom RANDOM = new SecureRandom((randomAlphanumeric(20)+now()).getBytes()); | |||
public static long getSystemTimeOffset () { return systemTimeOffset.get(); } | |||
public static void setSystemTimeOffset (long t) { systemTimeOffset.set(t); } | |||
public static long incrementSystemTimeOffset(long t) { return systemTimeOffset.addAndGet(t); } | |||
@@ -43,13 +43,16 @@ import java.io.IOException; | |||
import java.io.StringWriter; | |||
import java.lang.reflect.Method; | |||
import java.math.BigDecimal; | |||
import java.math.BigInteger; | |||
import java.math.MathContext; | |||
import java.net.InetAddress; | |||
import java.util.*; | |||
import java.util.concurrent.ExecutorService; | |||
import java.util.concurrent.atomic.AtomicReference; | |||
import java.util.regex.Pattern; | |||
import static java.util.regex.Pattern.quote; | |||
import static org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric; | |||
import static org.cobbzilla.util.collection.ArrayUtil.arrayToString; | |||
import static org.cobbzilla.util.daemon.DaemonThreadFactory.fixedPool; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.*; | |||
@@ -59,6 +62,8 @@ import static org.cobbzilla.util.io.StreamUtil.loadResourceAsStream; | |||
import static org.cobbzilla.util.io.StreamUtil.stream2string; | |||
import static org.cobbzilla.util.json.JsonUtil.getJsonStringEncoder; | |||
import static org.cobbzilla.util.json.JsonUtil.json; | |||
import static org.cobbzilla.util.network.NetworkUtil.big2ip4; | |||
import static org.cobbzilla.util.network.NetworkUtil.big2ip6; | |||
import static org.cobbzilla.util.security.ShaUtil.sha256_hex; | |||
import static org.cobbzilla.util.string.Base64.encodeBytes; | |||
import static org.cobbzilla.util.string.Base64.encodeFromFile; | |||
@@ -508,12 +513,43 @@ public class HandlebarsUtil extends AbstractTemplateLoader { | |||
final String kind = options.param(0, "alphanumeric"); | |||
final String alphaCase = options.param(1, "lowercase"); | |||
switch (kind) { | |||
case "alphanumeric": case "alnum": default: return new Handlebars.SafeString(adjustCase(RandomStringUtils.randomAlphanumeric(len), alphaCase)); | |||
case "alphanumeric": case "alnum": default: return new Handlebars.SafeString(adjustCase(randomAlphanumeric(len), alphaCase)); | |||
case "alpha": case "alphabetic": return new Handlebars.SafeString(adjustCase(RandomStringUtils.randomAlphabetic(len), alphaCase)); | |||
case "num": case "numeric": return new Handlebars.SafeString(RandomStringUtils.randomNumeric(len)); | |||
} | |||
}); | |||
hb.registerHelper("rand_ip", (Helper<String>) (cidr, options) -> { | |||
final String seed = options.param(0, null); | |||
final int slashPos = cidr.indexOf("/"); | |||
if (slashPos == -1 || slashPos == cidr.length()-1) return die("rand_ip: invalid cidr: "+cidr); | |||
final int fixedBits = Integer.parseInt(cidr.substring(slashPos+1)); | |||
final String network = cidr.substring(0, slashPos); | |||
final InetAddress addr = InetAddress.getByName(network); | |||
final BigInteger addrInt = new BigInteger(1, addr.getAddress()); | |||
final boolean v6 = cidr.contains(":"); | |||
final int randBits = (v6 ? 128 : 32) - fixedBits; | |||
final BigInteger offset = seed == null | |||
? random_bigint(bigint(2).pow(randBits)) | |||
: new BigInteger(sha256_hex(parseRandSeed(seed)), 16).and(new BigInteger("1".repeat(randBits), 2)); | |||
final BigInteger randIpInt = addrInt.add(offset); | |||
String randAddr = (v6 ? big2ip6(randIpInt) : big2ip4(randIpInt)).toString(); | |||
if (v6) { | |||
// coerce oddball to :1 | |||
if (randAddr.endsWith("::")) { | |||
randAddr = randAddr.substring(0, randAddr.lastIndexOf("::")) + ":1"; | |||
} else if (randAddr.endsWith(":0") || randAddr.endsWith(":0000") || randAddr.endsWith(":ffff")) { | |||
randAddr = randAddr.substring(0, randAddr.lastIndexOf(":")) + ":1"; | |||
} | |||
} else { | |||
if (randAddr.endsWith(".0") || randAddr.endsWith(".255")) { | |||
// coerce oddball to .1 | |||
randAddr = randAddr.substring(0, randAddr.lastIndexOf(".")) + ".1"; | |||
} | |||
} | |||
return new Handlebars.SafeString(randAddr); | |||
}); | |||
hb.registerHelper("truncate", (Helper<Integer>) (max, options) -> { | |||
final String val = options.param(0, " "); | |||
if (empty(val)) return ""; | |||
@@ -599,6 +635,12 @@ public class HandlebarsUtil extends AbstractTemplateLoader { | |||
}); | |||
} | |||
public static String parseRandSeed(String seed) { | |||
if (seed.equals("!host")) return hostname(); | |||
if (seed.equals("!domain")) return domainname(); | |||
return seed; | |||
} | |||
private static String adjustCase(String val, String alphaCase) { | |||
switch (alphaCase) { | |||
case "lower": case "lowercase": case "lc": return val.toLowerCase(); | |||
@@ -8,8 +8,8 @@ import org.cobbzilla.util.io.FileUtil; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.net.InetAddress; | |||
import java.net.NetworkInterface; | |||
import java.math.BigInteger; | |||
import java.net.*; | |||
import java.util.*; | |||
import java.util.stream.Collectors; | |||
@@ -217,6 +217,26 @@ public class NetworkUtil { | |||
} | |||
} | |||
// adapted from https://stackoverflow.com/a/19238983/1251543 | |||
public static Inet6Address big2ip6(BigInteger ipNumber) throws UnknownHostException { | |||
String ipString = ""; | |||
final BigInteger a = new BigInteger("FFFF", 16); | |||
for (int i=0; i<8; i++) { | |||
ipString = ipNumber.and(a).toString(16)+":"+ipString; | |||
ipNumber = ipNumber.shiftRight(16); | |||
} | |||
return (Inet6Address) Inet6Address.getByName(ipString.substring(0, ipString.length()-1)); | |||
} | |||
public static Inet4Address big2ip4(BigInteger ipNumber) throws UnknownHostException { | |||
String ipString = ""; | |||
final BigInteger a = new BigInteger("FF", 16); | |||
for (int i=0; i<4; i++) { | |||
ipString = ipNumber.and(a).toString(10)+"."+ipString; | |||
ipNumber = ipNumber.shiftRight(8); | |||
} | |||
return (Inet4Address) Inet4Address.getByName(ipString.substring(0, ipString.length()-1)); | |||
} | |||
public static Set<String> toHostSet(File file) throws IOException { | |||
return toHostSet(FileUtil.toStringList(file)); | |||
} | |||
@@ -18,6 +18,8 @@ import java.io.UnsupportedEncodingException; | |||
import java.security.SecureRandom; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.RANDOM; | |||
/** | |||
* BCrypt implements OpenBSD-style Blowfish password hashing using | |||
* the scheme described in "A Future-Adaptable Password Scheme" by | |||
@@ -726,7 +728,7 @@ public class BCrypt { | |||
* @return an encoded salt value | |||
*/ | |||
public static String gensalt(int log_rounds) { | |||
return gensalt(log_rounds, new SecureRandom()); | |||
return gensalt(log_rounds, RANDOM); | |||
} | |||
/** | |||
@@ -2,13 +2,11 @@ package org.cobbzilla.util.security.bcrypt; | |||
import lombok.extern.slf4j.Slf4j; | |||
import java.security.SecureRandom; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.RANDOM; | |||
@Slf4j | |||
public class BCryptUtil { | |||
private static final SecureRandom random = new SecureRandom(); | |||
private static volatile Integer bcryptRounds = null; | |||
public synchronized static void setBcryptRounds(int rounds) { | |||
@@ -23,7 +21,7 @@ public class BCryptUtil { | |||
public static Integer getBcryptRounds() { return bcryptRounds; } | |||
public static String hash(String password) { | |||
return BCrypt.hashpw(password, BCrypt.gensalt(getBcryptRounds(), random)); | |||
return BCrypt.hashpw(password, BCrypt.gensalt(getBcryptRounds(), RANDOM)); | |||
} | |||
public static void main (String[] args) { | |||