init: v1.0.0

This commit is contained in:
yaole
2026-05-27 23:03:00 +08:00
commit 8d97f750eb
466 changed files with 80067 additions and 0 deletions
+81
View File
@@ -0,0 +1,81 @@
package main
import (
"crypto/rand"
"fmt"
"math/big"
"sync"
"xdx.jelly/xgcl/sm/sm2"
"xdx.jelly/xgcl/sm/sm2/ec256"
)
func assertEqual(a, b interface{}) {
switch a.(type) {
case *big.Int:
if a.(*big.Int).Cmp(b.(*big.Int)) != 0 {
panic("assert equal failed")
}
case []uint64:
aa := a.([]uint64)
bb := b.([]uint64)
for i := 0; i < len(aa); i++ {
if aa[i] != bb[i] {
panic("assert equal failed")
}
}
default:
panic("unknown type")
}
}
var param = sm2.Curve().Params()
var c256 = sm2.Curve().(ec256.SM2CurveParam)
func testScalarMult() {
for i := 0; i < 1000; i++ {
k, _ := rand.Int(rand.Reader, param.N)
x1, y1 := param.ScalarMult(param.Gx, param.Gy, k.Bytes())
x2, y2 := c256.CurveParams.ScalarMult(param.Gx, param.Gy, k.Bytes())
assertEqual(x1, x2)
assertEqual(y1, y2)
}
}
func testScalarBaseMult() {
for i := 0; i < 1000; i++ {
k, _ := rand.Int(rand.Reader, param.N)
x1, y1 := param.ScalarBaseMult(k.Bytes())
x2, y2 := c256.CurveParams.ScalarBaseMult(k.Bytes())
assertEqual(x1, x2)
assertEqual(y1, y2)
}
}
func main() {
n := 10000000
var wg sync.WaitGroup
wg.Add(2)
go func() {
for i := 0; i < n; i++ {
if i%10 == 0 {
fmt.Printf("testScalarBaseMult - %d\n", 1000*i)
}
testScalarBaseMult()
}
wg.Done()
}()
go func() {
for i := 0; i < n; i++ {
if i%10 == 0 {
fmt.Printf("testScalarMult - %d\n", 1000*i)
}
testScalarMult()
}
wg.Done()
}()
wg.Wait()
}
File diff suppressed because it is too large Load Diff
Binary file not shown.
+25
View File
@@ -0,0 +1,25 @@
OS=$(shell uname)
ifeq (${OS}, Linux)
LIB=libgcl.so
endif
ifeq (${OS}, Darwin)
LIB=libgcl.dylib
endif
TEST=test
All: lib test
lib: staticlib gcl.c
gcc -fPIC -shared -o ${LIB} -L. gcl.c -lgcl_go
test: lib main.c
gcc -o ${TEST} main.c -L. -lgcl -lpthread
staticlib: lib.go
go build -buildmode=c-archive -o libgcl_go.a lib.go
android:
GOOS=android GOARCH=arm64 go build -buildmode=c-archive -o libgcl_go.a lib.go
clean:
rm -f libgcl_go.a *.dylib *.so ${LIB} ${TEST}
+35
View File
@@ -0,0 +1,35 @@
# 简介
输出gcl中的功能为C库
步骤:
- lib.go中编写要输出的函数:
```
//export Sm3
func Sm3(in []byte, out []byte) {
d := sm3.Sum(in)
copy(out, d[:])
}
```
- 生成go导出的C库(c-archive)
```
go build -buildmode=c-archive -o libgcl_go.a lib.go
```
- lib.c中编写C包装代码
```
int sm3(void *data, int dataLen, void *digest){
// input check, omit
GoSlice in = {
data, dataLen, dataLen
};
GoSlice out = {
digest, 32, 32
};
Sm3(in,out);
return 0;
}
```
- gcc编译gcl.c为动态库
```
gcc -shared -o libgcl.dylib -L. -lgcl_go gcl.c
```
+19
View File
@@ -0,0 +1,19 @@
package main
import "C"
import (
"fmt"
"xdx.jelly/xgcl/sm/sm3"
)
//export Sm3
func Sm3(in []byte, out []byte) {
d := sm3.Sum(in)
copy(out, d[:])
}
func main() {
fmt.Println("...")
}
+12
View File
@@ -0,0 +1,12 @@
#include "libgcl_go.h"
int sm3(void *data, int dataLen, void *digest){
GoSlice in = {
data, dataLen, dataLen
};
GoSlice out = {
digest, 32, 32
};
Sm3(in,out);
return 0;
}
+15
View File
@@ -0,0 +1,15 @@
#ifndef LIBGCL_H_
#define LIBGCL_H_
#ifdef __cplusplus
extern "C" {
#endif
int sm3(void *data, int dataLen, void *digest);
#ifdef __cplusplus
}
#endif
#endif // LIBGCL_H_
+81
View File
@@ -0,0 +1,81 @@
/* Code generated by cmd/cgo; DO NOT EDIT. */
/* package command-line-arguments */
#line 1 "cgo-builtin-export-prolog"
#include <stddef.h>
#ifndef GO_CGO_EXPORT_PROLOGUE_H
#define GO_CGO_EXPORT_PROLOGUE_H
#ifndef GO_CGO_GOSTRING_TYPEDEF
typedef struct { const char *p; ptrdiff_t n; } _GoString_;
#endif
#endif
/* Start of preamble from import "C" comments. */
/* End of preamble from import "C" comments. */
/* Start of boilerplate cgo prologue. */
#line 1 "cgo-gcc-export-header-prolog"
#ifndef GO_CGO_PROLOGUE_H
#define GO_CGO_PROLOGUE_H
typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt64 GoInt;
typedef GoUint64 GoUint;
typedef size_t GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
#ifdef _MSC_VER
#include <complex.h>
typedef _Fcomplex GoComplex64;
typedef _Dcomplex GoComplex128;
#else
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;
#endif
/*
static assertion to make sure the file is being used on architecture
at least with matching size of GoInt.
*/
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1];
#ifndef GO_CGO_GOSTRING_TYPEDEF
typedef _GoString_ GoString;
#endif
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
#endif
/* End of boilerplate cgo prologue. */
#ifdef __cplusplus
extern "C" {
#endif
extern void Sm3(GoSlice in, GoSlice out);
#ifdef __cplusplus
}
#endif
+24
View File
@@ -0,0 +1,24 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include "gcl.h"
int main() {
int msgLen = 10*1024*1024;
char *msg = malloc(msgLen);
char digest[32];
clock_t start, end;
int count = 100;
start = clock();
for (int i = 0; i < count; i++) {
sm3(msg, msgLen, &digest);
}
end = clock();
printf("sm3: %.1fMBps\n", (double)count * msgLen/1024/1024/ ((double)(end - start) / CLOCKS_PER_SEC));
free(msg);
return 0;
}
+239
View File
@@ -0,0 +1,239 @@
package main
import (
"crypto/rand"
"fmt"
"math/big"
"os"
"runtime"
"strconv"
"sync"
"time"
"xdx.jelly/xgcl/gmath"
"xdx.jelly/xgcl/grand"
"xdx.jelly/xgcl/he/paillier"
"xdx.jelly/xgcl/sm/sm2"
"xdx.jelly/xgcl/sm/sm3"
"xdx.jelly/xgcl/tpc/sm2/sm2m"
"xdx.jelly/xgcl/tpc/sm2/sm2m/outsource"
)
type timer struct {
totalTime float64
last time.Time
isStoped bool
}
func (t *timer) ResetTimer() {
t.last = time.Now()
t.totalTime = 0
t.isStoped = false
}
func (t *timer) StopTimer() {
if t.isStoped {
return
}
t.totalTime += time.Since(t.last).Seconds()
t.isStoped = true
}
func (t *timer) StartTimer() {
if !t.isStoped {
return
}
t.last = time.Now()
t.isStoped = false
}
func (t *timer) Seconds() float64 {
t.StopTimer()
return t.totalTime
}
func testPaillierHomomorphicScalarMul() {
_, pk, _ := paillier.GenerateKey(2048, grand.Reader)
limit := big.NewInt(1)
limit.Lsh(limit, 256)
m, _ := rand.Int(grand.Reader, limit)
c, _ := paillier.Encrypt(m, pk, grand.Reader)
k, _ := rand.Int(grand.Reader, limit)
var b timer
b.ResetTimer()
times := 1000
for i := 0; i < times; i++ {
c.HomomorphicScalarMul(c, k, pk)
}
b.StopTimer()
fmt.Printf("HomomorphicScalarMul(single): %.2f per second\n", float64(times)/b.Seconds())
}
func testPaillierHomomorphicScalarAdd() {
_, pk, _ := paillier.GenerateKey(2048, grand.Reader)
m1, _ := rand.Int(grand.Reader, pk.N)
c1, _ := pk.Encrypt(m1, grand.Reader)
m2, _ := rand.Int(grand.Reader, pk.N)
c2, _ := pk.Encrypt(m2, grand.Reader)
var c paillier.Cipher
times := 1000
var b timer
b.ResetTimer()
for i := 0; i < times; i++ {
c.HomomorphicAdd(c1, c2, pk)
}
b.StopTimer()
fmt.Printf("HomomorphicAdd(single): %.2f per second\n", float64(times)/b.Seconds())
}
func testPaillierEnc() {
_, pk, _ := paillier.GenerateKey(2048, grand.Reader)
m, _ := rand.Int(grand.Reader, pk.N)
times := 1000
var b timer
b.ResetTimer()
for i := 0; i < times; i++ {
pk.Encrypt(m, grand.Reader)
}
b.StopTimer()
fmt.Printf("Encrypt(single): %.2f per second\n", float64(times)/b.Seconds())
}
func testOS(N int) float64 {
// O、客户端生成paillier密钥
salt := grand.GetRandom(16)
paiPrivKey, _ := paillier.GenerateKeyFromPassword(2048, []byte("password123"), salt, 1024)
paiPubKey := paiPrivKey.Public()
// 一、密钥生成
// 1)客户端第一步, a1, a2 发外包服务器
clientKeyGen := &outsource.ClientKeyGenerator{}
a1, a2, _ := clientKeyGen.Step1(paiPubKey, grand.Reader)
// 2) 外包服务器第一步
// 保存encryptedClientKey1encryptedClientKey2,
// 把 P 发客户端
// encryptedClientKey1 -签名用
// encryptedClientKey2 -解密加密密钥保护结构用
osKenGen := &outsource.OSKeyGenerator{}
encryptedClientKey1, _, P, _ := osKenGen.Step1(a1, a2, paiPubKey, grand.Reader)
// 3) 客户端第二步
// clientTempKey发协同签名服务端
clientTempKey, _ := clientKeyGen.Step2(P)
// 4)协同签名服务器
// serverTempKey 发客户端,保存serverKey-服务端密钥分量
serverKey, serverTempKey, publicKey, _ := sm2m.ServerGenSignKey(clientTempKey, grand.GetRandom(32))
// 5)客户端第三步
// 把(serverTempKey,S)发送给外包服务器
S, _ := clientKeyGen.Step3(serverTempKey)
// 6)外包服务器第二步
// 把T osPublicKey发给客户端。保存osPublicKey为用户签名公钥
T, osPublicKey, _ := osKenGen.Step2(serverTempKey, S)
// 7)客户端第四步
// clientPublicKey, 客户端生成的公钥,如果没有返错,则应与ocPublicKey一致。
clientPublicKey, _ := clientKeyGen.Step4(T)
clientPublicKey.Equals(osPublicKey)
e := grand.GetRandom(32)
var b timer
// N := 1000
// 签名
b.ResetTimer()
for i := 0; i < N; i++ {
// 1)客户端发起请求
// 2)外包方计算
b.StartTimer()
outsourcintCtx := new(outsource.OSSignContext)
PPrime, _ := outsourcintCtx.Step1(grand.Reader) // P'
// outsourcintCtx把PPrime发给客户端,保存outsourcintCtx.Marshal()
// 3) 客户端组合数据data = (e,p)=e||px||py并发送给协同服务端
b.StopTimer()
data := make([]byte, sm3.Size+2*sm2.ByteSize())
pos := copy(data, e)
pos += copy(data[pos:], gmath.BigIntToNByte(PPrime.X, sm2.ByteSize()))
copy(data[pos:], gmath.BigIntToNByte(PPrime.Y, sm2.ByteSize()))
// 4) 协同服务端计算,发回data
b.StartTimer()
data, _ = sm2m.ServerSign(serverKey, data, grand.Reader)
// 5) 客户端解析data = r || s1 || s2, 把s1, s2发给外包服务器。
b.StopTimer()
r := new(big.Int)
r.SetBytes(data[:sm2.ByteSize()])
s1 := new(big.Int).SetBytes(data[sm2.ByteSize() : 2*sm2.ByteSize()])
s2 := new(big.Int).SetBytes(data[2*sm2.ByteSize():])
// 6) 外包服务器解析data并计算c,把c发送给客户端
b.StartTimer()
c, _ := outsourcintCtx.Step2(s1, s2, encryptedClientKey1, paiPubKey)
// 7) 客户端计算签名值
b.StopTimer()
s, _ := paillier.Decrypt(c, paiPrivKey)
s.Sub(s, r)
s.Mod(s, sm2.OrderN())
sig := &sm2.Signature{
R: r,
S: s,
}
// 8) 客户端验证签名
sm2.Verify(e, publicKey, sig)
}
return b.Seconds()
// fmt.Printf("used time: %v\n", b.Seconds())
// fmt.Printf("Outsource sign: %.2f per second\n", float64(N)/b.Seconds())
}
func multiTestOS(threads int) {
N := 100
times := make([]float64, threads)
var wg sync.WaitGroup
for i := 0; i < threads; i++ {
wg.Add(1)
go func(i int) {
times[i] = testOS(N)
wg.Done()
}(i)
}
wg.Wait()
avg := 0.0
for _, t := range times {
avg += t
}
avg /= float64(threads)
fmt.Printf("Outsource sign: %.2f per second\n", float64(N*threads)/avg)
}
func main() {
testPaillierEnc()
testPaillierHomomorphicScalarAdd()
testPaillierHomomorphicScalarMul()
var threads int
if len(os.Args) < 2 {
threads = runtime.NumCPU()
} else {
threads, _ = strconv.Atoi(os.Args[1])
}
fmt.Println("Cores:", threads)
multiTestOS(threads)
}
+219
View File
@@ -0,0 +1,219 @@
//go:build ignore
// +build ignore
package main
import (
"flag"
"fmt"
"io/ioutil"
"math"
"os"
"path"
"runtime"
"sync"
"xdx.jelly/xgcl/grand/statistics"
)
var suit = []struct {
name string
fn func([]byte) bool
}{
{
name: "单比特频数检测 ",
fn: statistics.Frequency,
},
{
name: "块内频数检测 ",
fn: statistics.BlockFrequency,
},
{
name: "扑克检测, m=4 ",
fn: statistics.Poker4,
},
{
name: "扑克检测, m=8 ",
fn: statistics.Poker8,
},
{
name: "重叠子序列检测, m=2",
fn: statistics.Serial2,
},
{
name: "重叠子序列检测, m=5",
fn: statistics.Serial5,
},
{
name: "游程总数检测 ",
fn: statistics.Runs,
},
{
name: "游程分布检测 ",
fn: statistics.RunsDistribution,
},
{
name: "二元推导检测, k=3 ",
fn: statistics.BinaryDerivative3,
},
{
name: "二元推导检测, k=7 ",
fn: statistics.BinaryDerivative7,
},
{
name: "自相关检测, d=1 ",
fn: statistics.Autocorrelation1,
},
{
name: "自相关检测, d=2 ",
fn: statistics.Autocorrelation2,
},
{
name: "自相关检测, d=8 ",
fn: statistics.Autocorrelation8,
},
{
name: "自相关检测, d=16 ",
fn: statistics.Autocorrelation16,
},
{
name: "矩阵秩检测 ",
fn: statistics.Rank,
},
{
name: "累加和检测 ",
fn: statistics.CumulativeSums,
},
{
name: "近似熵检测 ",
fn: statistics.ApproximateEntropy,
},
{
name: "线性复杂度检测 ",
fn: statistics.LinearComplexity,
},
{
name: "Maurer通用统计检测 ",
fn: statistics.Universal,
},
{
name: "离散傅立叶检测 ",
fn: statistics.DiscreteFourierTransform,
},
}
type payload struct {
e []byte
fn func([]byte) bool
}
func worker(in chan *payload, out chan bool, done chan struct{}) {
for {
select {
case p := <-in:
out <- p.fn(p.e) // fn may panic
case <-done:
return
}
}
}
func main() {
dataDir := flag.String("d", "./data", "The directory of random data, default is \"./data\"")
flag.Parse()
fmt.Println("=======================================================")
fmt.Println(" 测试文件夹:", *dataDir)
epsilons := make([][]byte, 0)
fs, err := ioutil.ReadDir(*dataDir)
if err != nil {
fmt.Println("文件夹读取错误: ", err)
return
}
for _, file := range fs {
if !file.IsDir() {
epsilon, err := readFile(path.Join(*dataDir, file.Name()))
if err != nil {
fmt.Println("文件读取错误: ", err)
return
}
epsilons = append(epsilons, epsilon)
}
}
fmt.Printf(" 共有随机数文件%d个,每个文件%d比特\n", len(epsilons), len(epsilons[0]))
bound := lowerBound(len(epsilons))
fmt.Printf(" 每组检测通过的样本数必须不小于: %d\n", bound)
fmt.Println("=======================================================")
threads := runtime.NumCPU()
in := make(chan *payload, threads)
out := make(chan bool, threads)
done := make(chan struct{})
for i := 0; i < threads; i++ {
go worker(in, out, done)
}
// for {
for _, t := range suit {
// for _, t := range suit[len(suit)-1:] {
sum := 0
var wg sync.WaitGroup
wg.Add(len(epsilons))
go func() {
for _, e := range epsilons {
in <- &payload{
e: e,
fn: t.fn,
}
}
}()
go func() {
for i := 0; i < len(epsilons); i++ {
b := <-out
if b {
sum += 1
}
wg.Done()
}
}()
wg.Wait()
if sum < bound {
fmt.Printf("[x] %s 【失败】: %d / %d\n", t.name, sum, len(epsilons))
} else {
fmt.Printf("[o] %s 【通过】: %d / %d\n", t.name, sum, len(epsilons))
}
}
// }
}
// readFile read from fileName and convert each bit to byte
func readFile(fileName string) ([]byte, error) {
content, err := os.ReadFile(fileName)
if err != nil {
return nil, err
}
bits := make([]byte, 0, len(content)*8)
for _, c := range content {
bits = append(bits, (c>>7)&1)
bits = append(bits, (c>>6)&1)
bits = append(bits, (c>>5)&1)
bits = append(bits, (c>>4)&1)
bits = append(bits, (c>>3)&1)
bits = append(bits, (c>>2)&1)
bits = append(bits, (c>>1)&1)
bits = append(bits, (c>>0)&1)
}
return bits, nil
}
const alpha float64 = 0.01
func lowerBound(samples int) int {
return int(math.Ceil((1 - alpha - 3*math.Sqrt((alpha*(1-alpha))/float64(samples))) * float64(samples)))
}
+45
View File
@@ -0,0 +1,45 @@
//go:build ignore
// +build ignore
package main
import (
"fmt"
"testing"
)
func TestLowerBound(t *testing.T) {
fmt.Println(lowerBound(1024))
}
func TestP(t *testing.T) {
tests := []string{
"Frequency",
"BlockFrequency",
"CumulativeSums",
"Runs",
"LongestRunOfOnes",
"Rank",
"DiscreteFourierTransform",
"Universal",
"ApproximateEntropy",
"LinearComplexity",
"Serial",
"Poker",
"Autocorrelation",
"BinaryDerivative",
"RunsDistribution",
}
for _, t := range tests {
fmt.Printf(`
sum = 0
for _, e := range epsilons {
if statistics.%s(e) {
sum += 1
}
}
if sum < bound {
fmt.Printf("%s Test Failed: \d/\d\n", sum, len(epsilons))
}
`, t, t)
}
}
+374
View File
@@ -0,0 +1,374 @@
#include "RandomTest.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
// 记录有过失败的数据
//
int fileNo = 1;
int testNo = 1;
int failed[TEST_NUM+1][SAMPLE_NUM+1] = {0};
int main(int argc, char * argv[])
{
unsigned char *epsilon;
int pass[TEST_NUM + 1];
if ( (epsilon = (BitSequence *) calloc(SAMPLE_LEN, sizeof(BitSequence))) == NULL ) {
printf("BITSTREAM DEFINITION: Insufficient memory available.\n");
return -1;
}
int ret = 0;
int testVector[30] = {0};
FILE *fp;
char FileName[128] = {0};
double passmin = 0.0;
int loop = 1, passnum = 0;
bzero(pass, sizeof(pass));
printf("\n\n I N P U T B A S E D I R\n");
printf(" Make sure the test datas are ./data/Random_[x].bin\n");
printf(" Press enter to continue.");
getchar();
while (loop)
{
ChooseItems(&testVector[0]);
/* testVector[0] = 19;*/
if (testVector[0] == 0)
break;
// 一键测试
if (testVector[0] == 80)
{
passnum = 0;
fprintf(stdout,">> one key test start.");
for (int k=1; k<=TEST_NUM ; ++k )
{
testNo = k;
printf("\n");
pass[k] = 0;
// for (int i=1; i<=SAMPLE_NUM; i++)
for (int i = 0; i < SAMPLE_NUM;)
{
fileNo = i;
sprintf(FileName, "./data/Random_%d.txt", i+1);
if((fp = fopen(FileName,"rb")),!fp)
{
printf("\n打开文件失败\n");
ret = -1;
goto CLR;
}
// read file and test
readHexDigitsInBinaryFormat(fp,k, epsilon, pass);
// close file
if (EOF == fclose(fp))
{
printf("\n关闭文件失败\n");
ret = -1;
goto CLR;
}
i++;
if (0 == i%200)
{
printf("\n option %d: %d / %d pass.\n",k,pass[k],i);
}
if ( SAMPLE_NUM == i )
{
passmin = SAMPLE_NUM * (1 - ALPHA - 3 * sqrt( ALPHA*(1-ALPHA)/SAMPLE_NUM));
if (pass[k] >= passmin)
{
passnum++;
fprintf(stdout,"\n[O] option %d pass the test, result is %d / %d .", k, pass[k], SAMPLE_NUM);
}
else
{
fprintf(stdout,"\n[X] option %d fail the test, result is %d / %d .", k, pass[k], SAMPLE_NUM);
}
}
}
}
if (passnum == sizeof(pass)/sizeof(pass[0]))
{
fprintf(stdout,"\n\n>> one key test end, all options passed.");
}
else
{
fprintf(stdout,"\n\n>> one key test end, some one failed.");
}
}
else
{
printf("\n");
pass[testVector[0]] = 0;
testNo = testVector[0];
for (int i=0; i<SAMPLE_NUM;)
{
fileNo = i;
sprintf(FileName, "./data/random%03d.bin", i);
// open file
if((fp = fopen(FileName,"rb")),!fp)
{
printf("\n打开文件失败\n");
ret = -1;
goto CLR;
}
// read file and test
readHexDigitsInBinaryFormat(fp,testVector[0], epsilon, pass);
// close file
if (EOF == fclose(fp))
{
printf("\n关闭文件失败\n");
ret = -1;
goto CLR;
}
i++;
if (0 == i%200)
{
printf("\n option %d: %d / %d pass.\n",testVector[0],pass[testVector[0]],i);
}
if ( SAMPLE_NUM == i )
{
passmin = SAMPLE_NUM * (1 - ALPHA - 3 * sqrt( ALPHA*(1-ALPHA)/SAMPLE_NUM));
if (pass[testVector[0]] >= passmin)
{
fprintf(stdout,"\n[O] option %d pass the test, result is %d / %d .", testVector[0], pass[testVector[0]], SAMPLE_NUM);
}
else
{
fprintf(stdout,"\n[X] option %d fail the test, result is %d / %d .", testVector[0], pass[testVector[0]], SAMPLE_NUM);
}
}
}
}
printf("\n\n F A I L E D T E S T D E T A I L S\n");
int filePassResult[SAMPLE_NUM + 1] = {0};
for (int j = 1; j < SAMPLE_NUM+1; j++){
for (int i = 1; i <= TEST_NUM; i++){
if (failed[i][j]){
printf(" random%d.bin failed test %d\n", j, i);
filePassResult[j] = 1;
}
}
}
printf("\n\n F A I L E D T E S T S U M A R R Y\n");
printf(" The following files are failed in some test:\n");
for (int j = 1; j < SAMPLE_NUM+1; j++){
if (filePassResult[j]){
printf(" random%i.bin\n", j);
}
}
if (testVector[0] == 80){
break;
}else{
printf("\n\nPress any key to go on!\n");
getchar();
}
}
CLR:
free(epsilon);
return ret;
}
void ChooseItems(int *pChoice)
{
printf("\n\n R A N D O M N E S S T E S T S\n");
printf(" _________________________________\n\n");
printf(" [01] monobit frequency test (单比特频数检测)\n");
printf(" [02] frequency test with a block (块内频数检测)\n");
printf(" [03] poker test (扑克检测, m=4)\n");
printf(" [04] serial test (重叠子序列检测, m=2)\n");
printf(" [05] runs test (游程总数检测)\n");
printf(" [06] runs distribution test (游程分布检测)\n");
printf(" [07] test for the longest run of ones in a block\n");
printf(" (块内最大“1”游程检测)\n");
printf(" [08] binary derivative test (二元推导检测, k=3)\n");
printf(" [09] autocorrelation test (自相关检测, d=1)\n");
printf(" [10] binary matrix rank test (矩阵秩检测)\n");
printf(" [11] cumulative test (累加和检测)\n");
printf(" [12] approximate entropy test (近似熵检测)\n");
printf(" [13] linear complexity test (线性复杂度检测)\n");
printf(" [14] Maurer's \"Universal Test\" (Maurer通用统计检测)\n");
printf(" [15] discrete fourier transform test (离散傅立叶检测)\n\n");
printf(" [16] poker test (扑克检测, m=8)\n");
printf(" [17] serial test (重叠子序列检测, m=5)\n");
printf(" [18] binary derivative test (二元推导检测, k=7)\n");
printf(" [19] autocorrelation test (自相关检测, d=2)\n");
printf(" [20] autocorrelation test (自相关检测, d=8)\n");
printf(" [21] autocorrelation test (自相关检测, d=16)\n\n");
printf(" [80] One Key Test All\n");
printf(" [00] Quit\n\n");
printf("> Enter Choice: ");
scanf("%d", pChoice);
printf("\n");
}
void Test_Suite(unsigned char *epsilon, int n, int Choice, int *pass)
{
if (TEST_FREQUENCY == Choice)
pass[TEST_FREQUENCY] += Frequency(epsilon, n);
if (TEST_BLOCK_FREQUENCY == Choice)
pass[TEST_BLOCK_FREQUENCY] += BlockFrequency(epsilon, n);
if ( TEST_CUSUM == Choice )
pass[TEST_CUSUM] += CumulativeSums(epsilon, n);
if ( TEST_RUNS == Choice )
pass[TEST_RUNS] += Runs(epsilon, n);
if ( TEST_LONGEST_RUN == Choice)
pass[TEST_LONGEST_RUN] += LongestRunOfOnes(epsilon, n);
if ( TEST_RANK == Choice)
pass[TEST_RANK] += Rank(epsilon, n);
if ( TEST_FFT == Choice)
pass[TEST_FFT] += DiscreteFourierTransform(epsilon, n);
if ( TEST_UNIVERSAL == Choice)
pass[TEST_UNIVERSAL] += Universal(epsilon, n);
if ( TEST_APEN == Choice)
pass[TEST_APEN] += ApproximateEntropy(epsilon, n);
if ( TEST_SERIAL2 == Choice)
pass[TEST_SERIAL2] += Serial(epsilon, n, 2);
if ( TEST_LINEARCOMPLEXITY == Choice)
pass[TEST_LINEARCOMPLEXITY] += LinearComplexity(epsilon, n);
if (TEST_POKER4 == Choice)
pass[TEST_POKER4] += Poker(epsilon, n, 4);
if (TEST_AUTOCORRELATION1 == Choice)
pass[TEST_AUTOCORRELATION1] += Autocorrelation(epsilon, n, 1);
if (TEST_BINARYDERIVATION3 == Choice)
pass[TEST_BINARYDERIVATION3] += BinaryDerivative(epsilon, n, 3);
if (TEST_RUNSDISTRIBUTION == Choice)
pass[TEST_RUNSDISTRIBUTION] += RunsDistribution(epsilon, n);
if (TEST_POKER8 == Choice)
pass[TEST_POKER8] += Poker(epsilon, n, 8);
if (TEST_SERIAL5 == Choice)
pass[TEST_SERIAL5] += Serial(epsilon, n, 5);
if (TEST_BINARYDERIVATION7 == Choice)
pass[TEST_BINARYDERIVATION7] += BinaryDerivative(epsilon, n, 7);
if (TEST_AUTOCORRELATION2 == Choice)
pass[TEST_AUTOCORRELATION2] += Autocorrelation(epsilon, n, 2);
if (TEST_AUTOCORRELATION8 == Choice)
pass[TEST_AUTOCORRELATION8] += Autocorrelation(epsilon, n, 8);
if (TEST_AUTOCORRELATION16 == Choice)
pass[TEST_AUTOCORRELATION16] += Autocorrelation(epsilon, n, 16);
}
void readHexDigitsInBinaryFormat(FILE *fp,int choose, unsigned char *epsilon, int *pass)
{
int i, done, num_0s, num_1s, bitsRead;
BYTE buffer[4];
// printf(" Statistical Testing In Progress.........\n\n");
for ( i=0; i<1; i++ ) {
num_0s = 0;
num_1s = 0;
bitsRead = 0;
done = 0;
do {
if ( fread(buffer, sizeof(unsigned char), 4, fp) != 4 ) {
printf("READ ERROR: Insufficient data in file.\n");
free(epsilon);
return;
}
done = convertToBits(epsilon,buffer, 32,SAMPLE_LEN, &num_0s, &num_1s, &bitsRead);
} while ( !done );
// fprintf(freqfp, "\t\tBITSREAD = %d 0s = %d 1s = %d\n", bitsRead, num_0s, num_1s);
Test_Suite(epsilon, SAMPLE_LEN, choose, pass);
}
}
int convertToBits(unsigned char *epsilon, BYTE *x, int xBitLength, int bitsNeeded, int *num_0s, int *num_1s, int *bitsRead)
{
int i, j, count, bit;
BYTE mask;
int zeros, ones;
count = 0;
zeros = ones = 0;
for ( i=0; i<(xBitLength+7)/8; i++ ) {
mask = 0x80;
for ( j=0; j<8; j++ ) {
if ( *(x+i) & mask ) {
bit = 1;
(*num_1s)++;
ones++;
}
else {
bit = 0;
(*num_0s)++;
zeros++;
}
mask >>= 1;
epsilon[*bitsRead] = bit;
(*bitsRead)++;
if ( *bitsRead == bitsNeeded )
return 1;
if ( ++count == xBitLength )
return 0;
}
}
return 0;
}
+71
View File
@@ -0,0 +1,71 @@
package main
import (
"crypto"
"crypto/sha256"
"fmt"
"os"
"runtime"
"strconv"
"sync"
"time"
"xdx.jelly/xgcl/rsa"
)
var wg sync.WaitGroup
func sign(sk *rsa.PrivateKey, digestData []byte, work, done chan struct{}) {
for {
select {
case <-work:
_, _ = rsa.PKCS1v15{}.Sign(sk, crypto.SHA256, digestData)
case <-done:
wg.Done()
return
}
}
}
func main() {
msg := []byte("message")
digestData := sha256.Sum256(msg)
sk, _, _ := rsa.PKCS1v15{}.GenerateKeyPairRSA(2048)
threads := runtime.NumCPU()
loops := 1000
work := make(chan struct{})
done := make(chan struct{})
if len(os.Args) >= 2 {
threads, _ = strconv.Atoi(os.Args[1])
}
if len(os.Args) >= 3 {
loops, _ = strconv.Atoi(os.Args[2])
}
for i := 0; i < threads; i++ {
wg.Add(1)
go sign(sk, digestData[:], work, done)
}
for i := 0; i < 1000; i++ {
// warm up
work <- struct{}{}
}
start := time.Now()
for i := 0; i < threads*loops; i++ {
work <- struct{}{}
}
close(done)
wg.Wait()
elapsed := time.Since(start)
cnt := threads * loops
fmt.Printf("Sign %d times on %d cores\n", threads*loops, threads)
fmt.Printf("Used time: %d ms, %d pcs/s\n", elapsed.Milliseconds(), int(float64(cnt)/float64(elapsed.Milliseconds())*1000))
}
+26
View File
@@ -0,0 +1,26 @@
package main_test
import (
"fmt"
"math/big"
"testing"
"time"
)
func TestPow(t *testing.T) {
n, _ := big.NewInt(1).SetString("151787717184422252307365020658866150659139813606887864663574443176328014948429913407344055128026662986925949147541666619511526142491196760869802510776788353419093645990851372578901256051814507665042918937343846064086867942964225457691185973174205523727877484153730596121423900155549117133518141928295347285789", 10)
m, _ := big.NewInt(1).SetString("15178771718442225230736502065886615065913981360688786466357444317632801494842991340734405512802666298692594914754166661951152614249119676086980251077678835341909364599085137257890125605181450766504291893734384606408686794296422545769118597317420552372787748415373059612142390015554911713351814192829534728578", 10)
d, _ := big.NewInt(1).SetString("141787717184422252307365020658866150659139813606887864663574443176328014948429913407344055128026662986925949147541666619511526142491196760869802510776788353419093645990851372578901256051814507665042918937343846064086867942964225457691185973174205523727877484153730596121423900155549117133518141928295347285789", 10)
c := big.NewInt(1)
cnt := 10000
start := time.Now()
for i := 0; i < cnt; i++ {
c.Exp(m, d, n)
}
elapsed := time.Since(start)
fmt.Printf("Sign %d times\n", cnt)
fmt.Printf("Used time: %d ms, %d pcs/s\n", elapsed.Milliseconds(), int(float64(cnt)/float64(elapsed.Seconds())))
}