CryptoSys Home > PKI > New features introduced CryptoSys Pro 1.0 to Pro 2.0

New features introduced CryptoSys PKI Pro 1.0 to Pro 2.0


This page looks at some of the new features introduced from the release of CryptoSys PKI Pro 1.0 in March 2015 to the release of CryptoSys PKI Pro 2.0 in October 2020.

Some sample C# and VBA/VB6 code below.

Some links with more information:

Some C# and VBA/VB6 code using new features in CryptoSys PKI Pro 2.0

Compute ECDH shared secret using NIST P-256

C# code

Console.WriteLine("\nECDH SHARED SECRET USING P-256:");
// Ref: CAVS 14.1 ECC CDH Primitive (SP800 - 56A Section 5.7.1.2)
// Test Information for "testecccdh" ecccdhtestvectors.zip
// [P-256]
Ecc.CurveName curve = Ecc.CurveName.P_256;
// Our private key is dUIT:
string ourPrivateKeyHex = "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534";
// Their public key as hex is "04" || QCAVSx || QCAVSy
string theirPublicKeyHex = "04" + "700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287"
	+ "db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac";
// Correct expected result
string zzOK = "46FC62106420FF012E54A434FBDD2D25CCC5852060561E68040DD7778997BD7B";
string ourPrivateKey = Ecc.ReadKeyByCurve(ourPrivateKeyHex, curve);
Console.WriteLine("Curve = {0}", Ecc.QueryKey(ourPrivateKey, "curveName"));
Console.WriteLine("Our private key has {0} bits", Ecc.QueryKey(ourPrivateKey, "keyBits"));
string theirPublicKey = Ecc.ReadKeyByCurve(theirPublicKeyHex, curve);
Console.WriteLine("Their public key has {0} bits", Ecc.QueryKey(theirPublicKey, "keyBits"));

// Compute shared secret
byte[] zz = Ecc.DHSharedSecret(ourPrivateKey, theirPublicKey);
Console.WriteLine("ZZ={0}", Cnv.ToHex(zz));
Debug.Assert(Cnv.ToHex(zz) == zzOK, "Ecc.DHSharedSecret failed");

VBA/VB6 code

For similar code using VBA/VB6 see the example in ECC_DHSharedSecret and the (shorter) example below. This shorter example uses the new VBA/VB6 wrapper functions introduced v20.0.1.

Debug.Print "Testing ECC_DHSharedSecret ..."
Dim strOurPriKeyHex As String
Dim strTheirPubKeyHex As String
Dim strOurPrivateKey As String
Dim strTheirPublicKey As String
Dim strCurveName As String
Dim strCorrectHex As String
Dim lpZZ() As Byte

' Ref: CAVS 14.1 ECC CDH Primitive (SP800 - 56A Section 5.7.1.2)
' Test Information for "testecccdh" ecccdhtestvectors.zip
'[P-256]
strCurveName = "P-256"
' Our private key is dUIT:
strOurPriKeyHex = "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534"
' Their public key as hex is "04" || QCAVSx || QCAVSy
strTheirPubKeyHex = "04" & "700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287" _
	+ "db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac"
' Correct result is ZIUT
strCorrectHex = "46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b"

Debug.Print "Test for curve " & strCurveName & " ..."
' Read in keys to internal key strings
' Our private key...
strOurPrivateKey = eccReadKeyByCurve(strOurPriKeyHex, strCurveName, 0)
Debug.Assert Len(strOurPrivateKey) > 0
' Check the key we read in
Debug.Print "Our private key has " & ECC_QueryKey("", 0, strOurPrivateKey, "keyBits", 0) & " bits"

' Their public key...
strTheirPublicKey = eccReadKeyByCurve(strTheirPubKeyHex, strCurveName, 0)
Debug.Assert Len(strTheirPublicKey) > 0
' Check the key we read in
Debug.Print "Their public key has " & ECC_QueryKey("", 0, strTheirPublicKey, "keyBits", 0) & " bits"

' Compute shared secret
lpZZ = eccDHSharedSecret(strOurPrivateKey, strTheirPublicKey, 0)
Debug.Assert cnvBytesLen(lpZZ) > 0

Debug.Print "ZZ=" & cnvHexStrFromBytes(lpZZ)
' Check the result
Debug.Print "OK=" & strCorrectHex
Debug.Assert UCase(cnvHexStrFromBytes(lpZZ)) = UCase(strCorrectHex)

Compute ECDH shared secret using X25519

C# code

Console.WriteLine("\nECDH SHARED SECRET USING X25519:");

// Ref: RFC7748 Section 6.1
// https://tools.ietf.org/html/rfc7748#section-6.1
/*
Test vector:
Alice's private key, a:
	77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a
Alice's public key, X25519(a, 9):
	8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a
Bob's private key, b:
	5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb
Bob's public key, X25519(b, 9):
	de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f
Their shared secret, K:
	4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742
*/
Ecc.CurveName curve = Ecc.CurveName.X25519;

string alicePrivateKeyHex = "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a";
string alicePublicKeyHex = "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a";
string bobPrivateKeyHex = "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb";
string bobPublicKeyHex = "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f";
// Correct expected result
string zzOK = "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742";

// 1. Alice's private + Bob's public
// NB we *must* specify whether X25519 keys are public or private
string ourPrivateKey = Ecc.ReadKeyByCurve(alicePrivateKeyHex, curve, Ecc.KeyType.PrivateKey);
Console.WriteLine("Curve = {0}", Ecc.QueryKey(ourPrivateKey, "curveName"));
Console.WriteLine("Our private key has {0} bits", Ecc.QueryKey(ourPrivateKey, "keyBits"));
string theirPublicKey = Ecc.ReadKeyByCurve(bobPublicKeyHex, curve, Ecc.KeyType.PublicKey);
Console.WriteLine("Their public key has {0} bits", Ecc.QueryKey(theirPublicKey, "keyBits"));
// Compute shared secret
byte[] zz1 = Ecc.DHSharedSecret(ourPrivateKey, theirPublicKey);
Console.WriteLine("ZZ={0}", Cnv.ToHex(zz1));
Debug.Assert(Cnv.ToHex(zz1).ToLower() == zzOK, "Ecc.DHSharedSecret failed");

// 2. Bob's private + Alice's public
ourPrivateKey = Ecc.ReadKeyByCurve(bobPrivateKeyHex, curve, Ecc.KeyType.PrivateKey);
theirPublicKey = Ecc.ReadKeyByCurve(alicePublicKeyHex, curve, Ecc.KeyType.PublicKey);
// Compute shared secret
byte[] zz2 = Ecc.DHSharedSecret(ourPrivateKey, theirPublicKey);
Console.WriteLine("ZZ={0}", Cnv.ToHex(zz2));
Debug.Assert(Cnv.ToHex(zz2).ToLower() == zzOK, "Ecc.DHSharedSecret failed");

VBA/VB6 code

' Ref: RFC7748 Section 6.1
' https://tools.ietf.org/html/rfc7748#section-6.1
'
'    Test vector:
'    Alice's private key, a:
'        77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a
'    Alice's public key, X25519(a, 9):
'        8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a
'    Bob's private key, b:
'        5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb
'    Bob's public key, X25519(b, 9):
'        de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f
'    Their shared secret, K:
'        4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742

' NB uses functions in basCrPKIWrappers.bas, available in v20.0.1
Dim curveName As String
Dim alicePrivateKeyHex As String
Dim alicePublicKeyHex As String
Dim bobPrivateKeyHex As String
Dim bobPublicKeyHex As String
Dim zzOK As String
Dim ourPrivateKey As String
Dim theirPublicKey As String
Dim zz1() As Byte
Dim zz2() As Byte

curveName = "X25519"
alicePrivateKeyHex = "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a"
alicePublicKeyHex = "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"
bobPrivateKeyHex = "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb"
bobPublicKeyHex = "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f"
' Correct expected result
zzOK = "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"

' 1. Alice's private + Bob's public
' NB we *must* specify whether X25519 keys are public or private
ourPrivateKey = eccReadKeyByCurve(alicePrivateKeyHex, curveName, PKI_ECC_PRIVATE_KEY)
Debug.Assert Len(ourPrivateKey) > 0
Debug.Print "Our private key has " & ECC_QueryKey("", 0, ourPrivateKey, "keyBits", 0) & " bits"
theirPublicKey = eccReadKeyByCurve(bobPublicKeyHex, curveName, PKI_ECC_PUBLIC_KEY)
Debug.Assert Len(theirPublicKey) > 0
Debug.Print "Their public key has " & ECC_QueryKey("", 0, theirPublicKey, "keyBits", 0) & " bits"
' Compute shared secret
zz1 = eccDHSharedSecret(ourPrivateKey, theirPublicKey, 0)
Debug.Print "ZZ=" & cnvHexStrFromBytes(zz1)
Debug.Assert StrComp(cnvHexStrFromBytes(zz1), zzOK, vbTextCompare) = 0

Create self-signed X.509 certificate using Ed25519 and self-issued certificate with X25519 key agreement key

C# code

Console.WriteLine("\nCREATE A SELF-SIGNED X.509 CERTIFICATE USING Ed25519:");
// Ref: [RFC8410] https://tools.ietf.org/html/rfc8410

string dn, extns, certname, prikeyfile, query;
string pubkeystr, issuercert;
X509.KeyUsageOptions keyUsage;
int r;
string s;

// 1. Create a new self-*signed* certificate using the Ed25519 key in RFC8410
certname = "ietf-Ed25519-self.cer";
prikeyfile = "edwards-ietf.p8"; // No password
dn = "CN=IETF Test Demo";
extns = "notBefore=2016-01-01;notAfter=2040-12-31";
//Digital Signature, Certificate Signing, [Off-line CRL Signing], CRL Signing
keyUsage = X509.KeyUsageOptions.DigitalSignature | X509.KeyUsageOptions.KeyCertSign | X509.KeyUsageOptions.CrlSign;
r = X509.MakeCertSelf(certname, prikeyfile, 0x0ED25519, 0, dn, extns, keyUsage, "", SigAlgorithm.Ed25519, X509.CertOptions.UTF8String);
Console.WriteLine("X509.MakeCertSelf returns {0} (expecting 0)", r);
Debug.Assert(0 == r, "X509.MakeCertSelf failed");
// Dump details
Console.WriteLine("FILE: {0}", certname);
Console.WriteLine(X509.TextDumpToString(certname, 0));

// Do a query on the cert
query = "signatureAlgorithm";
s = X509.QueryCert(certname, query);
Console.WriteLine("{0}={1}", query, s);
Debug.Assert(s.Length > 0, "X509.QueryCert failed");

// 2. Now create a self-*issued* cert using Ed25519 to sign an X25519 public key
// [RFC8410] 10.2. Example X25519 Certificate
// NB This is self-*issued* in that the public key is for an X25519 key intended for ECDH,
// but it is signed using an Ed25519 signature with a key also belonging to ones self.

// Read in X25519 public key from its hex value
// NB we *must* specify that it's a public key
pubkeystr = Ecc.ReadKeyByCurve("8520F0098930A754748B7DDCB43EF75A0DBF3A0D26381AF4EBA4A98EAA9B4E6A", Ecc.CurveName.X25519, Ecc.KeyType.PublicKey);
Debug.Assert(pubkeystr.Length > 0, "Ecc.ReadKeyByCurve failed");

// Set cert parameters to closely duplicate the cert given in RFC8410 (almost!)
dn = "CN=IETF Test Demo";
extns = "notBefore=2016-08-01T12:19:24;notAfter=2040-12-31T23:59:59;keyUsage=noncritical;serialNumber=#x5601474A2A8DC330;" +
	"subjectKeyIdentifier=9B1F5EEDED043385E4F7BC623C5975B90BC8BB3B";
keyUsage = X509.KeyUsageOptions.KeyAgreement;

issuercert = certname;  // Use the self-signed cert we made above to issue this new cert
certname = "ietf-X25519-self-issued.cer";

r = X509.MakeCert(certname, issuercert, pubkeystr, prikeyfile, 0, 0, dn, extns, keyUsage, "", SigAlgorithm.Ed25519, X509.CertOptions.UTF8String);
Console.WriteLine("X509.MakeCert returns {0} (expecting 0)", r);
Debug.Assert(0 == r, "X509.MakeCert failed");
// Dump details
Console.WriteLine("FILE: {0}", certname);
Console.WriteLine(X509.TextDumpToString(certname, 0));

// Verify that this cert was signed by the above
r = X509.VerifyCert(certname, issuercert);
Console.WriteLine("X509.VerifyCert returns {0} (expecting 0 => verified OK)", r);
Debug.Assert(0 == r, "X509.VerifyCert failed");

Output of above code:

CREATE A SELF-SIGNED X.509 CERTIFICATE USING Ed25519:
X509.MakeCertSelf returns 0 (expecting 0)
FILE: ietf-Ed25519-self.cer
X.509 CERTIFICATE
Version: 3
Serial Number:
  #x0ED25519
Issuer:
  CN=IETF Test Demo
Subject:
  CN=IETF Test Demo
Validity:
  NotBefore: 2016-01-01T00:00:01Z
  NotAfter:  2040-12-31T23:59:59Z
Subject Public Key Algorithm: Ed25519
  ECC key length: 256 bits
  Curve: Ed25519
  Public Key Value:
    19 BF 44 09 69 84 CD FE 85 41 BA C1 67 DC 3B 96
    C8 50 86 AA 30 B6 B6 CB 0C 5C 38 AD 70 31 66 E1
X509v3 Extensions:
  Subject Type: CA
  Key Usage[!]:
    digitalSignature,keyCertSign,cRLSign
Signature Algorithm: Ed25519
Signature Hash Algorithm: sha512
Signature Value:
  08 AD 57 0F C2 38 FF 32 F0 7D F3 3B 2E 50 7E 1E
  9A 0D 69 56 1D C8 F8 64 BF C5 5E B3 6D E3 4E 68
  7C C9 C9 A0 B2 18 42 A7 B9 CA 4A 81 FA CD E7 2A
  68 C0 D2 F9 F6 BD 4B A6 C3 01 25 CC 59 A4 E1 06
SHA-1 Thumbprint:
  0ec7fcf0df37594d947bd09cbbb8c014d5aec0e0
SHA-256 Thumbprint:
  42c8ca8d6f22e46e29f3efdffc74e1c16d297179dfcd16eb7b5bdc6100240690

signatureAlgorithm=Ed25519
X509.MakeCert returns 0 (expecting 0)
FILE: ietf-X25519-self-issued.cer
X.509 CERTIFICATE
Version: 3
Serial Number:
  #x5601474A2A8DC330
Issuer:
  CN=IETF Test Demo
Subject:
  CN=IETF Test Demo
Validity:
  NotBefore: 2016-08-01T12:19:24Z
  NotAfter:  2040-12-31T23:59:59Z
Subject Public Key Algorithm: X25519
  ECC key length: 256 bits
  Curve: X25519
  Public Key Value:
    85 20 F0 09 89 30 A7 54 74 8B 7D DC B4 3E F7 5A
    0D BF 3A 0D 26 38 1A F4 EB A4 A9 8E AA 9B 4E 6A
X509v3 Extensions:
  Subject Type: End Entity
  Key Usage:
    keyAgreement
  Subject Key Identifier:
    9b1f5eeded043385e4f7bc623c5975b90bc8bb3b
Signature Algorithm: Ed25519
Signature Hash Algorithm: sha512
Signature Value:
  44 1D 2A A4 48 FB 8E 71 89 99 9C 63 FD 5E 23 0D
  FA 67 A3 F8 1A 1E 62 18 00 4A CA 1C E8 96 EB FD
  CC F3 7F 8F 47 25 61 5B 92 D4 F3 F0 AC A3 C8 4F
  50 2C 34 5E 90 E7 61 95 CF 9E 4B F4 B6 BA 03 04
SHA-1 Thumbprint:
  1e9685c30312d596f7d079fc4c5086166b3ed6fb
SHA-256 Thumbprint:
  966e6c7ca1c70de8a32f1a327595053bbd4c18627eef1e20ecc44835656ba528

X509.VerifyCert returns 0 (expecting 0 => verified OK)

Contact us

To contact us or comment on this page, please send us a message.

[Go to top]

This page last updated 25 October 2023