跳到主要內容

Java8 SecureRandom

Random

java.util.Random 其實一點也不 Random, 因為屬於一種線性分佈,
線性不比離散, 所以就是有公式可以預測啦~

大神的論文在 這裡

https://stackoverflow.com/questions/11051205/difference-between-java-util-random-and-java-security-securerandom

The standard Oracle JDK 7 implementation uses what's called a Linear Congruential Generator to produce random values in java.util.Random.

Predictability of Linear Congruential Generators

Hugo Krawczyk wrote a pretty good paper about how these LCGs can be predicted ("How to predict congruential generators"). If you're lucky and interested, you may still find a free, downloadable version of it on the web. And there's plenty more research that clearly shows that you should never use an LCG for security-critical purposes. This also means that your random numbers are predictable right now, something you don't want for session IDs and the like.

隨機數安全議題

http://wps2015.org/drops/drops/%E8%81%8A%E4%B8%80%E8%81%8A%E9%9A%8F%E6%9C%BA%E6%95%B0%E5%AE%89%E5%85%A8.html

SecureRandom

較推薦的做法是採用 java.security.SecureRandom,


寫個簡單的 Faker


import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * Created by jerry on 2017/11/1.
 */
public class Faker {

    private SecureRandom random;
    
    public Faker() throws NoSuchAlgorithmException {
        this.random = SecureRandom.getInstance("SHA1PRNG");
    }
    
   /**
     * Generate a random alpha numbs.
     *
     * @param length
     * @return
     */
    public String randomAlphaNums(int length) {
        final char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".toCharArray();
        final String result = IntStream.range(0, length)
                .boxed()
                .map(index -> {
                    char character = chars[random.nextInt(chars.length)];
                    return String.valueOf(character);
                }).collect(Collectors.joining());

        return result;
    }

   /**
     * Generate a uuid.
     *
     * @return
     */
    public String uuid() {
        return UUID.randomUUID().toString();
    }

    /**
     * Generate a fake url
     *
     * @param domain
     * @return
     */
    public String randomUrl(String domain) {
        return new StringBuilder("https://")
                .append(domain)
                .append("/" + randomAlphaNums(5))
                .append("/" + randomAlphaNums(5))
                .toString();
    }
}


@Test
public void testAlphaNumbs() throws NoSuchAlgorithmException {
    Faker faker = new Faker();
    
    // mO03nYMKAiQi06sleVgeQSP4ZWpD5O2sr4M9PXyj6GBA0VHY2ucS9J0s4atRSRovI0EjffBoqBFL3loaLrbpKrxlkHFDHs76nMzW
    System.out.println(faker.randomAlphaNums(100));

    // https://my.domain/KMr1n/3xTIn
    System.out.println(faker.randomUrl("my.domain"));

    // 0b256f71-77bf-4dfb-8fae-850a128c785b
    System.out.println(faker.uuid());
}

題外話 Java Faker

Java Faker 是一款改寫自 Ruby's stympy/faker gem 的小工具, 在 TDD 階段還算滿實用的.



留言

這個網誌中的熱門文章

Google Compute Engine‎ - AccessDeniedExceptions 403

原因 打算從 instance 打包 logs 到 google cloud storage 發生了 AccessDeniedException: 403 Insufficient OAuth2 scope to perform this operation. , 看起來是 instance 沒有 storage 權限 解決 Reference: https://cloud.google.com/compute/docs/access/create-enable-service-accounts-for-instances#changeserviceaccountandscopes 重新設定 service account 權限 instance 上內建有 gcloud , 就直接用現有的工具查詢一下 instance 的 account. $ gsutil info 或者在本機直接 gcloud compute instances describe INSTANCE_NAMES Account: [alpha-number-compute@developer.gserviceaccount.com] Project: [our-project-name] 會看到 instance 的一些狀態, 接下來就簡單多了, 按照下列的說明, 要先 stop instance, 更改 storage scope 再重新 start 。 To change an instance's service account and access scopes, the instance must be temporarily stopped. To stop your instance, read the documentation for Stopping an instance. After changing the service account or access scopes, remember to restart the instance. # Stop Instance gcloud compute instances stop INSTANCE_NAMES # 設定 storage scope 為 full (Read, Write) gcloud co...

Parse URI query string to Key Value

Parse URI query String to Map 做 urlDecode 處理 沒有任何 query String 回傳 Empty Map 確保只處理 key-value 結構的 query String package com.example.util; import lombok.extern.slf4j.Slf4j; import org.apache.http.client.utils.URIBuilder; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.net.URLDecoder; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; /** * Created by jerry on 2017/12/28. * * @author jerry */ @Slf4j public class UriUtil { private UriUtil() { } public static Map splitQuery(final String uri) { Map queryPairs = new LinkedHashMap (); try { final URI uri = new URIBuilder(uri).build(); final String rawQuery = uri.getRawQuery(); log.info("CurrentUrl Query: {}", rawQuery); // 過濾沒有 query string // 還有過濾無法成對 keyValue 的 query, e.g. http://host/path?123 if (Objects.isNull(rawQuery) |...

Spring-boot Thymeleaf Html5 SAXParseException 解析錯誤

thymeleaf 解析 html5 出錯 <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="description" content=""> <meta name="author" content=""> <title>SB Admin - Start Bootstrap Template</title> <!-- Bootstrap core CSS--> <link href="../static/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet"> <!-- Custom fonts for this template--> <link href="../static/vendor/font-awesome/css/font-awesome.min.css" rel="stylesheet" type="text/css"> <!-- Page level plugin CSS--> <link href="../static/vendor/datatables/dataTables.bootstrap4.css" rel="stylesheet"> <!-- Custom styles for this template--> <li...