MastersThesis/PQ_TIIGER_TLS/sal/miracl-ubuntu22-11-04-24/includes/testecc.cpp
2024-04-19 14:16:07 +02:00

624 lines
16 KiB
C++

/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "ecdh_Ed25519.h"
#include "rsa_RSA2048.h"
#include "randapi.h"
#if CHUNK==32 || CHUNK==64
#include "ecdh_NIST256.h"
#include "ecdh_Ed448.h"
#endif
using namespace core;
int ecdh_Ed25519(csprng *RNG)
{
using namespace Ed25519;
int i, res;
unsigned long ran;
char *pp = (char *)"M0ng00se";
// These octets are automatically protected against buffer overflow attacks
// Note salt must be big enough to include an appended word
// Note ECIES ciphertext C must be big enough to include at least 1 appended block
// Recall EFS_Ed25519 is field size in bytes. So EFS_Ed25519=32 for 256-bit curve
char s0[2 * EGS_Ed25519], s1[EGS_Ed25519], w0[2 * EFS_Ed25519 + 1], w1[2 * EFS_Ed25519 + 1], z0[EFS_Ed25519], z1[EFS_Ed25519], key[AESKEY_Ed25519], salt[40], pw[40];
octet S0 = {0, sizeof(s0), s0};
octet S1 = {0, sizeof(s1), s1};
octet W0 = {0, sizeof(w0), w0};
octet W1 = {0, sizeof(w1), w1};
octet Z0 = {0, sizeof(z0), z0};
octet Z1 = {0, sizeof(z1), z1};
octet KEY = {0, sizeof(key), key};
octet SALT = {0, sizeof(salt), salt};
octet PW = {0, sizeof(pw), pw};
SALT.len = 8;
for (i = 0; i < 8; i++) SALT.val[i] = i + 1; // set Salt
printf("Alice's Passphrase= %s\n", pp);
OCT_empty(&PW);
OCT_jstring(&PW, pp); // set Password from string
// private key S0 of size EGS_Ed25519 bytes derived from Password and Salt
PBKDF2(MC_SHA2,HASH_TYPE_Ed25519, &S0, EGS_Ed25519, &PW, &SALT, 1000);
printf("Alices private key= 0x");
OCT_output(&S0);
// Generate Key pair S/W
ECP_KEY_PAIR_GENERATE(NULL, &S0, &W0);
printf("Alices public key= 0x");
OCT_output(&W0);
res = ECP_PUBLIC_KEY_VALIDATE(&W0);
if (res != 0)
{
printf("ECP Public Key is invalid!\n");
return 0;
}
// Random private key for other party
ECP_KEY_PAIR_GENERATE(RNG, &S1, &W1);
res = ECP_PUBLIC_KEY_VALIDATE(&W1);
if (res != 0)
{
printf("ECP Public Key is invalid!\n");
return 0;
}
printf("Servers private key= 0x");
OCT_output(&S1);
printf("Servers public key= 0x");
OCT_output(&W1);
// Calculate common key using DH - IEEE 1363 method
ECP_SVDP_DH(&S0, &W1, &Z0, 0);
ECP_SVDP_DH(&S1, &W0, &Z1, 0);
if (!OCT_comp(&Z0, &Z1))
{
printf("*** ECPSVDP-DH Failed\n");
return 0;
}
KDF2(MC_SHA2, HASH_TYPE_Ed25519, &KEY, AESKEY_Ed25519, &Z0, NULL);
printf("Alice's DH Key= 0x");
OCT_output(&KEY);
printf("Servers DH Key= 0x");
OCT_output(&KEY);
#if CURVETYPE_Ed25519 != MONTGOMERY
char ds[EGS_Ed25519], p1[30], p2[30], v[2 * EFS_Ed25519 + 1], m[32], c[64], t[32], cs[EGS_Ed25519];
octet DS = {0, sizeof(ds), ds};
octet CS = {0, sizeof(cs), cs};
octet P1 = {0, sizeof(p1), p1};
octet P2 = {0, sizeof(p2), p2};
octet V = {0, sizeof(v), v};
octet M = {0, sizeof(m), m};
octet C = {0, sizeof(c), c};
octet T = {0, sizeof(t), t};
printf("Testing ECIES\n");
P1.len = 3;
P1.val[0] = 0x0;
P1.val[1] = 0x1;
P1.val[2] = 0x2;
P2.len = 4;
P2.val[0] = 0x0;
P2.val[1] = 0x1;
P2.val[2] = 0x2;
P2.val[3] = 0x3;
M.len = 17;
for (i = 0; i <= 16; i++) M.val[i] = i;
ECP_ECIES_ENCRYPT(HASH_TYPE_Ed25519, &P1, &P2, RNG, &W1, &M, 12, &V, &C, &T);
printf("Ciphertext= \n");
printf("V= 0x");
OCT_output(&V);
printf("C= 0x");
OCT_output(&C);
printf("T= 0x");
OCT_output(&T);
if (!ECP_ECIES_DECRYPT(HASH_TYPE_Ed25519, &P1, &P2, &V, &C, &T, &S1, &M))
{
printf("*** ECIES Decryption Failed\n");
return 0;
}
else printf("Decryption succeeded\n");
printf("Message is 0x");
OCT_output(&M);
printf("Testing ECDSA\n");
if (ECP_SP_DSA(HASH_TYPE_Ed25519, RNG, NULL, &S0, &M, &CS, &DS) != 0)
{
printf("***ECDSA Signature Failed\n");
return 0;
}
printf("Signature C = 0x");
OCT_output(&CS);
printf("Signature D = 0x");
OCT_output(&DS);
if (ECP_VP_DSA(HASH_TYPE_Ed25519, &W0, &M, &CS, &DS) != 0)
{
printf("***ECDSA Verification Failed\n");
return 0;
}
else
{
printf("ECDSA Signature/Verification succeeded\n");
}
#endif
return 1;
}
#if CHUNK==32 || CHUNK==64
int ecdh_NIST256(csprng *RNG)
{
using namespace NIST256;
int i, res;
unsigned long ran;
char *pp = (char *)"M0ng00se";
// These octets are automatically protected against buffer overflow attacks
// Note salt must be big enough to include an appended word
// Note ECIES ciphertext C must be big enough to include at least 1 appended block
// Recall EFS_NIST256 is field size in bytes. So EFS_NIST256=32 for 256-bit curve
char s0[2 * EGS_NIST256], s1[EGS_NIST256], w0[2 * EFS_NIST256 + 1], w1[2 * EFS_NIST256 + 1], z0[EFS_NIST256], z1[EFS_NIST256], key[AESKEY_NIST256], salt[40], pw[40];
octet S0 = {0, sizeof(s0), s0};
octet S1 = {0, sizeof(s1), s1};
octet W0 = {0, sizeof(w0), w0};
octet W1 = {0, sizeof(w1), w1};
octet Z0 = {0, sizeof(z0), z0};
octet Z1 = {0, sizeof(z1), z1};
octet KEY = {0, sizeof(key), key};
octet SALT = {0, sizeof(salt), salt};
octet PW = {0, sizeof(pw), pw};
SALT.len = 8;
for (i = 0; i < 8; i++) SALT.val[i] = i + 1; // set Salt
printf("Alice's Passphrase= %s\n", pp);
OCT_empty(&PW);
OCT_jstring(&PW, pp); // set Password from string
// private key S0 of size EGS_NIST256 bytes derived from Password and Salt
PBKDF2(MC_SHA2, HASH_TYPE_NIST256, &S0, EGS_NIST256, &PW, &SALT, 1000);
printf("Alices private key= 0x");
OCT_output(&S0);
// Generate Key pair S/W
ECP_KEY_PAIR_GENERATE(NULL, &S0, &W0);
printf("Alices public key= 0x");
OCT_output(&W0);
res = ECP_PUBLIC_KEY_VALIDATE(&W0);
if (res != 0)
{
printf("ECP Public Key is invalid!\n");
return 0;
}
// Random private key for other party
ECP_KEY_PAIR_GENERATE(RNG, &S1, &W1);
res = ECP_PUBLIC_KEY_VALIDATE(&W1);
if (res != 0)
{
printf("ECP Public Key is invalid!\n");
return 0;
}
printf("Servers private key= 0x");
OCT_output(&S1);
printf("Servers public key= 0x");
OCT_output(&W1);
// Calculate common key using DH - IEEE 1363 method
ECP_SVDP_DH(&S0, &W1, &Z0, 0);
ECP_SVDP_DH(&S1, &W0, &Z1, 0);
if (!OCT_comp(&Z0, &Z1))
{
printf("*** ECPSVDP-DH Failed\n");
return 0;
}
KDF2(MC_SHA2, HASH_TYPE_NIST256, &KEY, AESKEY_NIST256, &Z0, NULL);
printf("Alice's DH Key= 0x");
OCT_output(&KEY);
printf("Servers DH Key= 0x");
OCT_output(&KEY);
#if CURVETYPE_NIST256 != MONTGOMERY
char ds[EGS_NIST256], p1[30], p2[30], v[2 * EFS_NIST256 + 1], m[32], c[64], t[32], cs[EGS_NIST256];
octet DS = {0, sizeof(ds), ds};
octet CS = {0, sizeof(cs), cs};
octet P1 = {0, sizeof(p1), p1};
octet P2 = {0, sizeof(p2), p2};
octet V = {0, sizeof(v), v};
octet M = {0, sizeof(m), m};
octet C = {0, sizeof(c), c};
octet T = {0, sizeof(t), t};
printf("Testing ECIES\n");
P1.len = 3;
P1.val[0] = 0x0;
P1.val[1] = 0x1;
P1.val[2] = 0x2;
P2.len = 4;
P2.val[0] = 0x0;
P2.val[1] = 0x1;
P2.val[2] = 0x2;
P2.val[3] = 0x3;
M.len = 17;
for (i = 0; i <= 16; i++) M.val[i] = i;
ECP_ECIES_ENCRYPT(HASH_TYPE_NIST256, &P1, &P2, RNG, &W1, &M, 12, &V, &C, &T);
printf("Ciphertext= \n");
printf("V= 0x");
OCT_output(&V);
printf("C= 0x");
OCT_output(&C);
printf("T= 0x");
OCT_output(&T);
if (!ECP_ECIES_DECRYPT(HASH_TYPE_NIST256, &P1, &P2, &V, &C, &T, &S1, &M))
{
printf("*** ECIES Decryption Failed\n");
return 0;
}
else printf("Decryption succeeded\n");
printf("Message is 0x");
OCT_output(&M);
printf("Testing ECDSA\n");
if (ECP_SP_DSA(HASH_TYPE_NIST256, RNG, NULL, &S0, &M, &CS, &DS) != 0)
{
printf("***ECDSA Signature Failed\n");
return 0;
}
printf("Signature C = 0x");
OCT_output(&CS);
printf("Signature D = 0x");
OCT_output(&DS);
if (ECP_VP_DSA(HASH_TYPE_NIST256, &W0, &M, &CS, &DS) != 0)
{
printf("***ECDSA Verification Failed\n");
return 0;
}
else
{
printf("ECDSA Signature/Verification succeeded\n");
}
#endif
return 1;
}
int ecdh_Ed448(csprng *RNG)
{
using namespace Ed448;
int i, res;
unsigned long ran;
char *pp = (char *)"M0ng00se";
// These octets are automatically protected against buffer overflow attacks
// Note salt must be big enough to include an appended word
// Note ECIES ciphertext C must be big enough to include at least 1 appended block
// Recall EFS_Ed448 is field size in bytes. So EFS_Ed448=32 for 256-bit curve
char s0[2 * EGS_Ed448], s1[EGS_Ed448], w0[2 * EFS_Ed448 + 1], w1[2 * EFS_Ed448 + 1], z0[EFS_Ed448], z1[EFS_Ed448], key[AESKEY_Ed448], salt[40], pw[40];
octet S0 = {0, sizeof(s0), s0};
octet S1 = {0, sizeof(s1), s1};
octet W0 = {0, sizeof(w0), w0};
octet W1 = {0, sizeof(w1), w1};
octet Z0 = {0, sizeof(z0), z0};
octet Z1 = {0, sizeof(z1), z1};
octet KEY = {0, sizeof(key), key};
octet SALT = {0, sizeof(salt), salt};
octet PW = {0, sizeof(pw), pw};
SALT.len = 8;
for (i = 0; i < 8; i++) SALT.val[i] = i + 1; // set Salt
printf("Alice's Passphrase= %s\n", pp);
OCT_empty(&PW);
OCT_jstring(&PW, pp); // set Password from string
// private key S0 of size EGS_Ed448 bytes derived from Password and Salt
PBKDF2(MC_SHA2, HASH_TYPE_Ed448, &S0, EGS_Ed448, &PW, &SALT, 1000);
printf("Alices private key= 0x");
OCT_output(&S0);
// Generate Key pair S/W
ECP_KEY_PAIR_GENERATE(NULL, &S0, &W0);
printf("Alices public key= 0x");
OCT_output(&W0);
res = ECP_PUBLIC_KEY_VALIDATE(&W0);
if (res != 0)
{
printf("ECP Public Key is invalid!\n");
return 0;
}
// Random private key for other party
ECP_KEY_PAIR_GENERATE(RNG, &S1, &W1);
res = ECP_PUBLIC_KEY_VALIDATE(&W1);
if (res != 0)
{
printf("ECP Public Key is invalid!\n");
return 0;
}
printf("Servers private key= 0x");
OCT_output(&S1);
printf("Servers public key= 0x");
OCT_output(&W1);
// Calculate common key using DH - IEEE 1363 method
ECP_SVDP_DH(&S0, &W1, &Z0, 0);
ECP_SVDP_DH(&S1, &W0, &Z1, 0);
if (!OCT_comp(&Z0, &Z1))
{
printf("*** ECPSVDP-DH Failed\n");
return 0;
}
KDF2(MC_SHA2, HASH_TYPE_Ed448, &KEY, AESKEY_Ed448, &Z0, NULL);
printf("Alice's DH Key= 0x");
OCT_output(&KEY);
printf("Servers DH Key= 0x");
OCT_output(&KEY);
#if CURVETYPE_Ed448 != MONTGOMERY
char ds[EGS_Ed448], p1[30], p2[30], v[2 * EFS_Ed448 + 1], m[32], c[64], t[32], cs[EGS_Ed448];
octet DS = {0, sizeof(ds), ds};
octet CS = {0, sizeof(cs), cs};
octet P1 = {0, sizeof(p1), p1};
octet P2 = {0, sizeof(p2), p2};
octet V = {0, sizeof(v), v};
octet M = {0, sizeof(m), m};
octet C = {0, sizeof(c), c};
octet T = {0, sizeof(t), t};
printf("Testing ECIES\n");
P1.len = 3;
P1.val[0] = 0x0;
P1.val[1] = 0x1;
P1.val[2] = 0x2;
P2.len = 4;
P2.val[0] = 0x0;
P2.val[1] = 0x1;
P2.val[2] = 0x2;
P2.val[3] = 0x3;
M.len = 17;
for (i = 0; i <= 16; i++) M.val[i] = i;
ECP_ECIES_ENCRYPT(HASH_TYPE_Ed448, &P1, &P2, RNG, &W1, &M, 12, &V, &C, &T);
printf("Ciphertext= \n");
printf("V= 0x");
OCT_output(&V);
printf("C= 0x");
OCT_output(&C);
printf("T= 0x");
OCT_output(&T);
if (!ECP_ECIES_DECRYPT(HASH_TYPE_Ed448, &P1, &P2, &V, &C, &T, &S1, &M))
{
printf("*** ECIES Decryption Failed\n");
return 0;
}
else printf("Decryption succeeded\n");
printf("Message is 0x");
OCT_output(&M);
printf("Testing ECDSA\n");
if (ECP_SP_DSA(HASH_TYPE_Ed448, RNG, NULL, &S0, &M, &CS, &DS) != 0)
{
printf("***ECDSA Signature Failed\n");
return 0;
}
printf("Signature C = 0x");
OCT_output(&CS);
printf("Signature D = 0x");
OCT_output(&DS);
if (ECP_VP_DSA(HASH_TYPE_Ed448, &W0, &M, &CS, &DS) != 0)
{
printf("***ECDSA Verification Failed\n");
return 0;
}
else
{
printf("ECDSA Signature/Verification succeeded\n");
}
#endif
return 1;
}
#endif
int rsa_2048(csprng *RNG)
{
using namespace RSA2048;
int i,valid;
unsigned long ran;
char m[RFS_RSA2048], ml[RFS_RSA2048], c[RFS_RSA2048], e[RFS_RSA2048], s[RFS_RSA2048];
rsa_public_key pub;
rsa_private_key priv;
octet M = {0, sizeof(m), m};
octet ML = {0, sizeof(ml), ml};
octet C = {0, sizeof(c), c};
octet E = {0, sizeof(e), e};
octet S = {0, sizeof(s), s};
printf("Generating public/private key pair\n");
RSA_KEY_PAIR(RNG, 65537, &priv, &pub, NULL, NULL);
printf("Encrypting test string\n");
OCT_jstring(&M, (char *)"Hello World\n");
OAEP_ENCODE(HASH_TYPE_RSA_RSA2048, &M, RNG, NULL, &E); // OAEP encode message m to e
RSA_ENCRYPT(&pub, &E, &C); // encrypt encoded message
printf("Ciphertext= ");
OCT_output(&C);
printf("Decrypting test string\n");
RSA_DECRYPT(&priv, &C, &ML); // ... and then decrypt it
printf("Decrypted\n");
OAEP_DECODE(HASH_TYPE_RSA_RSA2048, NULL, &ML); // decode it
printf("Decoded\n");
OCT_output_string(&ML);
PSS_ENCODE(HASH_TYPE_RSA_RSA2048, &M, RNG, &C);
//printf("T= 0x");OCT_output(&C);
if (PSS_VERIFY(HASH_TYPE_RSA_RSA2048, &M, &C))
printf("PSS encoding OK\n");
else
printf("PSS Encoding FAILED\n");
// Signature
printf("Signing message\n");
PKCS15(HASH_TYPE_RSA_RSA2048, &M, &C);
RSA_DECRYPT(&priv, &C, &S); // create signature in S
printf("Signature= ");
OCT_output(&S);
// Verification
valid=0;
RSA_ENCRYPT(&pub, &S, &ML);
PKCS15(HASH_TYPE_RSA_RSA2048, &M, &C);
if (OCT_comp(&C, &ML)) valid=1;
else {
PKCS15b(HASH_TYPE_RSA_RSA2048, &M, &C);
if (OCT_comp(&C, &ML)) valid=1;
}
if (valid) printf("Signature is valid\n");
else printf("Signature is INVALID\n");
RSA_PRIVATE_KEY_KILL(&priv);
OCT_clear(&M);
OCT_clear(&ML); // clean up afterwards
OCT_clear(&C);
OCT_clear(&E);
return 1;
}
int main()
{
int i, res;
unsigned long ran;
char raw[100];
octet RAW = {0, sizeof(raw), raw};
csprng RNG; // Crypto Strong RNG
time((time_t *)&ran);
RAW.len = 100; // fake random seed source
RAW.val[0] = ran;
RAW.val[1] = ran >> 8;
RAW.val[2] = ran >> 16;
RAW.val[3] = ran >> 24;
for (i = 0; i < 100; i++) RAW.val[i] = i;
CREATE_CSPRNG(&RNG, &RAW); // initialise strong RNG
printf("\nTesting ECDH protocols for curve Ed25519\n");
ecdh_Ed25519(&RNG);
#if CHUNK!=16
printf("\nTesting ECDH protocols for curve NIST256\n");
ecdh_NIST256(&RNG);
printf("\nTesting ECDH protocols for curve Ed448\n");
ecdh_Ed448(&RNG);
#endif
printf("\nTesting RSA protocols for 2048-bit RSA\n");
rsa_2048(&RNG);
KILL_CSPRNG(&RNG);
}