@@ -33,7 +33,7 @@ $(BUILD_DIR)/%.o: %.s | |||
case $@ in */*) f=$@; mkdir -p $${f%/*} ;; esac | |||
$(CC) -c -o $@ $< $(CFLAGS) | |||
all: libcsidh torturer | |||
all: libcsidh torturer vector-creator | |||
libcsidh: $(CODE_OBJ) | |||
mkdir -p $(PRJ_DIR)/$(BIN_DIR) | |||
@@ -48,6 +48,9 @@ clean: | |||
torturer: $(BUILD_DIR)/.ok | |||
GOPATH=$(GOPATH_LOCAL) $(GO) install $(IMPORT_PATH)/cmd/$@ | |||
vector-creator: $(BUILD_DIR)/.ok | |||
GOPATH=$(GOPATH_LOCAL) $(GO) install $(IMPORT_PATH)/cmd/$@ | |||
$(BUILD_DIR)/.ok: | |||
mkdir -p "$(dir $(BUILD_DIR)/src/$(IMPORT_PATH))" | |||
ln -s `pwd` "$(BUILD_DIR)/src/$(IMPORT_PATH)" | |||
@@ -10,16 +10,10 @@ import ( | |||
"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() { | |||
var r wrapper.Ref | |||
var ssRef [SsSz]byte | |||
var ss [SsSz]byte | |||
var ssRef [csidh.SharedSecretSize]byte | |||
var ss [csidh.SharedSecretSize]byte | |||
// Go types | |||
prA := r.KeygenPrv() | |||
@@ -48,8 +42,8 @@ func TestSS() { | |||
func TestKeyImport() { | |||
var r wrapper.Ref | |||
var ssRef [SsSz]byte | |||
var ss [SsSz]byte | |||
var ssRef [csidh.SharedSecretSize]byte | |||
var ss [csidh.SharedSecretSize]byte | |||
// Go types | |||
prA := r.KeygenPrv() | |||
@@ -75,8 +69,8 @@ func TestKeyImport() { | |||
func TestKeyGeneration() { | |||
var r wrapper.Ref | |||
var ssRef [SsSz]byte | |||
var ss [SsSz]byte | |||
var ssRef [csidh.SharedSecretSize]byte | |||
var ss [csidh.SharedSecretSize]byte | |||
// Go types | |||
prA := csidh.NewPrivateKey() | |||
@@ -110,6 +104,7 @@ func main() { | |||
fmt.Printf("| TestName |Go | C |\n") | |||
fmt.Printf("|------------------|----------|----------|\n") | |||
// OZAPTF: make configurable | |||
// for i:=0; i<100; i++ { | |||
for { | |||
TestSS() | |||
@@ -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++) { | |||
size_t j = i / 8; | |||
size_t k = i%8; | |||
uint64_t tmp = out[i]; | |||
pub->A.x.c[j] |= tmp << (8*k); | |||
} | |||
if (validate(pub)) { | |||
printf("DUPA"); | |||
} | |||
// TODO: should validate it | |||
return validate(pub); | |||
} | |||
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); | |||
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 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 import_private(private_key *prv, const uint8_t *out); | |||
int is_valid(const uint8_t *a); | |||
#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]) | |||
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); | |||
} | |||
// special cases: | |||
// * diag 0 | |||
// * only 0 | |||
static void validator() { | |||
uint8_t rnd[64] = {0}; | |||
public_key pub = {0}; | |||
for (size_t i=0; i<100; i++) { | |||
randombytes(rnd, sizeof(rnd)); | |||
printf("%llu=", i); | |||
import_public(&pub, rnd); | |||
printf("\n"); | |||
private_key prA = {0}; | |||
public_key pubA={0}; | |||
csidh_private(&prA); | |||
csidh(&pubA, &base, &prA); | |||
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() { | |||
// validator(); | |||
return !( | |||
testImportExport() && | |||
testLoopRef()); | |||
@@ -0,0 +1 @@ | |||
/home/hdc/repos/nobs/ |