@@ -21,6 +21,7 @@ import java.lang.reflect.Array; | |||||
import java.math.BigDecimal; | import java.math.BigDecimal; | ||||
import java.math.BigInteger; | import java.math.BigInteger; | ||||
import java.math.RoundingMode; | import java.math.RoundingMode; | ||||
import java.security.SecureRandom; | |||||
import java.util.*; | import java.util.*; | ||||
import java.util.concurrent.Callable; | import java.util.concurrent.Callable; | ||||
import java.util.concurrent.atomic.AtomicLong; | 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.concurrent.TimeUnit.SECONDS; | ||||
import static java.util.stream.LongStream.range; | import static java.util.stream.LongStream.range; | ||||
import static org.apache.commons.collections.CollectionUtils.collect; | 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.apache.commons.lang3.exception.ExceptionUtils.getStackTrace; | ||||
import static org.cobbzilla.util.error.ExceptionHandler.DEFAULT_EX_RUNNABLE; | import static org.cobbzilla.util.error.ExceptionHandler.DEFAULT_EX_RUNNABLE; | ||||
import static org.cobbzilla.util.io.FileUtil.abs; | 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(int val) { return new BigInteger(String.valueOf(val)); } | ||||
public static BigInteger bigint(byte 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(String val) { return new BigDecimal(val); } | ||||
public static BigDecimal big(double val) { return new BigDecimal(String.valueOf(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)); } | 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(); } | 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 long getSystemTimeOffset () { return systemTimeOffset.get(); } | ||||
public static void setSystemTimeOffset (long t) { systemTimeOffset.set(t); } | public static void setSystemTimeOffset (long t) { systemTimeOffset.set(t); } | ||||
public static long incrementSystemTimeOffset(long t) { return systemTimeOffset.addAndGet(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.io.StringWriter; | ||||
import java.lang.reflect.Method; | import java.lang.reflect.Method; | ||||
import java.math.BigDecimal; | import java.math.BigDecimal; | ||||
import java.math.BigInteger; | |||||
import java.math.MathContext; | import java.math.MathContext; | ||||
import java.net.InetAddress; | |||||
import java.util.*; | import java.util.*; | ||||
import java.util.concurrent.ExecutorService; | import java.util.concurrent.ExecutorService; | ||||
import java.util.concurrent.atomic.AtomicReference; | import java.util.concurrent.atomic.AtomicReference; | ||||
import java.util.regex.Pattern; | import java.util.regex.Pattern; | ||||
import static java.util.regex.Pattern.quote; | 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.collection.ArrayUtil.arrayToString; | ||||
import static org.cobbzilla.util.daemon.DaemonThreadFactory.fixedPool; | import static org.cobbzilla.util.daemon.DaemonThreadFactory.fixedPool; | ||||
import static org.cobbzilla.util.daemon.ZillaRuntime.*; | 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.io.StreamUtil.stream2string; | ||||
import static org.cobbzilla.util.json.JsonUtil.getJsonStringEncoder; | import static org.cobbzilla.util.json.JsonUtil.getJsonStringEncoder; | ||||
import static org.cobbzilla.util.json.JsonUtil.json; | 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.security.ShaUtil.sha256_hex; | ||||
import static org.cobbzilla.util.string.Base64.encodeBytes; | import static org.cobbzilla.util.string.Base64.encodeBytes; | ||||
import static org.cobbzilla.util.string.Base64.encodeFromFile; | 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 kind = options.param(0, "alphanumeric"); | ||||
final String alphaCase = options.param(1, "lowercase"); | final String alphaCase = options.param(1, "lowercase"); | ||||
switch (kind) { | 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 "alpha": case "alphabetic": return new Handlebars.SafeString(adjustCase(RandomStringUtils.randomAlphabetic(len), alphaCase)); | ||||
case "num": case "numeric": return new Handlebars.SafeString(RandomStringUtils.randomNumeric(len)); | 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) -> { | hb.registerHelper("truncate", (Helper<Integer>) (max, options) -> { | ||||
final String val = options.param(0, " "); | final String val = options.param(0, " "); | ||||
if (empty(val)) return ""; | 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) { | private static String adjustCase(String val, String alphaCase) { | ||||
switch (alphaCase) { | switch (alphaCase) { | ||||
case "lower": case "lowercase": case "lc": return val.toLowerCase(); | 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.File; | ||||
import java.io.IOException; | 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.*; | ||||
import java.util.stream.Collectors; | 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 { | public static Set<String> toHostSet(File file) throws IOException { | ||||
return toHostSet(FileUtil.toStringList(file)); | return toHostSet(FileUtil.toStringList(file)); | ||||
} | } | ||||
@@ -18,6 +18,8 @@ import java.io.UnsupportedEncodingException; | |||||
import java.security.SecureRandom; | import java.security.SecureRandom; | ||||
import static org.cobbzilla.util.daemon.ZillaRuntime.RANDOM; | |||||
/** | /** | ||||
* BCrypt implements OpenBSD-style Blowfish password hashing using | * BCrypt implements OpenBSD-style Blowfish password hashing using | ||||
* the scheme described in "A Future-Adaptable Password Scheme" by | * the scheme described in "A Future-Adaptable Password Scheme" by | ||||
@@ -726,7 +728,7 @@ public class BCrypt { | |||||
* @return an encoded salt value | * @return an encoded salt value | ||||
*/ | */ | ||||
public static String gensalt(int log_rounds) { | 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 lombok.extern.slf4j.Slf4j; | ||||
import java.security.SecureRandom; | |||||
import static org.cobbzilla.util.daemon.ZillaRuntime.RANDOM; | |||||
@Slf4j | @Slf4j | ||||
public class BCryptUtil { | public class BCryptUtil { | ||||
private static final SecureRandom random = new SecureRandom(); | |||||
private static volatile Integer bcryptRounds = null; | private static volatile Integer bcryptRounds = null; | ||||
public synchronized static void setBcryptRounds(int rounds) { | public synchronized static void setBcryptRounds(int rounds) { | ||||
@@ -23,7 +21,7 @@ public class BCryptUtil { | |||||
public static Integer getBcryptRounds() { return bcryptRounds; } | public static Integer getBcryptRounds() { return bcryptRounds; } | ||||
public static String hash(String password) { | 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) { | public static void main (String[] args) { | ||||