csidh: test vectors
This commit is contained in:
джерело
7227d565a9
коміт
16f0f5b588
@ -33,7 +33,7 @@ $(BUILD_DIR)/%.o: %.s
|
|||||||
case $@ in */*) f=$@; mkdir -p $${f%/*} ;; esac
|
case $@ in */*) f=$@; mkdir -p $${f%/*} ;; esac
|
||||||
$(CC) -c -o $@ $< $(CFLAGS)
|
$(CC) -c -o $@ $< $(CFLAGS)
|
||||||
|
|
||||||
all: libcsidh torturer
|
all: libcsidh torturer vector-creator
|
||||||
|
|
||||||
libcsidh: $(CODE_OBJ)
|
libcsidh: $(CODE_OBJ)
|
||||||
mkdir -p $(PRJ_DIR)/$(BIN_DIR)
|
mkdir -p $(PRJ_DIR)/$(BIN_DIR)
|
||||||
@ -48,6 +48,9 @@ clean:
|
|||||||
torturer: $(BUILD_DIR)/.ok
|
torturer: $(BUILD_DIR)/.ok
|
||||||
GOPATH=$(GOPATH_LOCAL) $(GO) install $(IMPORT_PATH)/cmd/$@
|
GOPATH=$(GOPATH_LOCAL) $(GO) install $(IMPORT_PATH)/cmd/$@
|
||||||
|
|
||||||
|
vector-creator: $(BUILD_DIR)/.ok
|
||||||
|
GOPATH=$(GOPATH_LOCAL) $(GO) install $(IMPORT_PATH)/cmd/$@
|
||||||
|
|
||||||
$(BUILD_DIR)/.ok:
|
$(BUILD_DIR)/.ok:
|
||||||
mkdir -p "$(dir $(BUILD_DIR)/src/$(IMPORT_PATH))"
|
mkdir -p "$(dir $(BUILD_DIR)/src/$(IMPORT_PATH))"
|
||||||
ln -s `pwd` "$(BUILD_DIR)/src/$(IMPORT_PATH)"
|
ln -s `pwd` "$(BUILD_DIR)/src/$(IMPORT_PATH)"
|
||||||
|
@ -10,16 +10,10 @@ import (
|
|||||||
"github.com/henrydcase/nobs/dh/csidh"
|
"github.com/henrydcase/nobs/dh/csidh"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
PrvSz = 37 // PrvSz is a size of private key in bytes.
|
|
||||||
PubSz = 64 // PubSz is a size of public key in bytes.
|
|
||||||
SsSz = 64 // SsSz is a size of shared secret in bytes.
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSS() {
|
func TestSS() {
|
||||||
var r wrapper.Ref
|
var r wrapper.Ref
|
||||||
var ssRef [SsSz]byte
|
var ssRef [csidh.SharedSecretSize]byte
|
||||||
var ss [SsSz]byte
|
var ss [csidh.SharedSecretSize]byte
|
||||||
|
|
||||||
// Go types
|
// Go types
|
||||||
prA := r.KeygenPrv()
|
prA := r.KeygenPrv()
|
||||||
@ -48,8 +42,8 @@ func TestSS() {
|
|||||||
|
|
||||||
func TestKeyImport() {
|
func TestKeyImport() {
|
||||||
var r wrapper.Ref
|
var r wrapper.Ref
|
||||||
var ssRef [SsSz]byte
|
var ssRef [csidh.SharedSecretSize]byte
|
||||||
var ss [SsSz]byte
|
var ss [csidh.SharedSecretSize]byte
|
||||||
|
|
||||||
// Go types
|
// Go types
|
||||||
prA := r.KeygenPrv()
|
prA := r.KeygenPrv()
|
||||||
@ -75,8 +69,8 @@ func TestKeyImport() {
|
|||||||
|
|
||||||
func TestKeyGeneration() {
|
func TestKeyGeneration() {
|
||||||
var r wrapper.Ref
|
var r wrapper.Ref
|
||||||
var ssRef [SsSz]byte
|
var ssRef [csidh.SharedSecretSize]byte
|
||||||
var ss [SsSz]byte
|
var ss [csidh.SharedSecretSize]byte
|
||||||
|
|
||||||
// Go types
|
// Go types
|
||||||
prA := csidh.NewPrivateKey()
|
prA := csidh.NewPrivateKey()
|
||||||
@ -110,6 +104,7 @@ func main() {
|
|||||||
fmt.Printf("| TestName |Go | C |\n")
|
fmt.Printf("| TestName |Go | C |\n")
|
||||||
fmt.Printf("|------------------|----------|----------|\n")
|
fmt.Printf("|------------------|----------|----------|\n")
|
||||||
|
|
||||||
|
// OZAPTF: make configurable
|
||||||
// for i:=0; i<100; i++ {
|
// for i:=0; i<100; i++ {
|
||||||
for {
|
for {
|
||||||
TestSS()
|
TestSS()
|
||||||
|
182
csidh/cmd/vector-creator/main.go
Normal file
182
csidh/cmd/vector-creator/main.go
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
|
"github.com/henrydcase/nobs/dh/csidh"
|
||||||
|
"github.com/henrydcase/sidh_torture/csidh/ref/go-wrapper"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Possible values for "Status"
|
||||||
|
const (
|
||||||
|
Valid = iota // Indicates that shared secret must be agreed correctly
|
||||||
|
InvalidSharedSecret // Calculated shared secret must be different than test vector
|
||||||
|
InvalidPublicKey1 // Public key 1 generated from private key must be different than test vector
|
||||||
|
InvalidPublicKey2 // Public key 2 must fail validation
|
||||||
|
)
|
||||||
|
|
||||||
|
var StatusValues = map[int]string{
|
||||||
|
Valid: "valid",
|
||||||
|
InvalidSharedSecret: "invalid_shared_secret",
|
||||||
|
InvalidPublicKey1: "invalid_public_key1",
|
||||||
|
InvalidPublicKey2: "invalid_public_key2",
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestVector struct {
|
||||||
|
Id int `json:"Id"`
|
||||||
|
Pk1 string `json:"Pk1"`
|
||||||
|
Pr1 string `json:"Pr1"`
|
||||||
|
Pk2 string `json:"Pk2"`
|
||||||
|
Ss string `json:"Ss"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestVectors struct {
|
||||||
|
Vectors []TestVector `json:"Vectors"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// R is a reference to C implementation.
|
||||||
|
var R wrapper.Ref
|
||||||
|
|
||||||
|
// createValid creates 'num' of TestVector's. Each vector contains
|
||||||
|
// valid data.
|
||||||
|
func createValid(num int) TestVector {
|
||||||
|
var tv TestVector
|
||||||
|
var ss [csidh.SharedSecretSize]byte
|
||||||
|
var pk [csidh.PublicKeySize]byte
|
||||||
|
var pr [csidh.PrivateKeySize]byte
|
||||||
|
|
||||||
|
prA := R.KeygenPrv()
|
||||||
|
pkA := R.KeygenPub(&prA)
|
||||||
|
prB := R.KeygenPrv()
|
||||||
|
pkB := R.KeygenPub(&prB)
|
||||||
|
|
||||||
|
R.Derive(ss[:], &pkB, &prA)
|
||||||
|
|
||||||
|
tv.Id = num
|
||||||
|
tv.Status = StatusValues[Valid]
|
||||||
|
|
||||||
|
tv.Ss = hex.EncodeToString(ss[:])
|
||||||
|
|
||||||
|
prA.Export(pr[:])
|
||||||
|
tv.Pr1 = hex.EncodeToString(pr[:])
|
||||||
|
|
||||||
|
pkA.Export(pk[:])
|
||||||
|
tv.Pk1 = hex.EncodeToString(pk[:])
|
||||||
|
|
||||||
|
for i, _ := range pk {
|
||||||
|
pk[i] = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pkB.Export(pk[:])
|
||||||
|
tv.Pk2 = hex.EncodeToString(pk[:])
|
||||||
|
|
||||||
|
return tv
|
||||||
|
}
|
||||||
|
|
||||||
|
func createNegativeSharedSecret(vectors *TestVectors) {
|
||||||
|
n := len(vectors.Vectors)
|
||||||
|
tv := createValid(n)
|
||||||
|
ss, err := hex.DecodeString(tv.Ss)
|
||||||
|
if err != nil {
|
||||||
|
panic("Can't decode shared secret")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i:=0; i<csidh.SharedSecretSize; i++ {
|
||||||
|
var newSs [csidh.SharedSecretSize]byte
|
||||||
|
copy(newSs[:], ss[:])
|
||||||
|
newSs[i] = ss[i]^ss[(i+1)%csidh.SharedSecretSize]
|
||||||
|
|
||||||
|
if bytes.Equal(newSs[:], ss) {
|
||||||
|
tv.Status = StatusValues[Valid]
|
||||||
|
} else {
|
||||||
|
tv.Status = StatusValues[InvalidSharedSecret]
|
||||||
|
}
|
||||||
|
tv.Ss = hex.EncodeToString(newSs[:])
|
||||||
|
tv.Id = n + i
|
||||||
|
vectors.Vectors = append(vectors.Vectors, tv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public key validation fails
|
||||||
|
func createNegativePk2(vectors *TestVectors) {
|
||||||
|
n := len(vectors.Vectors)
|
||||||
|
tv := createValid(n)
|
||||||
|
pk, err := hex.DecodeString(tv.Pk2)
|
||||||
|
if err != nil {
|
||||||
|
panic("Can't decode public key 2")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i:=0; i<csidh.PublicKeySize; i++ {
|
||||||
|
var newPk [csidh.PublicKeySize]byte
|
||||||
|
|
||||||
|
// Modify good public key so it's probably no longer valid
|
||||||
|
copy(newPk[:], pk[:])
|
||||||
|
newPk[i] = pk[i]^pk[(i+1)%csidh.PublicKeySize]
|
||||||
|
|
||||||
|
// Try to validate and set the status
|
||||||
|
if R.Validate(newPk[:]) {
|
||||||
|
tv.Status = StatusValues[Valid]
|
||||||
|
} else {
|
||||||
|
tv.Status = StatusValues[InvalidPublicKey2]
|
||||||
|
}
|
||||||
|
tv.Pk2 = hex.EncodeToString(newPk[:])
|
||||||
|
tv.Id = n + i
|
||||||
|
vectors.Vectors = append(vectors.Vectors, tv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private key doesn't correspond to public key
|
||||||
|
func createNegativePrivateKey(vectors *TestVectors, num int) {
|
||||||
|
n := len(vectors.Vectors)
|
||||||
|
for i:=0; i<num; i++ {
|
||||||
|
var tv TestVector
|
||||||
|
var pkBytes1 [csidh.PublicKeySize]byte
|
||||||
|
var pkBytes2 [csidh.PublicKeySize]byte
|
||||||
|
var prBytes [csidh.PrivateKeySize]byte
|
||||||
|
|
||||||
|
pr1 := R.KeygenPrv()
|
||||||
|
pk1 := R.KeygenPub(&pr1)
|
||||||
|
|
||||||
|
// Store private key 1
|
||||||
|
pr1.Export(prBytes[:])
|
||||||
|
tv.Pr1 = hex.EncodeToString(prBytes[:])
|
||||||
|
|
||||||
|
// Generate public key which doesn't correspond to pr1
|
||||||
|
pr2 := R.KeygenPrv()
|
||||||
|
pk2 := R.KeygenPub(&pr2)
|
||||||
|
|
||||||
|
pk1.Export(pkBytes1[:])
|
||||||
|
pk2.Export(pkBytes2[:])
|
||||||
|
if bytes.Equal(pkBytes1[:], pkBytes2[:]) {
|
||||||
|
tv.Status = StatusValues[Valid]
|
||||||
|
} else {
|
||||||
|
tv.Status = StatusValues[InvalidPublicKey1]
|
||||||
|
}
|
||||||
|
|
||||||
|
tv.Id = n + i
|
||||||
|
tv.Pk1 = hex.EncodeToString(pkBytes2[:])
|
||||||
|
|
||||||
|
vectors.Vectors = append(vectors.Vectors, tv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var vectors TestVectors
|
||||||
|
|
||||||
|
for i:=0; i<10; i++ {
|
||||||
|
vectors.Vectors = append(vectors.Vectors, createValid(i))
|
||||||
|
}
|
||||||
|
createNegativeSharedSecret(&vectors)
|
||||||
|
createNegativePrivateKey(&vectors, 10)
|
||||||
|
createNegativePk2(&vectors)
|
||||||
|
|
||||||
|
marshalled, err := json.MarshalIndent(vectors, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
panic("Error occured while Marshalling")
|
||||||
|
}
|
||||||
|
ioutil.WriteFile("testvectors.dat", marshalled, 0644)
|
||||||
|
}
|
@ -230,18 +230,14 @@ void export_public(uint8_t *out, const public_key *pub) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void import_public(public_key *pub, const uint8_t *out) {
|
bool import_public(public_key *pub, const uint8_t *out) {
|
||||||
for (size_t i=0; i<64; i++) {
|
for (size_t i=0; i<64; i++) {
|
||||||
size_t j = i / 8;
|
size_t j = i / 8;
|
||||||
size_t k = i%8;
|
size_t k = i%8;
|
||||||
uint64_t tmp = out[i];
|
uint64_t tmp = out[i];
|
||||||
pub->A.x.c[j] |= tmp << (8*k);
|
pub->A.x.c[j] |= tmp << (8*k);
|
||||||
}
|
}
|
||||||
if (validate(pub)) {
|
return validate(pub);
|
||||||
printf("DUPA");
|
|
||||||
}
|
|
||||||
// TODO: should validate it
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void export_private(uint8_t *out, const private_key *prv) {
|
void export_private(uint8_t *out, const private_key *prv) {
|
||||||
@ -281,3 +277,9 @@ void derive(uint8_t result[64], const uint8_t public[64], const uint8_t private[
|
|||||||
csidh(&ss, &pub, &prv);
|
csidh(&ss, &pub, &prv);
|
||||||
export_public(&result[0], &ss);
|
export_public(&result[0], &ss);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns 1 if valid 0 otherwise
|
||||||
|
int is_valid(const uint8_t *a) {
|
||||||
|
public_key pub = {0};
|
||||||
|
return import_public(&pub, a);
|
||||||
|
}
|
||||||
|
@ -28,7 +28,8 @@ void keygen_pub(uint8_t public[64], const uint8_t private[37]);
|
|||||||
void derive(uint8_t result[64], const uint8_t public[64], const uint8_t private_key[37]);
|
void derive(uint8_t result[64], const uint8_t public[64], const uint8_t private_key[37]);
|
||||||
|
|
||||||
void export_public(uint8_t *out, const public_key *pub);
|
void export_public(uint8_t *out, const public_key *pub);
|
||||||
void import_public(public_key *pub, const uint8_t *out);
|
bool import_public(public_key *pub, const uint8_t *out);
|
||||||
void export_private(uint8_t *out, const private_key *prv);
|
void export_private(uint8_t *out, const private_key *prv);
|
||||||
void import_private(private_key *prv, const uint8_t *out);
|
void import_private(private_key *prv, const uint8_t *out);
|
||||||
|
int is_valid(const uint8_t *a);
|
||||||
#endif
|
#endif
|
||||||
|
@ -72,3 +72,9 @@ func (c Ref) Derive(ss []byte, pub *csidh.PublicKey, prv *csidh.PrivateKey) {
|
|||||||
C.derive(&ss_c_buf[0], &pub_c_buf[0], &prv_c_buf[0])
|
C.derive(&ss_c_buf[0], &pub_c_buf[0], &prv_c_buf[0])
|
||||||
copy(ss, C.GoBytes(unsafe.Pointer(&ss_c_buf[0]), C.int(len(ss_c_buf))))
|
copy(ss, C.GoBytes(unsafe.Pointer(&ss_c_buf[0]), C.int(len(ss_c_buf))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c Ref) Validate(a []byte) bool {
|
||||||
|
var pub_c_buf [PubSz]C.uchar
|
||||||
|
c.toBytes(pub_c_buf[:], a[:])
|
||||||
|
return C.is_valid(&pub_c_buf[0]) != 0
|
||||||
|
}
|
||||||
|
@ -87,18 +87,28 @@ static bool testImportExport() {
|
|||||||
return fp_cmp(&pub1.A, &pub2.A);
|
return fp_cmp(&pub1.A, &pub2.A);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// special cases:
|
||||||
|
// * diag 0
|
||||||
|
// * only 0
|
||||||
static void validator() {
|
static void validator() {
|
||||||
uint8_t rnd[64] = {0};
|
uint8_t rnd[64] = {0};
|
||||||
public_key pub = {0};
|
private_key prA = {0};
|
||||||
for (size_t i=0; i<100; i++) {
|
public_key pubA={0};
|
||||||
randombytes(rnd, sizeof(rnd));
|
|
||||||
printf("%llu=", i);
|
csidh_private(&prA);
|
||||||
import_public(&pub, rnd);
|
csidh(&pubA, &base, &prA);
|
||||||
printf("\n");
|
export_public(rnd, &pubA);
|
||||||
|
|
||||||
|
for (size_t i=0; i<64; i++) {
|
||||||
|
uint8_t r[64] = {0};
|
||||||
|
memcpy(r, rnd, sizeof(r));
|
||||||
|
r[i]=0x01;
|
||||||
|
printf("%u -> ", import_public(&pubA, r));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
// validator();
|
||||||
return !(
|
return !(
|
||||||
testImportExport() &&
|
testImportExport() &&
|
||||||
testLoopRef());
|
testLoopRef());
|
||||||
|
1
csidh/vendor/github.com/henrydcase/nobs
згенерований
сторонній
Символічне посилання
1
csidh/vendor/github.com/henrydcase/nobs
згенерований
сторонній
Символічне посилання
@ -0,0 +1 @@
|
|||||||
|
/home/hdc/repos/nobs/
|
Завантаження…
Посилання в новій задачі
Block a user