Smart Card Shell

Crypto - Reference Documentation

Implements access to cryptographic services.

Index of Methods

Constants

Type Name Description
Number RSA RSA algorithm
Number RSA_ISO9796_2 RSA algorithm in ISO-9796-2 variant
Number RSA_PKCS1 RSA Encryption with PKCS#1 V1.5 padding
Number RSA_OAEP RSA Encryption with OAEP padding using SHA-1 and MGF1
Number RSA_OAEP_SHA224 RSA Encryption with OAEP padding using SHA-224 and MGF1
Number RSA_OAEP_SHA256 RSA Encryption with OAEP padding using SHA-256 and MGF1
Number RSA_OAEP_SHA384 RSA Encryption with OAEP padding using SHA-384 and MGF1
Number RSA_OAEP_SHA512 RSA Encryption with OAEP padding using SHA-512 and MGF1
Number RSA_SHA1 SHA-1 with RSA signature algorithm and PKCS#1 V1.5 encoding
Number RSA_SHA224 SHA-224 with RSA signature algorithm and PKCS#1 V1.5 encoding
Number RSA_SHA256 SHA-256 with RSA signature algorithm and PKCS#1 V1.5 encoding
Number RSA_SHA384 SHA-384 with RSA signature algorithm and PKCS#1 V1.5 encoding
Number RSA_SHA512 SHA-512 with RSA signature algorithm and PKCS#1 V1.5 encoding
Number RSA_PSS_SHA1 SHA-1 with RSA signature algorithm and PKCS#1 V1.5 encoding
Number RSA_PSS_SHA224 SHA-224 with RSA signature algorithm and PSS encoding
Number RSA_PSS_SHA256 SHA-256 with RSA signature algorithm and PSS encoding
Number RSA_PSS_SHA384 SHA-384 with RSA signature algorithm and PSS encoding
Number RSA_PSS_SHA512 SHA-512 with RSA signature algorithm and PSS encoding
Number EC Elliptic curve key operation
Number ECDSA Elliptic curve digital signature algorithm without hash
Number ECDSA_SHA1 Elliptic curve digital signature algorithm using SHA-1
Number ECDSA_SHA224 Elliptic curve digital signature algorithm using SHA-224
Number ECDSA_SHA256 Elliptic curve digital signature algorithm using SHA-256
Number ECDSA_SHA384 Elliptic curve digital signature algorithm using SHA-384
Number ECDSA_SHA512 Elliptic curve digital signature algorithm using SHA-512
Number ECDH Elliptic curve Diffie-hellman algorithm
Number ECDHC Elliptic curve Diffie-hellman algorithm with cofactor
Number ECDHP Elliptic curve Diffie-hellman algorithm returning x and y coordinate of shared point
Number EC_MULTIPLY_ADD Elliptic curve point multiplication and addition
Number EC_MULTIPLY_SUB Elliptic curve point multiplication and substraction
Number ECELGAMAL ElGamal Decryption
Number DES_CBC Cipher Block Chaining encryption using DES
Number DES_ECB Electronic Cook Book encryption using DES
Number AES_CBC Cipher Block Chaining encryption using AES
Number AES_ECB Electronic Cook Book encryption using AES
Number AES_CTR Segmented Integer Counter (CTR) encryption using AES
Number AES_CMAC Message Authentication Code (MAC) acccording to NIST Special Publication 800-38B
Number MD5 MD5 message digest algorithm
Number SHA_1 SHA-1 message digest algorithm
Number SHA_224 SHA-224 message digest algorithm
Number SHA_256 SHA-256 message digest algorithm
Number SHA_384 SHA-384 message digest algorithm
Number SHA_512 SHA-512 message digest algorithm
Number DES_MAC Message authentication code using 3DES for each block
Number DES_MAC_EMV Message authentication code using DES for each block and 3DES for final block (Retail MAC)
Number DES_CBC_LP Variant of DES_CBC encryption used for wrap operations (Length || Key || ISOPadding)
Number DES_CBC_P Variant of DES_CBC encryption used for wrap operations (Key || ISOPadding)
Number DES_ECB_LP Variant of DES_ECB encryption used for wrap operations (Length || Key || ISOPadding)
Number DES_ECB_P Variant of DES_ECB encryption used for wrap operations (Key || ISOPadding)
Number ISO9797_METHOD_1 Padding method according to ISO 9797 with 8 byte block size
Number ISO9797_METHOD_2 Padding method according to ISO 9797 with 8 byte block size
Number ISO9797_METHOD_1_16 Padding method according to ISO 9797 with 16 byte block size
Number ISO9797_METHOD_2_16 Padding method according to ISO 9797 with 16 byte block size
Number DES Constant to denote a single length (56 bit) DES key in generateKey()
Number DES2 Constant to denote a double length (112 bit) DES key in generateKey()
Number DES3 Constant to denote a double length (168 bit) DES key in generateKey()
Number HMAC_SHA1 Constant to denote a Hashmac using SHA-1
Number HMAC_SHA256 Constant to denote a Hashmac using SHA-256
Number HMAC_SHA384 Constant to denote a Hashmac using SHA-256
Number HMAC_SHAMD5 Constant to denote a Hashmac using MD5

Constructor

Prototype

Crypto()

Crypto(String provider)

Crypto(String provider, String password)

Description

Create a crypto object and bind it to the given cryptographic service provider. If no provider is defined, then the default provider "BC" will be used.

Arguments

Type Name Description
String provider Name of cryptographic service provider (JCE Provider)
String password Password to activated provider

Exceptions

Name Value Description
GPError GPError.INVALID_ARGUMENTS Too many arguments given
GPError GPError.INVALID_TYPE On or more arguments are not of the expected type

Example


crypto = new Crypto();
assert(crypto != null);

crypto = new Crypto("BC");
assert(crypto != null);


encrypt()

Prototype

ByteString encrypt(Key key, Number mech, ByteString data)

ByteString encrypt(Key key, Number mech, ByteString data, ByteString iv)

Description

Encrypt the plain data using the algorithm defined by mech and the specified key.

The Crypto.RSA mechanism performs a plain RSA encrypt operation with no encoding format.

The Crypto.RSA_ISO9796_2 mechanism performs a plain RSA encrypt operation with no encoding format but according to ISO 9697-2. The result is less than half of the modulus.

The Crypto.PKCS1 mechanism performs a plain RSA encrypt operation with PKCS1 V1.5 encoding format.

The Crypto.OAEP_XXX mechanism performs a plain RSA encrypt operation with PKCS1 V2.1 OEAP encoding format using the selected message digest algorithm.

If the algorithm requires an initialisation vector, then the additional argument iv must be specified (DES_CBC, AES_CBC or AES_CTR).

Arguments

Type Name Description
Key key Key object representing the key
Key mech Algorithm to be used to decryption. Must be one of Crypto.DES_CBC, Crypto.DES_ECB, Crypto.AES_CBC, Crypto.AES_ECB, Crypto.AES_ECB or Crypto.RSA.
ByteString data The data to be encrypted

Return

ByteString Returns the plain text value

Exceptions

Name Value Description
GPError GPError.ARGUMENTS_MISSING Too few arguments in call
GPError GPError.INVALID_ARGUMENTS Too many arguments in call
GPError GPError.INVALID_TYPE Type of argument is invalid for method invocation
GPError GPError.INVALID_MECH The mechanism is invalid

Example


// Instantiate crypto service
var crypto = new Crypto();

// Define 3 different single DES key values
var key1 = new ByteString("7CA110454A1A6E57", HEX);
var key2 = new ByteString("0131D9619DC1376E", HEX);
var key3 = new ByteString("9DC1376E0131D961", HEX);

var plain = new ByteString("01A1D6D039776742", HEX);
var cipher;
var result;

// Create three single DES keys, a double DES key and a triple DES key
var deskey1 = new Key();
deskey1.setComponent(Key.DES, key1);

var deskey2 = new Key();
deskey2.setComponent(Key.DES, key2);

var deskey3 = new Key();
deskey3.setComponent(Key.DES, key3);

var des2key = new Key();
des2key.setComponent(Key.DES, key1.concat(key2));

var des3key = new Key();
des3key.setComponent(Key.DES, key1.concat(key2).concat(key3));


// Single DES ECB encrypt
cipher = new ByteString("690F5B0D9A26939B", HEX);

result = crypto.encrypt(deskey1, Crypto.DES_ECB, plain);
assert(result.equals(cipher));


// Single DES ECB decrypt
result = crypto.decrypt(deskey1, Crypto.DES_ECB, cipher);
assert(result.equals(plain));


// Double DES ECB encrypt
cipher = plain;
cipher = crypto.encrypt(deskey1, Crypto.DES_ECB, cipher);
cipher = crypto.decrypt(deskey2, Crypto.DES_ECB, cipher);
cipher = crypto.encrypt(deskey1, Crypto.DES_ECB, cipher);

result = crypto.encrypt(des2key, Crypto.DES_ECB, plain);
assert(result.equals(cipher));


// Double DES ECB decrypt
result = crypto.decrypt(des2key, Crypto.DES_ECB, cipher);
assert(result.equals(plain));


// Triple DES ECB encrypt
cipher = plain;
cipher = crypto.encrypt(deskey1, Crypto.DES_ECB, cipher);
cipher = crypto.decrypt(deskey2, Crypto.DES_ECB, cipher);
cipher = crypto.encrypt(deskey3, Crypto.DES_ECB, cipher);

result = crypto.encrypt(des3key, Crypto.DES_ECB, plain);
assert(result.equals(cipher));


// Triple DES ECB decrypt
result = crypto.decrypt(des3key, Crypto.DES_ECB, cipher);
assert(result.equals(plain));


// Single DES CBC encrypt
var plain = new ByteString("01A1D6D0397767423977674201A1D6D0", HEX);
var iv = new ByteString("59D9839733B8455D", HEX);
var v;

v = plain.bytes(0, 8);
v = v.xor(iv);
v = crypto.encrypt(deskey1, Crypto.DES_ECB, v);
cipher = v;

v = plain.bytes(8, 8);
v = cipher.xor(v);
v = crypto.encrypt(deskey1, Crypto.DES_ECB, v);
cipher = cipher.concat(v);

result = crypto.encrypt(deskey1, Crypto.DES_CBC, plain, iv);
assert(result.equals(cipher));


// Single DES CBC decrypt
result = crypto.decrypt(deskey1, Crypto.DES_CBC, cipher, iv);
assert(result.equals(plain));


// Encrypt and decrypt with AES key

var key = new Key();

// Make key a 128 bit AES key
key.setComponent(Key.AES, new ByteString("000102030405060708090a0b0c0d0e0f", HEX));
var plain = new ByteString("00112233445566778899aabbccddeeff", HEX);
var cipher = new ByteString("69c4e0d86a7b0430d8cdb78070b4c55a", HEX);

var result = crypto.encrypt(key, Crypto.AES_ECB, plain);
assert(cipher.equals(result));

var result = crypto.decrypt(key, Crypto.AES_ECB, cipher);
assert(plain.equals(result));


// Make key a 192 bit AES key
key.setComponent(Key.AES, new ByteString(
            "000102030405060708090a0b0c0d0e0f1011121314151617", HEX));
var plain = new ByteString("00112233445566778899aabbccddeeff", HEX);
var cipher = new ByteString("dda97ca4864cdfe06eaf70a0ec0d7191", HEX);
var result = crypto.encrypt(key, Crypto.AES_ECB, plain);
assert(cipher.equals(result));

var result = crypto.decrypt(key, Crypto.AES_ECB, cipher);
assert(plain.equals(result));


// Make key a 256 bit AES key
key.setComponent(Key.AES, new ByteString(
            "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", HEX));
var plain = new ByteString("00112233445566778899aabbccddeeff", HEX);
var cipher = new ByteString("8ea2b7ca516745bfeafc49904b496089", HEX);
var result = crypto.encrypt(key, Crypto.AES_ECB, plain);
assert(cipher.equals(result));

var result = crypto.decrypt(key, Crypto.AES_ECB, cipher);
assert(plain.equals(result));


// AES CTR mode
key.setComponent(Key.AES, new ByteString("2b7e151628aed2a6abf7158809cf4f3c", HEX));
var plain = new ByteString("6bc1bee22e409f96e93d7e117393172a", HEX);
var cipher = new ByteString("874d6191b620e3261bef6864990db6ce", HEX);
var iv = new ByteString("F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF", HEX);

var result = crypto.encrypt(key, Crypto.AES_CTR, plain, iv);
assert(cipher.equals(result));

var result = crypto.decrypt(key, Crypto.AES_CTR, cipher, iv);
assert(plain.equals(result));

// Decrypt and encrypt as basically the same in CTR mode
var result = crypto.encrypt(key, Crypto.AES_CTR, cipher, iv);
assert(plain.equals(result));


// RSA encrypt with plain input block

// Make RSA private key from modulus and private exponent

var rsaprkey = new Key();
rsaprkey.setType(Key.PRIVATE);

rsaprkey.setComponent(Key.MODULUS, new ByteString(
            "b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9" +
            "900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", HEX));
rsaprkey.setComponent(Key.EXPONENT, new ByteString(
            "9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae" +
            "79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", HEX));

// Make RSA public key from modulus and public exponent

var rsapukey = new Key();
rsapukey.setType(Key.PUBLIC);
rsapukey.setComponent(Key.MODULUS, new ByteString(
            "b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9"+
            "900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", HEX));
rsapukey.setComponent(Key.EXPONENT, new ByteString("11", HEX));


var inp = new ByteString(
            "2600000000000000000000000000000000000000000000000000000000000000" +
            "0000000000000000000000000000000000000000000000000000000000000000", HEX);
assert(inp.length == 64);

var cipher = crypto.encrypt(rsaprkey, Crypto.RSA, inp);

print(cipher);

var plain = crypto.decrypt(rsapukey, Crypto.RSA, cipher);

print(plain);
assert(plain.equals(inp));


// RSA encrypt with OAEP padding

var inp = new ByteString("Message", ASCII);

var cipher = crypto.encrypt(rsapukey, Crypto.RSA_OAEP, inp);

print(cipher);

var plain = crypto.decrypt(rsaprkey, Crypto.RSA, cipher);

print("Decrypted OAEP block:");
print(plain);

assert(plain.byteAt(0) == 0);

var plain = crypto.decrypt(rsaprkey, Crypto.RSA_OAEP, cipher);
assert(plain.equals(inp));


//RSA encrypt with PKCS#1 V1.5 padding

var inp = new ByteString("Message", ASCII);

var cipher = crypto.encrypt(rsapukey, Crypto.RSA_PKCS1, inp);

print(cipher);

var plain = crypto.decrypt(rsaprkey, Crypto.RSA, cipher);

print("Decrypted PKCS#1 V1.5 block:");
print(plain);

assert(plain.byteAt(0) == 0);
assert(plain.byteAt(1) == 2);

var plain = crypto.decrypt(rsaprkey, Crypto.RSA_PKCS1, cipher);
assert(plain.equals(inp));


// Encrypt and decrypt with RSA primitive using ISO 9796-2 (DINSIG) variant that
// ensures that the numeric value of the output message is less than half of the
// modulus
var inp = new ByteString(
            "260000000000000000000000000000000000000000000000000000000000000" +
            "000000000000000000000000000000000000000000000000000000000000000BC", HEX);
assert(inp.length == 64);

var cipher = crypto.encrypt(rsaprkey, Crypto.RSA_ISO9796_2, inp);

print(cipher);

var plain = crypto.decrypt(rsapukey, Crypto.RSA_ISO9796_2, cipher);
assert(plain.equals(inp));


// Make RSA private key from CRT components stored in key profile

var rsaprkey = new Key("profiles/kp_rsa_private_crt.xml");

// Make RSA public key from modulus and public exponent stored in key profile

var rsapukey = new Key("profiles/kp_rsa_public.xml");

var inp = new ByteString(
            "2600000000000000000000000000000000000000000000000000000000000000" +
            "0000000000000000000000000000000000000000000000000000000000000000", HEX);
assert(inp.length == 64);

var cipher = crypto.encrypt(rsaprkey, Crypto.RSA, inp);

print(cipher);

var plain = crypto.decrypt(rsapukey, Crypto.RSA, cipher);

print(plain);
assert(plain.equals(inp));

decrypt()

Prototype

ByteString decrypt(Key key, Number mech, ByteString data)

ByteString decrypt(Key key, Number mech, ByteString data, ByteString iv)

Description

Decrypt the cipher in data using the algorithm defined by mech and the specified key. If the algorithm requires an initialisation vector, then the additional argument iv must be specified (DES_CBC, AES_CBC or AES_CTR).

The Crypto.RSA mechanism performs a plain RSA decrypt operation with no encoding format.

The Crypto.RSA_ISO9796_2 mechanism performs a plain RSA decrypt operation with no encoding format but according to ISO 9697-2.

The Crypto.PKCS1 mechanism performs a RSA decrypt operation with PKCS1 V1.5 encoding format.

The Crypto.OAEP_XXX mechanism performs a RSA decrypt operation with PKCS1 V2.1 OEAP encoding format using the selected message digest algorithm and MGF1.

This method can also be used to perform an ECDH or an ECDHC with cofactor primitive using a private EC key. The method treats the data as x and y coordinate of the EC public key from the sending party.

The Crypto.ECDH method return as result the x coordinate of the multiplication of the private key value d with the public point Q (result = xof(d * q))

The Crypto.ECDHC method returns as result the x coordinate of the multiplication of the private key value d with the cofactor h and the public point Q (result = xof(d * h * q)). The cofactor is a parameter of the curve.

The Crypto.ECDHP method returns as result the concatenation of the x and y coordinate of the multiplication of the private key value d with the public point Q (result = d * h * q). This method is a non-standard variant, only available with the default BouncyCastle crypto provider.

The ECDH decryption is a basic building block for cipher operations based on ECC. The result of the decrypt operation is a common secret, which can be either used directly as secret key or used as input to a key derivation process.

The Crypto.ECELGAMAL mechanism performs an ElGamal decrypt operation. The cryptogram is an ASN1 sequence containing the EC Points for blinding and cipher. Each point is encoded as public key sequence.

Arguments

Type Name Description
Key key Key object representing the key
Key mech Algorithm to be used to decryption. Must be one of Crypto.DES_CBC, Crypto.DES_ECB, Crypto.AES_CBC, Crypto.AES_ECB, Crypto.AES_CTR, Crypto.RSA, Crypto.ECDH, Crypto.ECDHC, Crypto.ECDHP or Crypto.ECELGAMAL.
ByteString data The cryptogram

Return

ByteString Returns the plain text value

Exceptions

Name Value Description
GPError GPError.ARGUMENTS_MISSING Too few arguments in call
GPError GPError.INVALID_ARGUMENTS Too many arguments in call
GPError GPError.INVALID_TYPE Type of argument is invalid for method invocation
GPError GPError.INVALID_DATA The data or initial vector provided is invalid
GPError GPError.INVALID_MECH The mechanism is invalid

Example


// See encrypt() for a complete example using DES and RSA

// ECDH Generating a shared secret between Bob and Alice to exchange protected messages

var pubKeyBob = new Key();
pubKeyBob.setType(Key.PUBLIC);
pubKeyBob.setComponent(Key.ECC_CURVE_OID, new ByteString("1.2.840.10045.3.1.1", OID));

var priKeyBob = new Key();
priKeyBob.setType(Key.PRIVATE);
priKeyBob.setComponent(Key.ECC_CURVE_OID, new ByteString("1.2.840.10045.3.1.1", OID));
crypto.generateKeyPair(Crypto.EC, pubKeyBob, priKeyBob);

var pubKeyAlice = new Key();
pubKeyAlice.setType(Key.PUBLIC);
pubKeyAlice.setComponent(Key.ECC_CURVE_OID,
                                    new ByteString("1.2.840.10045.3.1.1", OID));

var priKeyAlice = new Key();
priKeyAlice.setType(Key.PRIVATE);
priKeyAlice.setComponent(Key.ECC_CURVE_OID,
                                    new ByteString("1.2.840.10045.3.1.1", OID));
crypto.generateKeyPair(Crypto.EC, pubKeyAlice, priKeyAlice);

var inputBob = pubKeyBob.getComponent(Key.ECC_QX).concat(
                                    pubKeyBob.getComponent(Key.ECC_QY));
var inputAlice = pubKeyAlice.getComponent(Key.ECC_QX).concat(
                                    pubKeyAlice.getComponent(Key.ECC_QY));


var secretAlice = crypto.decrypt(priKeyAlice, Crypto.ECDH, inputBob);
print(secretAlice);

var secretBob = crypto.decrypt(priKeyBob, Crypto.ECDH, inputAlice);
print(secretBob);

assert(secretBob.equals(secretAlice));


var secretAlice = crypto.decrypt(priKeyAlice, Crypto.ECDHC, inputBob);
print(secretAlice);

var secretBob = crypto.decrypt(priKeyBob, Crypto.ECDHC, inputAlice);
print(secretBob);

assert(secretBob.equals(secretAlice));


var secretAlice = crypto.decrypt(priKeyAlice, Crypto.ECDHP, inputBob);
print(secretAlice);

var secretBob = crypto.decrypt(priKeyBob, Crypto.ECDHP, inputAlice);
print(secretBob);

assert(secretBob.equals(secretAlice));

// ElGamal decryption

// Create dummy EC Points representing the ELGamal ciphertext pair of blinding and cipher

var blindingPoint = new Key();
blindingPoint.setType(Key.PUBLIC);
blindingPoint.setComponent(Key.ECC_CURVE_OID, new ByteString("brainpoolP320r1", OID));

var cipherPoint = new Key();
cipherPoint.setType(Key.PUBLIC);
cipherPoint.setComponent(Key.ECC_CURVE_OID, new ByteString("brainpoolP320r1", OID));

var priKey = new Key();
priKey.setType(Key.PRIVATE);

var crypto = new Crypto();
crypto.generateKeyPair(Crypto.EC, blindingPoint, priKey);
crypto.generateKeyPair(Crypto.EC, cipherPoint, priKey);

// Encode ciphertext pair

var blinding = new ByteString("04", HEX);
blinding = blinding.concat(blindingPoint.getComponent(Key.ECC_QX));
blinding = blinding.concat(blindingPoint.getComponent(Key.ECC_QY));

cipher = new ByteString("04", HEX);
cipher = cipher.concat(cipherPoint.getComponent(Key.ECC_QX));
cipher = cipher.concat(cipherPoint.getComponent(Key.ECC_QY));

var seq = new ASN1(ASN1.SEQUENCE);

var pubSeq = new ASN1(0x7F49);
pubSeq.add(new ASN1(0x06, new ByteString("brainpoolP320r1", OID)));
pubSeq.add(new ASN1(0x86, blinding));
seq.add(pubSeq);

var pubSeq = new ASN1(0x7F49);
pubSeq.add(new ASN1(0x06, new ByteString("brainpoolP320r1", OID)));
pubSeq.add(new ASN1(0x86, cipher));
seq.add(pubSeq);

// ElGamal decryption

var c = new Crypto();
var resp = c.decrypt(priKey, Crypto.ECELGAMAL, seq.getBytes());

print(new ASN1(resp));

sign()

Prototype

ByteString sign(Key key, Number mech, ByteString data)

ByteString sign(Key key, Number mech, ByteString data, ByteString iv)

Description

Sign the data provided using the mechanism and key specified. If the algorithms requires an initialisation vector, then it can be provided in the iv argument.

When the Crypto.RSA argument is supplied, then RSA with SHA-1 and PKCS#1 V1.5 encoding is used as signature algorithm. Crypto.RSA has the same effect as Crypto.RSA_SHA1.

When the Crypto.ECDSA argument is supplied, then ECDSA without a hash is used, i.e. the hash value must be provided as input.

A signature created using ECDSA is encoded in an ASN1 SEQUENCE object containing an INTEGER object r and s. See RFC3279 for details.

A method to convert a TLV encoded ECDSA signature into a binary concatenation of the x and y coordinate is provided in the tools/eccutils.js script.

Arguments

Type Name Description
Key key Key reference object to be used for signature generation
Number mech Signature algorithm to be used. Must be one of Crypto.DES_MAC, Crypto.DES_MAC_EMV, Crypto.AES_MAC, Crypto.AES_CMAC, Crypto.RSA* or Crypto.ECDSA*.
ByteString data Input data for signature computation
ByteString iv Initialisation vector for symmetric algorithm

Return

ByteString Signature value

Exceptions

Name Value Description
GPError GPError.ARGUMENTS_MISSING Too few arguments in call
GPError GPError.INVALID_ARGUMENTS Too many arguments in call
GPError GPError.INVALID_TYPE Type of argument is invalid for method invocation
GPError GPError.INVALID_MECH The mechanism is invalid

Example


// Instantiate crypto service
var crypto = new Crypto();


// Define 3 different single DES key values
var key1 = new ByteString("7CA110454A1A6E57", HEX);
var key2 = new ByteString("0131D9619DC1376E", HEX);
var key3 = new ByteString("9DC1376E0131D961", HEX);

var plain = new ByteString("Hello World !!!!", ASCII);
var cipher;
var result;


// Create three single DES keys, a double DES key and a triple DES key
var deskey1 = new Key();
deskey1.setComponent(Key.DES, key1);

var deskey2 = new Key();
deskey2.setComponent(Key.DES, key2);

var deskey3 = new Key();
deskey3.setComponent(Key.DES, key3);

var des2key = new Key();
des2key.setComponent(Key.DES, key1.concat(key2));

var des3key = new Key();
des3key.setComponent(Key.DES, key1.concat(key2).concat(key3));


// Triple DES MAC
cipher = crypto.encrypt(des3key, Crypto.DES_ECB, plain.bytes(0, 8));
cipher = cipher.xor(plain.bytes(8, 8));
cipher = crypto.encrypt(des3key, Crypto.DES_ECB, cipher);

result = crypto.sign(des3key, Crypto.DES_MAC, plain);
assert(result.equals(cipher));


// Triple DES MAC according to EMV (aka Retail MAC)
cipher = crypto.encrypt(deskey1, Crypto.DES_ECB, plain.bytes(0, 8));
cipher = cipher.xor(plain.bytes(8, 8));
cipher = crypto.encrypt(deskey1, Crypto.DES_ECB, cipher);
cipher = crypto.decrypt(deskey2, Crypto.DES_ECB, cipher);
cipher = crypto.encrypt(deskey1, Crypto.DES_ECB, cipher);

result = crypto.sign(des2key, Crypto.DES_MAC_EMV, plain);
assert(result.equals(cipher));


// AES MAC
// Make key a 128 bit AES key
var key = new Key();
key.setComponent(Key.AES, new ByteString("000102030405060708090a0b0c0d0e0f", HEX));
var plain = new ByteString("01234567890123456789012345678901", ASCII);
var cipher = crypto.encrypt(key, Crypto.AES_ECB, plain.bytes(0, 16));
cipher = cipher.xor(plain.bytes(16, 16));
var cipher = crypto.encrypt(key, Crypto.AES_ECB, cipher);

result = crypto.sign(key, Crypto.AES_MAC, plain);
assert(result.equals(cipher));


//AES CMAC
//Make key a 128 bit AES key
var key = new Key();
key.setComponent(Key.AES, new ByteString("2b7e151628aed2a6abf7158809cf4f3c", HEX));
var plain = new ByteString("6bc1bee22e409f96e93d7e117393172aae2d8a571" +
                           "e03ac9c9eb76fac45af8e5130c81c46a35ce411", HEX);
var mac = crypto.sign(key, Crypto.AES_CMAC, plain);
var ref = new ByteString("dfa66747de9ae63030ca32611497c827", HEX);
assert(ref.equals(mac));


// RSA with SHA-1
var rsaprkey = new Key("profiles/kp_rsa_private_crt.xml");
var rsapukey = new Key("profiles/kp_rsa_public.xml");

var message = new ByteString("Hello World !", ASCII);

var signature = crypto.sign(rsaprkey, Crypto.RSA, message);

print("Plain PKCS#1 V1.5 = " + crypto.decrypt(rsapukey, Crypto.RSA, signature));
assert(crypto.verify(rsapukey, Crypto.RSA, message, signature));

// RSA with SHA-224

var signature = crypto.sign(rsaprkey, Crypto.RSA_SHA224, message);

print("Plain PKCS#1 V1.5 = " + crypto.decrypt(rsapukey, Crypto.RSA, signature));
assert(crypto.verify(rsapukey, Crypto.RSA_SHA224, message, signature));

// RSA with SHA-256

var signature = crypto.sign(rsaprkey, Crypto.RSA_SHA256, message);

print("Plain PKCS#1 V1.5 = " + crypto.decrypt(rsapukey, Crypto.RSA, signature));
assert(crypto.verify(rsapukey, Crypto.RSA_SHA256, message, signature));

//RSA with SHA-1 and PSS

var signature = crypto.sign(rsaprkey, Crypto.RSA_PSS_SHA1, message);

print("Plain PSS = " + crypto.decrypt(rsapukey, Crypto.RSA, signature));
assert(crypto.verify(rsapukey, Crypto.RSA_PSS_SHA1, message, signature));


//Create empty public key object and set size
var rsapukey = new Key();
rsapukey.setType(Key.PUBLIC);
rsapukey.setSize(1024);

// Create empty private key object and set size
var rsaprkey = new Key();
rsaprkey.setType(Key.PRIVATE);

// Generate key pair
crypto.generateKeyPair(Crypto.RSA, rsapukey, rsaprkey);

//RSA with SHA-256 and PSS

var signature = crypto.sign(rsaprkey, Crypto.RSA_PSS_SHA256, message);

print("Plain PSS = " + crypto.decrypt(rsapukey, Crypto.RSA, signature));
assert(crypto.verify(rsapukey, Crypto.RSA_PSS_SHA256, message, signature));


// ECDSA Fp with SHA-1
var eccprkey = new Key("profiles/kp_ec_private.xml");
var eccpukey = new Key("profiles/kp_ec_public.xml");

var message = new ByteString("Hello World !", ASCII);

var signature = crypto.sign(eccprkey, Crypto.ECDSA_SHA1, message);

assert(crypto.verify(eccpukey, Crypto.ECDSA_SHA1, message, signature));


/*
// ECDSA F2m with SHA-1
var eccprkey = new Key("profiles/kp_ec_f2m_private.xml");
var eccpukey = new Key("profiles/kp_ec_f2m_public.xml");

var message = new ByteString("Hello World !", ASCII);

var signature = crypto.sign(eccprkey, Crypto.ECDSA_SHA1, message);

assert(crypto.verify(eccpukey, Crypto.ECDSA_SHA1, message, signature));
*/
// see Crypto.generateKeyPair for longer ECC keys


// HMAC
var msg = new ByteString("The quick brown fox jumps over the lazy dog", ASCII);
var key = new Key();
key.setComponent(Key.GENERIC, new ByteString("key", ASCII));

assert(crypto.sign(key, Crypto.HMAC_SHA1, msg).equals(new ByteString("de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9", HEX)));
assert(crypto.sign(key, Crypto.HMAC_SHA256, msg).equals(new ByteString("f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8", HEX)));
assert(crypto.sign(key, Crypto.HMAC_SHA384, msg).equals(new ByteString("D7F4727E2C0B39AE0F1E40CC96F60242D5B7801841CEA6FC592C5D3E1AE50700582A96CF35E1E554995FE4E03381C237", HEX)));
assert(crypto.sign(key, Crypto.HMAC_MD5, msg).equals(new ByteString("80070713463e7749b90c2dc24911e275", HEX)));

verify()

Prototype

Boolean verify(Key key, Number mech, ByteString data, ByteString signature)

Boolean verify(Key key, Number mech, ByteString data, ByteString signature, ByteString iv)

Description

Verify the signature applied to data with the mechanism and key specified

For ECDSA the signature must be TLV encoded as defined in RFC3279.

A method to convert a ECDSA signature encoded as binary concatenation of the x and y coordinate into the TLV format is provided in the tools/eccutils.js script.

Arguments

Type Name Description
Key key Key reference object to be used for signature verificaton
Number mech Verification algorithm to be used. Must be one of Crypto.DES_MAC, Crypto.DES_MAC_EMV, Crypto.AES_MAC, Crypto.RSA* or Crypto.ECDSA*.
ByteString data Input data for signature computation
ByteString signature Signature to be verified
ByteString iv Initialisation vector for symmetric algorithm

Return

Boolean True, if the signature was valid, false otherwise

Exceptions

Name Value Description
GPError GPError.ARGUMENTS_MISSING Too few arguments in call
GPError GPError.INVALID_ARGUMENTS Too many arguments in call
GPError GPError.INVALID_TYPE Type of argument is invalid for method invocation
GPError GPError.INVALID_MECH The mechanism is invalid

Example


// Instantiate crypto service
var crypto = new Crypto();

// Define 3 different single DES key values
var key1 = new ByteString("7CA110454A1A6E57", HEX);
var key2 = new ByteString("0131D9619DC1376E", HEX);
var key3 = new ByteString("9DC1376E0131D961", HEX);

var plain = new ByteString("Hello World !!!!", ASCII);
var cipher;
var result;

// Create three single DES keys, a double DES key and a triple DES key
var des1key = new Key();
des1key.setComponent(Key.DES, key1);

var des2key = new Key();
des2key.setComponent(Key.DES, key1.concat(key2));

var des3key = new Key();
des3key.setComponent(Key.DES, key1.concat(key2).concat(key3));

// Single DES MAC
result = crypto.sign(des1key, Crypto.DES_MAC, plain);
var ok = crypto.verify(des1key, Crypto.DES_MAC, plain, result);
assert(ok);

// Triple DES MAC
result = crypto.sign(des3key, Crypto.DES_MAC, plain);
var ok = crypto.verify(des3key, Crypto.DES_MAC, plain, result);
assert(ok);

// Triple DES MAC according to EMV (aka Retail MAC)
result = crypto.sign(des2key, Crypto.DES_MAC_EMV, plain);
var ok = crypto.verify(des2key, Crypto.DES_MAC_EMV, plain, result);
assert(ok);


// AES MAC
// Make key a 128 bit AES key
var key = new Key();
key.setComponent(Key.AES, new ByteString("000102030405060708090a0b0c0d0e0f", HEX));
var plain = new ByteString("01234567890123456789012345678901", ASCII);

result = crypto.sign(key, Crypto.AES_MAC, plain);
var ok = crypto.verify(key, Crypto.AES_MAC, plain, result);
assert(ok);


//AES CMAC
//Make key a 128 bit AES key
var key = new Key();
key.setComponent(Key.AES, new ByteString("000102030405060708090a0b0c0d0e0f", HEX));
var plain = new ByteString("01234567890123456789012345678901", ASCII);

result = crypto.sign(key, Crypto.AES_CMAC, plain);
var ok = crypto.verify(key, Crypto.AES_CMAC, plain, result);
assert(ok);


// RSA

var cert = new X509("root.cer");
var ncert = cert.getNative();

var message = ncert.getTBSCertificate();
var signature = ncert.getSignature();
var key = cert.getPublicKey();

assert(crypto.verify(key, Crypto.RSA, message, signature));


// ECDSA

var cert = new X509("ecdsacert.cer");
var key = cert.getPublicKey();

var message = new ByteString("Hello World", ASCII);

// Be carefull if the most significant bit of r or s is 1. In that case you need
// to add a 00 to prevent interpretation as negative integer
var r = new ByteString("06CF31FCE556DC74F7B0B3061E47300CC11B3F5BFD01976A", HEX);
var s = new ByteString("33F8D70EF472EEC8489CAA705837FA5F0156BF70CFD371FD", HEX);

var signature = new ASN1(ASN1.SEQUENCE);
signature.add(new ASN1(ASN1.INTEGER, r));
signature.add(new ASN1(ASN1.INTEGER, s));

assert(crypto.verify(key, Crypto.ECDSA_SHA1, message, signature.getBytes()));


deriveKey()

Prototype

void deriveKey (Key masterKey, Number mech, ByteString data, Key derivedKey)

Description

Derive key from a master key using the mechanism specified and data for diversification.

The resulting DES key is parity adjusted, so that the number of 1 bits in each byte of the key value is odd.

This method can be used to calculate a public key (point) by multiplying the point with a skalar value and adding a second point (EC_MULTIPLY_ADD). This method is used in the PACE protocol to determine a temporary generator point using the formular G' = s * G + P. The variant EC_MULTIPLY_ADD performs a substration instead of an addition.

The parameter G is the point from the masterKey, the point P is provided by the public key value in derivedKey and the skalar value s is provided in the argument data. The result is stored as public key value in derivedKey.

If the public point P is undefined, then only the skalar multiplication is performed. If the argument data is null, then only the point addition is performed.

Arguments

Type Name Description
Key masterKey Master key to use for derivation algorithm
Number mech Derivation algorithm. Must be Crypto.DES_CBC or Crypto.DES_ECB.
ByteString data Derivation data. The length of the derivation data determines the length of the resulting key (8/16 or 24 Bytes). For method EC_MULTIPLY_ADD the argument determines the skalar value. If data is null, then the skalar multiplication is skipped and only the point addition is performed.
Key derivedKey The key object to store the resulting key value.

Return

None The method does not return data

Exceptions

Name Value Description
GPError GPError.ARGUMENTS_MISSING Too few arguments in call
GPError GPError.INVALID_ARGUMENTS Too many arguments in call
GPError GPError.INVALID_TYPE Type of argument is invalid for method invocation

Example


// Instantiate crypto service
var crypto = new Crypto();

// Create a single DES key, a double DES key and a triple DES key
var des1key = new Key("profiles/kp_single_des_1.xml");
var des2key = new Key("profiles/kp_double_des.xml");
var des3key = new Key("profiles/kp_triple_des.xml");

// Define derivation parameter
var dpara8  = new ByteString("0102030405060708", HEX);
var dpara16 = new ByteString("01020304050607081020304050607080", HEX);
var dpara24 = new ByteString("010203040506070810203040506070801122334455667788", HEX);

var derivedKey = new Key();
var reference;

// Derive a single DES key
crypto.deriveKey(des1key, Crypto.DES_ECB, dpara8, derivedKey);
reference = crypto.encrypt(des1key, Crypto.DES_ECB, dpara8);
assert(keyequals(derivedKey.getComponent(Key.DES), reference));

// Derive a double DES key
crypto.deriveKey(des1key, Crypto.DES_ECB, dpara16, derivedKey);
reference = crypto.encrypt(des1key, Crypto.DES_ECB, dpara16);
assert(keyequals(derivedKey.getComponent(Key.DES), reference));

// Derive a triple DES key
crypto.deriveKey(des1key, Crypto.DES_ECB, dpara24, derivedKey);
reference = crypto.encrypt(des1key, Crypto.DES_ECB, dpara24);
assert(keyequals(derivedKey.getComponent(Key.DES), reference));

// Derive a single DES key
crypto.deriveKey(des2key, Crypto.DES_ECB, dpara8, derivedKey);
reference = crypto.encrypt(des2key, Crypto.DES_ECB, dpara8);
assert(keyequals(derivedKey.getComponent(Key.DES), reference));

// Derive a double DES key
crypto.deriveKey(des2key, Crypto.DES_ECB, dpara16, derivedKey);
reference = crypto.encrypt(des2key, Crypto.DES_ECB, dpara16);
assert(keyequals(derivedKey.getComponent(Key.DES), reference));

// Derive a triple DES key
crypto.deriveKey(des2key, Crypto.DES_ECB, dpara24, derivedKey);
reference = crypto.encrypt(des2key, Crypto.DES_ECB, dpara24);
assert(keyequals(derivedKey.getComponent(Key.DES), reference));

// Derive a single DES key
crypto.deriveKey(des3key, Crypto.DES_ECB, dpara8, derivedKey);
reference = crypto.encrypt(des3key, Crypto.DES_ECB, dpara8);
assert(keyequals(derivedKey.getComponent(Key.DES), reference));

// Derive a double DES key
crypto.deriveKey(des3key, Crypto.DES_ECB, dpara16, derivedKey);
reference = crypto.encrypt(des3key, Crypto.DES_ECB, dpara16);
assert(keyequals(derivedKey.getComponent(Key.DES), reference));

// Derive a triple DES key
crypto.deriveKey(des3key, Crypto.DES_ECB, dpara24, derivedKey);
reference = crypto.encrypt(des3key, Crypto.DES_ECB, dpara24);
assert(keyequals(derivedKey.getComponent(Key.DES), reference));


var iv = new ByteString("0000000000000000", HEX);

// Derive a single DES key
crypto.deriveKey(des1key, Crypto.DES_CBC, dpara8, derivedKey);
reference = crypto.encrypt(des1key, Crypto.DES_CBC, dpara8, iv);
assert(keyequals(derivedKey.getComponent(Key.DES), reference));

// Derive a double DES key
crypto.deriveKey(des1key, Crypto.DES_CBC, dpara16, derivedKey);
reference = crypto.encrypt(des1key, Crypto.DES_CBC, dpara16, iv);
assert(keyequals(derivedKey.getComponent(Key.DES), reference));

// Derive a triple DES key
crypto.deriveKey(des1key, Crypto.DES_CBC, dpara24, derivedKey);
reference = crypto.encrypt(des1key, Crypto.DES_CBC, dpara24, iv);
assert(keyequals(derivedKey.getComponent(Key.DES), reference));

// Derive a single DES key
crypto.deriveKey(des2key, Crypto.DES_CBC, dpara8, derivedKey);
reference = crypto.encrypt(des2key, Crypto.DES_CBC, dpara8, iv);
assert(keyequals(derivedKey.getComponent(Key.DES), reference));

// Derive a double DES key
crypto.deriveKey(des2key, Crypto.DES_CBC, dpara16, derivedKey);
reference = crypto.encrypt(des2key, Crypto.DES_CBC, dpara16, iv);
assert(keyequals(derivedKey.getComponent(Key.DES), reference));

// Derive a triple DES key
crypto.deriveKey(des2key, Crypto.DES_CBC, dpara24, derivedKey);
reference = crypto.encrypt(des2key, Crypto.DES_CBC, dpara24, iv);
assert(keyequals(derivedKey.getComponent(Key.DES), reference));

// Derive a single DES key
crypto.deriveKey(des3key, Crypto.DES_CBC, dpara8, derivedKey);
reference = crypto.encrypt(des3key, Crypto.DES_CBC, dpara8, iv);
assert(keyequals(derivedKey.getComponent(Key.DES), reference));

// Derive a double DES key
crypto.deriveKey(des3key, Crypto.DES_CBC, dpara16, derivedKey);
reference = crypto.encrypt(des3key, Crypto.DES_CBC, dpara16, iv);
assert(keyequals(derivedKey.getComponent(Key.DES), reference));

// Derive a triple DES key
crypto.deriveKey(des3key, Crypto.DES_CBC, dpara24, derivedKey);
reference = crypto.encrypt(des3key, Crypto.DES_CBC, dpara24, iv);
assert(keyequals(derivedKey.getComponent(Key.DES), reference));

// Calculate a new point by multiplying G with skalar s and adding P.
// This method is used to implement PACE as defined by the
// Extended Access Control 2.x specification

var P = new Key();
P.setComponent(Key.ECC_CURVE_OID, new ByteString("1.3.36.3.3.2.8.1.1.5", OID));
P.setComponent(Key.ECC_QX, new ByteString(
            "A99D861875FDCAF2406B6CE4423C1FE2EB4396A8636CF039C723DDEE", HEX));
P.setComponent(Key.ECC_QY, new ByteString(
            "634A17EA9EC0DC8611EF51CDF46E8247C64A2B9F8ECFCE53B690ADC0", HEX));

var G = new Key();
G.setComponent(Key.ECC_CURVE_OID, new ByteString("1.3.36.3.3.2.8.1.1.5", OID));
G.setComponent(Key.ECC_QX, P.getComponent(Key.ECC_GX));
G.setComponent(Key.ECC_QY, P.getComponent(Key.ECC_GY));

var s = new ByteString("3924D2D1E31CE13C", HEX);

// Calculate G' = s * G + P
crypto.deriveKey(G, Crypto.EC_MULTIPLY_ADD, s, P);

// This method does not change the generator point directly, but the public key point
// in the derived key. For PACE the public key point ECC_QX/Y must be copied
// to ECC_GX/Y !
assert(P.getComponent(Key.ECC_QX).toString(HEX) ==
            "992042B9D17CBDFA5915EAE4292E62A3F6582071622371F47C2C717E");
assert(P.getComponent(Key.ECC_QY).toString(HEX) ==
            "16FC907BD3D87C7F45F56533DE33909A3A1D1E25487615284BC741E7");


var G1 = new Key();
G1.setType(Key.PUBLIC);
G1.setComponent(Key.ECC_CURVE_OID, new ByteString("1.3.36.3.3.2.8.1.1.5", OID));

var G = new Key();
G.setComponent(Key.ECC_CURVE_OID, new ByteString("1.3.36.3.3.2.8.1.1.5", OID));
G.setComponent(Key.ECC_QX, P.getComponent(Key.ECC_GX));
G.setComponent(Key.ECC_QY, P.getComponent(Key.ECC_GY));

var s = new ByteString("3924D2D1E31CE13C", HEX);

// Calculate G'' = s * G
crypto.deriveKey(G, Crypto.EC_MULTIPLY_ADD, s, G1);

var P = new Key();
P.setComponent(Key.ECC_CURVE_OID, new ByteString("1.3.36.3.3.2.8.1.1.5", OID));
P.setComponent(Key.ECC_QX, new ByteString(
            "A99D861875FDCAF2406B6CE4423C1FE2EB4396A8636CF039C723DDEE", HEX));
P.setComponent(Key.ECC_QY, new ByteString(
            "634A17EA9EC0DC8611EF51CDF46E8247C64A2B9F8ECFCE53B690ADC0", HEX));

//Calculate G'' = G'' + P
crypto.deriveKey(G1, Crypto.EC_MULTIPLY_ADD, null, P);

assert(P.getComponent(Key.ECC_QX).toString(HEX) ==
            "992042B9D17CBDFA5915EAE4292E62A3F6582071622371F47C2C717E");
assert(P.getComponent(Key.ECC_QY).toString(HEX) ==
            "16FC907BD3D87C7F45F56533DE33909A3A1D1E25487615284BC741E7");

digest()

Prototype

ByteString digest(Number mech, ByteString data, Number iterations)

Description

Calculate message digest for data using hash algorithm specified in argument mech.

Arguments

Type Name Description
Number mech Digest algorithm. Must be either Crypto.SHA_x or Crypto.MD5.
ByteString data Message to process
Number iterations Optional parameter defining the number of iterations to perform with the previous result as input for the next round (Default 1). This is an extension to the GP specification.

Return

ByteString Message digest for given data

Exceptions

Name Value Description
GPError GPError.ARGUMENTS_MISSING Too few arguments in call
GPError GPError.INVALID_ARGUMENTS Too many arguments in call
GPError GPError.INVALID_TYPE Type of argument is invalid for method invocation
GPError GPError.INVALID_MECH The mechanism is invalid

Example


var message = new ByteString("Hello World", ASCII);
var hash = crypto.digest(Crypto.SHA_1, message);
print("SHA1: " + hash);
var hash = crypto.digest(Crypto.MD5, message);
print("MD5: " + hash);


var message = new ByteString("", HEX);
var ref = new ByteString("da39a3ee5e6b4b0d3255bfef95601890afd80709", HEX);
var hash = crypto.digest(Crypto.SHA_1, message);
assert(ref.equals(hash));

var message = new ByteString("61", HEX);
var ref = new ByteString("86f7e437faa5a7fce15d1ddcb9eaeaea377667b8", HEX);
var hash = crypto.digest(Crypto.SHA_1, message);
assert(ref.equals(hash));

var message = new ByteString("616263", HEX);
var ref = new ByteString("a9993e364706816aba3e25717850c26c9cd0d89d", HEX);
var hash = crypto.digest(Crypto.SHA_1, message);
assert(ref.equals(hash));

var message = new ByteString(
            "6162636465666768696a6b6c6d6e6f707172737475767778797a", HEX);
var ref = new ByteString("32d10c7b8cf96570ca04ce37f2a19d84240d3a89", HEX);
var hash = crypto.digest(Crypto.SHA_1, message);
assert(ref.equals(hash));

var message = new ByteString("616263", HEX);
var ref = new ByteString(
            "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7", HEX);
var hash = crypto.digest(Crypto.SHA_224, message);
assert(ref.equals(hash));

var message = new ByteString("616263", HEX);
var ref = new ByteString(
            "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", HEX);
var hash = crypto.digest(Crypto.SHA_256, message);
assert(ref.equals(hash));

var message = new ByteString("616263", HEX);
var ref = new ByteString(
            "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded163" +
            "1a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7", HEX);
var hash = crypto.digest(Crypto.SHA_384, message);
assert(ref.equals(hash));

var message = new ByteString("616263", HEX);
var ref = new ByteString(
            "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
            "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f", HEX);
var hash = crypto.digest(Crypto.SHA_512, message);
assert(ref.equals(hash));



var message = new ByteString("", HEX);
var ref = new ByteString("d41d8cd98f00b204e9800998ecf8427e", HEX);
var hash = crypto.digest(Crypto.MD5, message);
assert(ref.equals(hash));

var message = new ByteString("61", HEX);
var ref = new ByteString("0cc175b9c0f1b6a831c399e269772661", HEX);
var hash = crypto.digest(Crypto.MD5, message);
assert(ref.equals(hash));

var message = new ByteString("616263", HEX);
var ref = new ByteString("900150983cd24fb0d6963f7d28e17f72", HEX);
var hash = crypto.digest(Crypto.MD5, message);
assert(ref.equals(hash));

var message = new ByteString(
            "6162636465666768696a6b6c6d6e6f707172737475767778797a", HEX);
var ref = new ByteString("c3fcd3d76192e4007dfb496cca67e13b", HEX);
var hash = crypto.digest(Crypto.MD5, message);
assert(ref.equals(hash));

generateKeyPair()

Prototype

Void generateKeyPair(Number mech, Key pubKey, Key priKey)

Description

Generate an asymmetric key pair according to the specification from the public key object.

For RSA key, the key size must be defined using the Key.setSize() method.

For EC keys, the curve parameter must be set using the setComponent() method.

Arguments

Type Name Description
Number mech Type of key pair, must be either Crypto.RSA or Crypto.EC.

Return

Void The method does not return a value

Exceptions

Name Value Description
GPError GPError.ARGUMENTS_MISSING Too few arguments in call
GPError GPError.INVALID_ARGUMENTS Too many arguments in call
GPError GPError.INVALID_TYPE Type of argument is invalid for method invocation
GPError GPError.INVALID_DATA The type of key is invalid

Example


// RSA Example - Generate a 1024 bit RSA key pair

// Create empty public key object and set size
var pubKey = new Key();
pubKey.setType(Key.PUBLIC);
pubKey.setSize(1024);

// Create empty private key object and set size
var priKey = new Key();
priKey.setType(Key.PRIVATE);

// Generate key pair
crypto.generateKeyPair(Crypto.RSA, pubKey, priKey);

// Extract key components...
var modulus = pubKey.getComponent(Key.MODULUS);
print("RSA Modulus:");
print(modulus);

var publicexponent = pubKey.getComponent(Key.EXPONENT);
print("RSA Public Exponent:");
print(publicexponent);

print("CRT prime P");
var crt_p = priKey.getComponent(Key.CRT_P);
print(crt_p);

print("CRT prime Q");
var crt_q = priKey.getComponent(Key.CRT_Q);
print(crt_q);

print("CRT prime exponent P");
var crt_dp = priKey.getComponent(Key.CRT_DP1);
print(crt_dp);

print("CRT prime exponent Q");
var crt_dq = priKey.getComponent(Key.CRT_DQ1);
print(crt_dq);

print("CRT coefficient pq");
var crt_pq = priKey.getComponent(Key.CRT_PQ);
print(crt_pq);

// ... and reassemble in newly created key
var pubKey = new Key();
pubKey.setType(Key.PUBLIC);
pubKey.setComponent(Key.MODULUS, modulus);
pubKey.setComponent(Key.EXPONENT, publicexponent);

var priKey = new Key();
priKey.setType(Key.PRIVATE);
priKey.setComponent(Key.CRT_P, crt_p);
priKey.setComponent(Key.CRT_Q, crt_q);
priKey.setComponent(Key.CRT_DP1, crt_dp);
priKey.setComponent(Key.CRT_DQ1, crt_dq);
priKey.setComponent(Key.CRT_PQ, crt_pq);

// Verify that keys still work
var message = new ByteString("Hello World", ASCII);

var cryptogram = crypto.sign(priKey, Crypto.RSA, message);

assert(crypto.verify(pubKey, Crypto.RSA, message, cryptogram));

// ECC Example - Generate a 192 bit key pair over the prime192v1 curve

// Create empty public key object
var pubKey = new Key();
pubKey.setType(Key.PUBLIC);

// Select prime192v1 curve using it's object identifier
pubKey.setComponent(Key.ECC_CURVE_OID, new ByteString("1.2.840.10045.3.1.1", OID));

// Print out the curve parameter selected
print("Curve Fp:");
print(pubKey.getComponent(Key.ECC_P));
print("Curve A:");
print(pubKey.getComponent(Key.ECC_A));
print("Curve B:");
print(pubKey.getComponent(Key.ECC_B));
print("Parameter Gx:");
print(pubKey.getComponent(Key.ECC_GX));
print("Parameter Gy:");
print(pubKey.getComponent(Key.ECC_GY));
print("Parameter N:");
print(pubKey.getComponent(Key.ECC_N));
print("Parameter H:");
print(pubKey.getComponent(Key.ECC_H));

// Create empty private key object
var priKey = new Key();
priKey.setType(Key.PRIVATE);

// Generate key pair
crypto.generateKeyPair(Crypto.EC, pubKey, priKey);

// Extract and print private and public key values
print("Public Key Qx:");
var qx = pubKey.getComponent(Key.ECC_QX);
assert(qx.length == 24);
print(qx.toString(HEX));
var qy = pubKey.getComponent(Key.ECC_QY);
assert(qy.length == 24);
print("Public Key Qy:");
print(qy.toString(HEX));
var d = priKey.getComponent(Key.ECC_D);
print("Private Key D:");
print(d.toString(HEX));

// Reassemble keys
var pubKey = new Key();
pubKey.setType(Key.PUBLIC);
pubKey.setComponent(Key.ECC_QX, qx);
pubKey.setComponent(Key.ECC_QY, qy);
pubKey.setComponent(Key.ECC_CURVE_OID, new ByteString("1.2.840.10045.3.1.1", OID));

var priKey = new Key();
priKey.setComponent(Key.ECC_D, d);
priKey.setComponent(Key.ECC_CURVE_OID, new ByteString("1.2.840.10045.3.1.1", OID));

// Test keys to verify integrity
var message = new ByteString("Hello World", ASCII);

var cryptogram = crypto.sign(priKey, Crypto.ECDSA_SHA1, message);

assert(crypto.verify(pubKey, Crypto.ECDSA_SHA1, message, cryptogram));


// ECC Example - Generate a 571 bit key pair over the secp521r1 curve

// Create empty public key object
var pubKey = new Key();
pubKey.setType(Key.PUBLIC);

// Select secp521r1 curve using it's object identifier
pubKey.setComponent(Key.ECC_CURVE_OID, new ByteString("1.3.132.0.35", OID));

// Print out the curve parameter selected
print("Curve P:");
print(pubKey.getComponent(Key.ECC_P));
print("Curve A:");
print(pubKey.getComponent(Key.ECC_A));
print("Curve B:");
print(pubKey.getComponent(Key.ECC_B));
print("Parameter Gx:");
print(pubKey.getComponent(Key.ECC_GX));
print("Parameter Gy:");
print(pubKey.getComponent(Key.ECC_GY));
print("Parameter N:");
print(pubKey.getComponent(Key.ECC_N));
print("Parameter H:");
print(pubKey.getComponent(Key.ECC_H));

// Create empty private key object
var priKey = new Key();
priKey.setType(Key.PRIVATE);

// Generate key pair
crypto.generateKeyPair(Crypto.EC, pubKey, priKey);

// Extract and print private and public key values
print("Public Key Qx:");
var qx = pubKey.getComponent(Key.ECC_QX);
assert(qx.length == 66);
print(qx.toString(HEX));
var qy = pubKey.getComponent(Key.ECC_QY);
assert(qy.length == 66);
print("Public Key Qy:");
print(qy.toString(HEX));
var d = priKey.getComponent(Key.ECC_D);
print("Private Key D:");
print(d.toString(HEX));

// Reassemble keys
var pubKey = new Key();
pubKey.setType(Key.PUBLIC);
pubKey.setComponent(Key.ECC_QX, qx);
pubKey.setComponent(Key.ECC_QY, qy);
pubKey.setComponent(Key.ECC_CURVE_OID, new ByteString("1.3.132.0.35", OID));

var priKey = new Key();
priKey.setComponent(Key.ECC_D, d);
priKey.setComponent(Key.ECC_CURVE_OID, new ByteString("1.3.132.0.35", OID));

// Test keys to verify integrity
var message = new ByteString("Hello World", ASCII);

var cryptogram = crypto.sign(priKey, Crypto.ECDSA_SHA512, message);

assert(crypto.verify(pubKey, Crypto.ECDSA_SHA512, message, cryptogram));


var pubKey = new Key();
pubKey.setType(Key.PUBLIC);
// Select secp224k1 curve using it's object identifier
pubKey.setComponent(Key.ECC_CURVE_OID, new ByteString("secp224k1", OID));

print("Curve P:");
print(pubKey.getComponent(Key.ECC_P));
print("Curve A:");
print(pubKey.getComponent(Key.ECC_A));
print("Curve B:");
print(pubKey.getComponent(Key.ECC_B));
print("Parameter Gx:");
print(pubKey.getComponent(Key.ECC_GX));
print("Parameter Gy:");
print(pubKey.getComponent(Key.ECC_GY));
print("Parameter N:");
print(pubKey.getComponent(Key.ECC_N));
print("Parameter H:");
print(pubKey.getComponent(Key.ECC_H));

// Create empty private key object
var priKey = new Key();
priKey.setType(Key.PRIVATE);

// Generate key pair
crypto.generateKeyPair(Crypto.EC, pubKey, priKey);

// Test keys to verify integrity
var message = new ByteString("Hello World", ASCII);

var cryptogram = crypto.sign(priKey, Crypto.ECDSA_SHA224, message);

assert(crypto.verify(pubKey, Crypto.ECDSA_SHA224, message, cryptogram));

generateRandom()

Prototype

ByteString generateRandom(Number length)

Description

Generate a ByteString of given length with random data

Arguments

Type Name Description
Number length Number of random bytes

Return

ByteString Returns length bytes of random data

Exceptions

Name Value Description
GPError GPError.ARGUMENTS_MISSING Too few arguments in call
GPError GPError.INVALID_ARGUMENTS Too many arguments in call
GPError GPError.INVALID_TYPE Type of argument is invalid for method invocation

Example


var val1 = crypto.generateRandom(10);
assert(val1.length == 10);

var val2 = crypto.generateRandom(10);
assert(val2.length == 10);

assert(val1 != val2);