Switch to a Java-based test generator, which seems to work better.
This commit is contained in:
@@ -1,128 +0,0 @@
|
||||
{-# LANGUAGE ScopedTypeVariables #-}
|
||||
import Control.Monad
|
||||
import Codec.Crypto.DSA.Pure
|
||||
import Control.Concurrent
|
||||
import Crypto.Random.DRBG
|
||||
import Data.Bits
|
||||
import qualified Data.ByteString as BS
|
||||
import qualified Data.ByteString.Char8 as BSC
|
||||
import qualified Data.ByteString.Lazy as BSL
|
||||
import Data.Char
|
||||
import Data.List
|
||||
import qualified Data.Map.Strict as Map
|
||||
import GHC.Integer.GMP.Internals
|
||||
import Numeric
|
||||
import System.IO
|
||||
import System.ProgressBar
|
||||
import System.Random
|
||||
import Debug.Trace
|
||||
|
||||
numThreads :: Int
|
||||
numThreads = 4
|
||||
|
||||
keyIterations :: [ParameterSizes]
|
||||
keyIterations = replicate 500 L1024_N160 ++
|
||||
replicate 500 L2048_N224 ++
|
||||
replicate 200 L2048_N256 ++
|
||||
replicate 100 L3072_N256
|
||||
|
||||
randomByteString :: CryptoRandomGen g => g -> (BS.ByteString, g)
|
||||
randomByteString g =
|
||||
let Right (bs, g') = genBytes 2 g
|
||||
[h,l] = BS.unpack bs
|
||||
x = (fromIntegral h `shiftL` 8) + (fromIntegral l)
|
||||
Right (res, g'') = genBytes (x `mod` 1024) g'
|
||||
in (res, g'')
|
||||
|
||||
randomHash :: CryptoRandomGen g => g -> ((HashFunction, String), g)
|
||||
randomHash g =
|
||||
randomElement g [(SHA1, "1"),
|
||||
(SHA224, "224"),
|
||||
(SHA256, "256"),
|
||||
(SHA384, "384"),
|
||||
(SHA512, "512")]
|
||||
|
||||
showBinary :: BS.ByteString -> String
|
||||
showBinary v = go v
|
||||
where
|
||||
go bstr =
|
||||
case BS.uncons bstr of
|
||||
Nothing ->
|
||||
""
|
||||
Just (x, rest) ->
|
||||
let high = showHex (x `shiftR` 4) ""
|
||||
low = showHex (x .&. 0xF) ""
|
||||
in high ++ low ++ go rest
|
||||
|
||||
dump :: Handle -> [(String,String)] -> IO ()
|
||||
dump hndl = mapM_ writeItem
|
||||
where
|
||||
writeItem (name, value) =
|
||||
do hPutStr hndl name
|
||||
hPutStr hndl ": "
|
||||
hPutStrLn hndl value
|
||||
|
||||
mkProgress x y = Progress (fromIntegral x) (fromIntegral y)
|
||||
|
||||
runSignatureGenerator :: Chan ParameterSizes ->
|
||||
Chan [(String,String)] ->
|
||||
IO ()
|
||||
runSignatureGenerator inputs outputs =
|
||||
do rng0 :: GenBuffered SystemRandom <- newGenIO
|
||||
go Nothing rng0
|
||||
where
|
||||
go Nothing rng0 =
|
||||
do keySize <- readChan inputs
|
||||
go (Just keySize) rng0
|
||||
go (Just keySize) g0 =
|
||||
do let Right (public, private, _, g1) = generateKeyPair g0 keySize
|
||||
let (msg, g2) = randomByteString g1
|
||||
let msg' = BSL.fromStrict msg
|
||||
let ((hash, hashname), g3) = randomHash g2
|
||||
case signMessage' hash kViaRFC6979 g3 private msg' of
|
||||
Left _ ->
|
||||
go (Just keySize) g3
|
||||
Right (sig, g4) ->
|
||||
do unless (verifyMessage' hash public msg' sig) $
|
||||
fail "DSA verification failed internally."
|
||||
let params = private_params private
|
||||
writeChan outputs [("p", showHex (params_p params) ""),
|
||||
("g", showHex (params_g params) ""),
|
||||
("q", showHex (params_q params) ""),
|
||||
("x", showHex (private_x private) ""),
|
||||
("y", showHex (public_y public) ""),
|
||||
("h", hashname),
|
||||
("m", showBinary msg),
|
||||
("r", showHex (sign_r sig) ""),
|
||||
("s", showHex (sign_s sig) "")]
|
||||
go Nothing g4
|
||||
|
||||
writeData :: Chan [(String,String)] -> (Progress -> IO ()) -> Handle -> IO ()
|
||||
writeData outputChan progressBar hndl = go 0
|
||||
where
|
||||
count = fromIntegral (length keyIterations)
|
||||
go x | x == count = return ()
|
||||
| otherwise = do output <- readChan outputChan
|
||||
dump hndl output
|
||||
hFlush hndl
|
||||
progressBar (Progress (x + 1) count)
|
||||
go (x + 1)
|
||||
|
||||
main :: IO ()
|
||||
main =
|
||||
do sizeChan <- newChan
|
||||
outputChan <- newChan
|
||||
--
|
||||
sigthrs <- replicateM numThreads $
|
||||
forkIO $ runSignatureGenerator sizeChan outputChan
|
||||
let bar = autoProgressBar (msg "Generating signature tests") percentage 60
|
||||
writeList2Chan sizeChan keyIterations
|
||||
g1 <- withFile "signature.test" WriteMode (writeData outputChan bar)
|
||||
return ()
|
||||
|
||||
randomElement :: CryptoRandomGen g => g -> [a] -> (a, g)
|
||||
randomElement g xs =
|
||||
let Right (bs, g') = genBytes 1 g
|
||||
x = BS.head bs
|
||||
idx = fromIntegral x `mod` length xs
|
||||
in (xs !! idx, g')
|
||||
195
tests/dsa/Generator.java
Normal file
195
tests/dsa/Generator.java
Normal file
@@ -0,0 +1,195 @@
|
||||
// Just because I always forget Java compilation:
|
||||
// javac Generator.java -cp bcprov-ext-jdk15on-159.jar
|
||||
// java -cp "bcprov-ext-jdk15on-159.jar:." Generator
|
||||
// Also, go here:
|
||||
// https://www.bouncycastle.org/latest_releases.html
|
||||
//
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.lang.InterruptedException;
|
||||
import java.lang.Math;
|
||||
import java.lang.Thread;
|
||||
import java.math.BigInteger;
|
||||
import java.security.SecureRandom;
|
||||
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
|
||||
import org.bouncycastle.crypto.Digest;
|
||||
import org.bouncycastle.crypto.digests.SHA1Digest;
|
||||
import org.bouncycastle.crypto.digests.SHA224Digest;
|
||||
import org.bouncycastle.crypto.digests.SHA256Digest;
|
||||
import org.bouncycastle.crypto.digests.SHA384Digest;
|
||||
import org.bouncycastle.crypto.digests.SHA512Digest;
|
||||
import org.bouncycastle.crypto.generators.DSAKeyPairGenerator;
|
||||
import org.bouncycastle.crypto.generators.DSAParametersGenerator;
|
||||
import org.bouncycastle.crypto.params.DSAKeyGenerationParameters;
|
||||
import org.bouncycastle.crypto.params.DSAParameterGenerationParameters;
|
||||
import org.bouncycastle.crypto.params.DSAParameters;
|
||||
import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
|
||||
import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
|
||||
import org.bouncycastle.crypto.signers.DSASigner;
|
||||
import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
|
||||
|
||||
class Generator {
|
||||
private FileWriter out;
|
||||
private SecureRandom rng;
|
||||
|
||||
final static int NUM_THREADS = 4;
|
||||
|
||||
public Generator(SecureRandom r, FileWriter o) {
|
||||
rng = r;
|
||||
out = o;
|
||||
}
|
||||
|
||||
public void runTests(int lsize, int nsize, int count)
|
||||
throws IOException, InterruptedException
|
||||
{
|
||||
Thread threads[] = new Thread[NUM_THREADS];
|
||||
|
||||
System.out.print("Generating L" + lsize + "N" + nsize + " tests ");
|
||||
for(int i = 0; i < NUM_THREADS; i++) {
|
||||
Runner runner = new Runner(lsize, nsize, count / NUM_THREADS, this);
|
||||
Thread runThread = new Thread(runner);
|
||||
runThread.start();
|
||||
threads[i] = runThread;
|
||||
}
|
||||
for(Thread thread : threads) {
|
||||
thread.join();
|
||||
}
|
||||
System.out.println(" done.");
|
||||
}
|
||||
|
||||
public synchronized void output(DSAParameters params,
|
||||
AsymmetricCipherKeyPair kp,
|
||||
int digestsize,
|
||||
byte[] message,
|
||||
BigInteger[] rs)
|
||||
throws IOException
|
||||
{
|
||||
DSAPublicKeyParameters pub = (DSAPublicKeyParameters)kp.getPublic();
|
||||
DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)kp.getPrivate();
|
||||
out.write("p: " + params.getP().toString(16) + "\n");
|
||||
out.write("q: " + params.getQ().toString(16) + "\n");
|
||||
out.write("g: " + params.getG().toString(16) + "\n");
|
||||
out.write("x: " + priv.getX().toString(16) + "\n");
|
||||
out.write("y: " + pub.getY().toString(16) + "\n");
|
||||
out.write("h: " + digestsize + "\n");
|
||||
out.write("m: " + asHex(message) + "\n");
|
||||
out.write("r: " + rs[0].toString(16) + "\n");
|
||||
out.write("s: " + rs[1].toString(16) + "\n");
|
||||
out.flush();
|
||||
System.out.print(".");
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
private Digest appropriateDigest(int nsize)
|
||||
throws IOException
|
||||
{
|
||||
switch(nsize) {
|
||||
case 1: return new SHA1Digest();
|
||||
case 160: return new SHA1Digest();
|
||||
case 224: return new SHA224Digest();
|
||||
case 256: return new SHA256Digest();
|
||||
case 384: return new SHA384Digest();
|
||||
case 512: return new SHA512Digest();
|
||||
default:
|
||||
throw new IOException("Bad digest size!");
|
||||
}
|
||||
}
|
||||
|
||||
private int randomDigestSize()
|
||||
throws IOException
|
||||
{
|
||||
switch(getRandomChoice(5)) {
|
||||
case 0: return 1;
|
||||
case 1: return 224;
|
||||
case 2: return 256;
|
||||
case 3: return 384;
|
||||
case 4: return 512;
|
||||
default:
|
||||
throw new IOException("The world broke.");
|
||||
}
|
||||
}
|
||||
|
||||
private int getRandomChoice(int modulus) {
|
||||
byte randoms[] = new byte[2];
|
||||
rng.nextBytes(randoms);
|
||||
int random = ((int)randoms[0] << 8) + ((int)randoms[1]);
|
||||
return (Math.abs(random) % modulus);
|
||||
}
|
||||
|
||||
private String asHex(byte[] data) {
|
||||
String result = "";
|
||||
|
||||
for(byte value : data) {
|
||||
result = result + String.format("%02x", value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
throws IOException, InterruptedException
|
||||
{
|
||||
SecureRandom rng = new SecureRandom();
|
||||
FileWriter outfile = new FileWriter("signatures.test", false);
|
||||
Generator gen = new Generator(rng, outfile);
|
||||
|
||||
gen.runTests(1024, 160, 500);
|
||||
gen.runTests(2047, 224, 500);
|
||||
gen.runTests(2048, 256, 250);
|
||||
gen.runTests(3072, 256, 100);
|
||||
}
|
||||
|
||||
private class Runner implements Runnable {
|
||||
private int lsize;
|
||||
private int nsize;
|
||||
private int count;
|
||||
private Generator parent;
|
||||
|
||||
public Runner(int lsize, int nsize, int count, Generator parent)
|
||||
{
|
||||
this.lsize = lsize;
|
||||
this.nsize = nsize;
|
||||
this.count = count;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
for(int i = 0; i < count; i++) {
|
||||
runTest();
|
||||
}
|
||||
}
|
||||
|
||||
private void runTest()
|
||||
{
|
||||
try {
|
||||
DSAParameterGenerationParameters genparams =
|
||||
new DSAParameterGenerationParameters(lsize, nsize, 80, rng);
|
||||
DSAParametersGenerator gen =
|
||||
new DSAParametersGenerator(parent.appropriateDigest(nsize));
|
||||
gen.init(genparams);
|
||||
DSAParameters params = gen.generateParameters();
|
||||
DSAKeyGenerationParameters dsakeygenparams =
|
||||
new DSAKeyGenerationParameters(rng, params);
|
||||
DSAKeyPairGenerator keygen = new DSAKeyPairGenerator();
|
||||
keygen.init(dsakeygenparams);
|
||||
AsymmetricCipherKeyPair kp = keygen.generateKeyPair();
|
||||
DSAPublicKeyParameters pub = (DSAPublicKeyParameters)kp.getPublic();
|
||||
DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)kp.getPrivate();
|
||||
int msgsize = getRandomChoice(1024);
|
||||
byte message[] = new byte[msgsize];
|
||||
rng.nextBytes(message);
|
||||
int digestsize = randomDigestSize();
|
||||
Digest msgdigest = appropriateDigest(digestsize);
|
||||
HMacDSAKCalculator kgen = new HMacDSAKCalculator(msgdigest);
|
||||
DSASigner signer = new DSASigner(kgen);
|
||||
signer.init(true, priv);
|
||||
BigInteger rs[] = signer.generateSignature(message);
|
||||
parent.output(params, kp, digestsize, message, rs);
|
||||
} catch(IOException exc) {
|
||||
System.out.println("EXCEPTION!");
|
||||
run();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user