Преглед на файлове

HPCC-12788 Create new Std library for cryptographic functions

Introduce a new cryptographic STD library plugin to perform hashing, symmetric
encryption/decryption, and PKI encryption/decryption/digital signing/signature
verification. This plugin will be part of the STD library and available via
ECL IDE, the ECLWatch Playground, and command line ECL.

Signed-off-by: Russ Whitehead <william.whitehead@lexisnexisrisk.com>
Russ Whitehead преди 5 години
родител
ревизия
936e3acf30

+ 1 - 0
ecllibrary/std/CMakeLists.txt

@@ -22,6 +22,7 @@ set(
     Audit.ecl
     BLAS.ecl
     BundleBase.ecl
+    Crypto.ecl
     Date.ecl
     File.ecl
     Math.ecl

+ 212 - 0
ecllibrary/std/Crypto.ecl

@@ -0,0 +1,212 @@
+/*##############################################################################
+## HPCC SYSTEMS software Copyright (C) 2019 HPCC Systems®.  All rights reserved.
+############################################################################## */
+
+
+EXPORT Crypto := MODULE
+
+
+IMPORT lib_cryptolib;
+
+
+/**
+ * Returns set of supported Hash Algorithms
+ *
+ * @return        SET OF STRING containing all supported Hash Algorithms
+ */
+EXPORT SET OF STRING SupportedHashAlgorithms() := lib_cryptolib.CryptoLib.SupportedHashAlgorithms();
+	
+
+/**
+ * Returns set of supported CipherAlgorithms
+ *
+ * @return        SET OF STRING containing all supported Cipher Algorithms
+ */
+EXPORT SET OF STRING SupportedSymmetricCipherAlgorithms() := lib_cryptolib.CryptoLib.SupportedSymmetricCipherAlgorithms();
+
+
+/**
+ * Returns set of supported Public Key Algorithms
+ *
+ * @return        SET OF STRING containing all supported Public Key Algorithms
+ */
+EXPORT SET OF STRING SupportedPublicKeyAlgorithms() := lib_cryptolib.CryptoLib.SupportedPublicKeyAlgorithms();
+
+
+
+/**
+ * Hashing module that can be instantiated by an ECL caller.  Data can be hashed
+ * with functionality here
+ *
+ * @param   hashAlgorithm  Hashing algorithm to be used, as returned by SupportedHashAlgorithms()
+ * @return                 Hashing object reference
+ */
+EXPORT Hashing(VARSTRING hashAlgorithm) := MODULE
+    /**
+     * Create a hash of the given data, using a hash algorithm that
+     * was returned by SupportedHashAlgorithms()
+     *
+     * @param   inputData      Data to be hashed
+     * @return                 Hashed contents
+     */
+    EXPORT DATA Hash(DATA inputData) := FUNCTION
+        return lib_cryptolib.CryptoLib.Hash(hashAlgorithm, inputData);
+    END;
+END; // Hashing module
+
+//-----
+
+/**
+ * Encryption module that can be instantiated by an ECL caller
+ * to perform symmetric encryption/decryption
+ *
+ * @param   algorithm      Symmetric algorithm to be used, as returned by SupportedSymmetricCipherAlgorithms()
+ * @param   passphrase     Passphrase to be used for encryption/encryption
+ * @return                 Encryption object reference
+ */
+EXPORT SymmetricEncryption(VARSTRING algorithm, VARSTRING passphrase) := MODULE
+    /**
+     * Encrypt the given data, using the specified passphrase and symmetric cipher
+     * algorithm that was returned by SupportedSymmetricCipherAlgorithms()
+     *
+     * @param   inputData  Contents to be encrypted
+     * @return             Encrypted cipher
+     */
+    EXPORT DATA Encrypt(DATA inputData) := FUNCTION
+        RETURN lib_cryptolib.CryptoLib.SymmetricEncrypt( algorithm, passphrase, inputData );
+    END;
+    
+    /**
+     * Decrypt the given cipher, using the specified passphrase and symmetric cipher
+     * algorithm that was returned by SupportedSymmetricCipherAlgorithms()
+     *
+     * @param   encryptedData  Contents to be decrypted
+     * @return                 Decrypted data
+     */
+    EXPORT DATA Decrypt(DATA encryptedData) := FUNCTION
+        RETURN lib_cryptolib.CryptoLib.SymmetricDecrypt( algorithm, passphrase, encryptedData );
+    END;
+END; // SymmetricEncryption module
+
+
+
+
+/**
+ * Encryption module that can be instantiated by an ECL caller
+ * to perform asymmetric encryption/decryption/digital signing/signature verification
+ *
+ * @param   pkAlgorithm    ASymmetric algorithm to be used, as returned by SupportedPublicKeyAlgorithms()
+ * @param   publicKeyFile  File specification of PEM formatted public key file
+ * @param   privateKeyFile File specification of PEM formatted private key file
+ * @param   passphrase	   Passphrase to be used for encryption/encryption/signing/verifying
+ * @return                 Encryption object reference
+ */
+EXPORT PublicKeyEncryption(VARSTRING pkAlgorithm, VARSTRING publicKeyFile = '', VARSTRING privateKeyFile = '', VARSTRING passphrase = '') := MODULE
+    /**
+     * Encrypt the given data, using the specified public key file,
+     * passphrase, and algorithm
+     *
+     * @param   inputData    Contents to be Encrypted
+     * @return               Encrypted data
+     */
+    EXPORT DATA Encrypt(DATA inputData) := FUNCTION
+        RETURN lib_cryptolib.CryptoLib.Encrypt( pkAlgorithm, publicKeyFile, passphrase, inputData);
+    END;
+
+    /**
+     * Decrypt the given encrypted data, using the specified private key file,
+     * passphrase, and algorithm
+     *
+     * @param   encryptedData    Contents to be Decrypted
+     * @return                   Decrypted data
+     */
+    EXPORT DATA Decrypt(DATA encryptedData) := FUNCTION
+        RETURN lib_cryptolib.CryptoLib.Decrypt( pkAlgorithm, privateKeyFile, passphrase, encryptedData);
+    END;
+
+    /**
+     * Create a digital signature of the given data, using the
+     * specified private key file, passphrase and algorithm
+     *
+     * @param   inputData    Contents to be signed
+     * @return               Computed Digital signature
+     */
+    EXPORT DATA Sign( DATA inputData) := FUNCTION
+        RETURN lib_cryptolib.CryptoLib.Sign( pkAlgorithm, privateKeyFile, passphrase, inputData);
+    END;
+
+    /**
+     * Verify the given digital signature of the given data, using
+     * the specified public key file, passphrase and algorithm
+     *
+     * @param   signature      Signature to be verified
+     * @param   signedData     Data used to create signature
+     * @return                 BOOL
+     */
+    EXPORT BOOLEAN VerifySignature(DATA signature, DATA signedData) := FUNCTION
+        RETURN lib_cryptolib.CryptoLib.VerifySignature( pkAlgorithm, publicKeyFile, passphrase, signature, signedData);
+    END;
+END; // PublicKeyEncryption module
+
+
+
+/**
+  * Encryption module that can be instantiated by an ECL caller
+  * to perform asymmetric encryption/decryption/digital signing/signature verification
+  *
+  * @param   pkAlgorithm    ASymmetric algorithm to be used, as returned by SupportedPublicKeyAlgorithms()
+  * @param   publicKeyBuff  PEM formatted Public key buffer
+  * @param   privateKeyBuff PEM formatted Private key buffer
+  * @param   passphrase     Passphrase to be used for encryption/encryption/signing/verifying
+  * @return                 Encryption object reference
+  */
+EXPORT PublicKeyEncryptionFromBuffer(VARSTRING pkAlgorithm, VARSTRING publicKeyBuff = '', VARSTRING privateKeyBuff = '', VARSTRING passphrase = '') := MODULE
+    /**
+      * Encrypt the given data, using the specified public key, passphrase,
+      * and algorithm
+      *
+      * @param   inputData    Contents to be Encrypted
+      * @return               Encrypted data
+      */
+    EXPORT DATA Encrypt(DATA inputData) := FUNCTION
+        RETURN lib_cryptolib.CryptoLib.EncryptBuff( pkAlgorithm, publicKeyBuff, passphrase, inputData);
+    END;
+    
+    /**
+      * Decrypt the given data, using the specified private key, passphrase,
+      * and algorithm
+      *
+      * @param   encryptedData  Contents to be Decrypted
+      * @return                 Decrypted data
+      */
+    EXPORT DATA Decrypt(DATA encryptedData) := FUNCTION
+        RETURN lib_cryptolib.CryptoLib.DecryptBuff(pkAlgorithm, privateKeyBuff, passphrase, encryptedData);
+    END;
+
+    /**
+      * Create a digital signature of the given data, using the specified private key,
+      * passphrase, and algorithm
+      *
+      * @param   inputData    Contents to be signed
+      * @return               Computed digital signature
+      */
+    EXPORT DATA Sign(DATA inputData) := FUNCTION
+        RETURN lib_cryptolib.CryptoLib.SignBuff( pkAlgorithm, privateKeyBuff, passphrase, inputData);
+    END;
+
+    /**
+      * Verify the given digital signature of the given data, using the specified public key,
+      * passphrase, and algorithm
+      *
+      * @param   signature      Signature to be verified     
+      * @param   signedData     Data used to create signature
+      * @return                 True if signature is valid, false otherwise
+      */
+    EXPORT BOOLEAN VerifySignature(DATA signature, DATA signedData) := FUNCTION
+        RETURN lib_cryptolib.CryptoLib.VerifySignatureBuff( pkAlgorithm, publicKeyBuff, passphrase, signature, signedData);
+    END;
+    
+END; // PublicKeyEncryption module
+
+
+END; // Crypto module

+ 65 - 0
ecllibrary/teststd/Crypto/TestCrypto_Hash.ecl

@@ -0,0 +1,65 @@
+/*##############################################################################
+## HPCC SYSTEMS software Copyright (C) 2019 HPCC Systems®.  All rights reserved.
+############################################################################## */
+
+IMPORT Std;
+
+
+EXPORT TestCrypto_Hash := MODULE
+
+  EXPORT TestSupportedHash := MODULE
+    EXPORT TSH01 := ASSERT(Std.Crypto.SupportedHashAlgorithms() = ['SHA1', 'SHA224', 'SHA256', 'SHA384', 'SHA512']);
+  END;
+
+  EXPORT TestHashSHA1 := MODULE
+    EXPORT hashModuleSHA1 := Std.Crypto.Hashing('sha1');
+    EXPORT DATA h1 := hashModuleSHA1.Hash((DATA)'SHA1The quick brown fox jumps over the lazy dog');
+    EXPORT TH01 := ASSERT(h1 = (DATA)x'23BAFEB89163FFC27029B3736311810FD4BDFD9D');
+  END;
+
+  EXPORT TestHashSHA224 := MODULE
+    EXPORT hashModuleSHA224 := Std.Crypto.Hashing('SHA224');
+    EXPORT DATA h1 := hashModuleSHA224.Hash((DATA)'SHA224The quick brown fox jumps over the lazy dog');
+    EXPORT TH01 := ASSERT(h1 = (DATA)x'FE3E6060CE32A22BAC04E7CB699942516E8CFA69090C9543526B6FEF');
+  END;
+
+  EXPORT TestHashSHA256 := MODULE
+    EXPORT hashModuleSHA256 := Std.Crypto.Hashing('SHA256');
+    EXPORT DATA h1 := hashModuleSHA256.Hash((DATA)'SHA256The quick brown fox jumps over the lazy dog');
+    EXPORT TH01 := ASSERT(h1 = (DATA)x'10E051175BC5400D5F3B6D9953DCB17677B4B9493E178F47C35D9D8A8DB7D510');
+  END;
+
+  EXPORT TestHashSHA384 := MODULE
+    EXPORT hashModuleSHA384 := Std.Crypto.Hashing('SHA384');
+    EXPORT DATA h1 := hashModuleSHA384.Hash((DATA)'SHA384The quick brown fox jumps over the lazy dog');
+    EXPORT TH01 := ASSERT(h1 = (DATA)x'5934D11571137F45423D001CD52092AE911F98B99335C867D0AB1B684C47F761985CD52E94B24DE2560A37F368CC8F9C');
+  END;
+
+  EXPORT TestHashSHA512 := MODULE
+    EXPORT hashModuleSHA512 := Std.Crypto.Hashing('SHA512');
+    EXPORT DATA h1 := hashModuleSHA512.Hash((DATA)'SHA512The quick brown fox jumps over the lazy dog');
+    EXPORT TH01 := ASSERT(h1 = (DATA)x'18C8C050337567DFB8AB37B6D7132404A2FD0A9104F78C7A981283DF4AF2B84CF0A88A7D25D6E2640A5B176CA7BF453B60026A9A88507C6B0AF352F185AB831D');
+  END;
+
+  EXPORT TestHashSHACombined := MODULE
+    EXPORT hashModuleSHA1   := Std.Crypto.Hashing('sha1');
+    EXPORT hashModuleSHA224 := Std.Crypto.Hashing('SHA224');
+    EXPORT hashModuleSHA256 := Std.Crypto.Hashing('SHA256');
+    EXPORT hashModuleSHA384 := Std.Crypto.Hashing('SHA384');
+    EXPORT hashModuleSHA512 := Std.Crypto.Hashing('SHA512');
+
+    EXPORT DATA h1   := hashModuleSHA1.Hash(  (DATA)'SHA1The quick brown fox jumps over the lazy dog');
+    EXPORT DATA h224 := hashModuleSHA224.Hash((DATA)'SHA224The quick brown fox jumps over the lazy dog');
+    EXPORT DATA h256 := hashModuleSHA256.Hash((DATA)'SHA256The quick brown fox jumps over the lazy dog');
+    EXPORT DATA h384 := hashModuleSHA384.Hash((DATA)'SHA384The quick brown fox jumps over the lazy dog');
+    EXPORT DATA h512 := hashModuleSHA512.Hash((DATA)'SHA512The quick brown fox jumps over the lazy dog');
+
+    EXPORT TH01  := ASSERT(h1   = (DATA)x'23BAFEB89163FFC27029B3736311810FD4BDFD9D');
+    EXPORT TH224 := ASSERT(h224 = (DATA)x'FE3E6060CE32A22BAC04E7CB699942516E8CFA69090C9543526B6FEF');
+    EXPORT TH256 := ASSERT(h256 = (DATA)x'10E051175BC5400D5F3B6D9953DCB17677B4B9493E178F47C35D9D8A8DB7D510');
+    EXPORT TH384 := ASSERT(h384 = (DATA)x'5934D11571137F45423D001CD52092AE911F98B99335C867D0AB1B684C47F761985CD52E94B24DE2560A37F368CC8F9C');
+    EXPORT TH512 := ASSERT(h512 = (DATA)x'18C8C050337567DFB8AB37B6D7132404A2FD0A9104F78C7A981283DF4AF2B84CF0A88A7D25D6E2640A5B176CA7BF453B60026A9A88507C6B0AF352F185AB831D');
+  END;
+
+END;
+

+ 114 - 0
ecllibrary/teststd/Crypto/TestCrypto_PKE.ecl

@@ -0,0 +1,114 @@
+/*##############################################################################
+## HPCC SYSTEMS software Copyright (C) 2019 HPCC Systems®.  All rights reserved.
+############################################################################## */
+
+IMPORT Std;
+
+
+EXPORT TestCrypto_PKE := MODULE
+
+
+EXPORT STRING pubKey := '-----BEGIN PUBLIC KEY-----' + '\n' +
+'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr64RncTp5pV0KMnWRAof' + '\n' +
+'od+3AUS/IDngT39j3Iovv9aI2N8g4W5ipqhKftRESmzQ6I/TiUQcmi42soUXmCeE' + '\n' +
+'BHqlMDydw9aHOQG17CB30GYsw3Lf8iZo7RC7ocQE3OcRzH0eBkOryW6X3efWnMoy' + '\n' +
+'hIR9MexCldF+3WM/X0IX0ApSs7kuVPVG4Yj202+1FVO/XNwjMukJG5ASuxpYAQvv' + '\n' +
+'/oKj6q7kInEIvhLiGfcm3bpTzWQ66zVz3z/huLbEXEy5oj2fQaC5E3s5mdpk/CW3' + '\n' +
+'J6Tk4NY3NySWzE/2/ZOWxZdR79XC+goNL6v/5gPI8B/a3Z8OeM2PfSZwPMnVuvU0' + '\n' +
+'bwIDAQAB' + '\n' +
+'-----END PUBLIC KEY-----';
+
+
+EXPORT STRING privKey := '-----BEGIN RSA PRIVATE KEY-----' + '\n' +
+'MIIEowIBAAKCAQEAr64RncTp5pV0KMnWRAofod+3AUS/IDngT39j3Iovv9aI2N8g' + '\n' +
+'4W5ipqhKftRESmzQ6I/TiUQcmi42soUXmCeEBHqlMDydw9aHOQG17CB30GYsw3Lf' + '\n' +
+'8iZo7RC7ocQE3OcRzH0eBkOryW6X3efWnMoyhIR9MexCldF+3WM/X0IX0ApSs7ku' + '\n' +
+'VPVG4Yj202+1FVO/XNwjMukJG5ASuxpYAQvv/oKj6q7kInEIvhLiGfcm3bpTzWQ6' + '\n' +
+'6zVz3z/huLbEXEy5oj2fQaC5E3s5mdpk/CW3J6Tk4NY3NySWzE/2/ZOWxZdR79XC' + '\n' +
+'+goNL6v/5gPI8B/a3Z8OeM2PfSZwPMnVuvU0bwIDAQABAoIBAQCnGAtNYkOOu8wW' + '\n' +
+'F5Oid3aKwnwPytF211WQh3v2AcFU17qle+SMRi+ykBL6+u5RU5qH+HSc9Jm31AjW' + '\n' +
+'V1yPrdYVZInFjYIJCPzorcXY5zDOmMAuzg5PBVV7VhUA0a5GZck6FC8AilDUcEom' + '\n' +
+'GCK6Ul8mR9XELBFQ6keeTo2yDu0TQ4oBXrPBMN61uMHCxh2tDb2yvl8Zz+EllADG' + '\n' +
+'70pztRWNOrCzrC+ARlmmDfYOUgVFtZin53jq6O6ullPLzhkm3/+QFRGYWsFgQB6J' + '\n' +
+'Z9HJtW5YB47RT5RbLHKXeMc6IJW+d+5HrzgTdK79P7wAZk8JCIDyHe2AaNAUzc/G' + '\n' +
+'sB0cNeURAoGBAOKtaVFa6z2F4Q+koMBXCt4m7dCJnaC+qthF249uEOIBeF3ds9Fq' + '\n' +
+'f0jhhvuV0OcN8lYbR/ZlYRJDUs6mHh/2BYSkdeaLKojXTxKR2bA4xQk5dtJCdoPf' + '\n' +
+'0c15AlTgOYk2oNXP/azDICJYT/cdvIdUL9P4IoZthu1FjwG266GacEnNAoGBAMZn' + '\n' +
+'1wRUXS1dbqemoc+g48wj5r3/qsIG8PsZ2Y8W+oYW7diNA5o6acc8YPEWE2RbJDbX' + '\n' +
+'YEADBnRSdzzOdo0JEj4VbNZEtx6nQhBOOrtYKnnqHVI/XOz3VVu6kedUKdBR87KC' + '\n' +
+'eCzO1VcEeZtsTHuLO4t7NmdHGqNxTV+jLvzBoQsrAoGAI+fOD+nz6znirYSpRe5D' + '\n' +
+'tW67KtYxlr28+CcQoUaQ/Au5kjzE9/4DjXrT09QmVAMciNEnc/sZBjiNzFf525wv' + '\n' +
+'wZP/bPZMVYKtbsaVkdlcNJranHGUrkzswbxSRzmBQ5/YmCWrDAuYcnhEqmMWcuU9' + '\n' +
+'8jiS13JP9hOXlHDyIBYDhV0CgYBV6TznuQgnzp9NpQ/H8ijxilItz3lHTu4mLMlR' + '\n' +
+'9mdAjMkszdLTg5uuE+z+N8rp17VUseoRjb3LvLG4+MXIyDbH/0sDdPm+IjqvCNDR' + '\n' +
+'spmh9MgBh0JbsbWaZK0s9/qrI/FcSLZ04JLsfRmTPU/Y5y8/dHjYO6fDQhp44RZF' + '\n' +
+'iCqNxQKBgHf7KZIOKgV4YNyphk1UYWHNz8YY5o7WtaQ51Q+kIbU8PRd9rqJLZyk2' + '\n' +
+'tKf8e6z+wtKjxi8GKQzE/IdkQqiFmB1yEjjRHQ81WS+K5NnjN1t0IEscJqOAwv9s' + '\n' +
+'iIhG5ueb6xoj/N0LuXa8loUT5aChKWxRHEYdegqU48f+qxUcJj9R' + '\n' +
+'-----END RSA PRIVATE KEY-----';
+
+  EXPORT TestSupportedPKE := MODULE
+    EXPORT TS01 := ASSERT(Std.Crypto.SupportedPublicKeyAlgorithms() = ['SHA256']);
+  END;
+
+  //Encrypt/Decrypt
+
+  EXPORT TestPKE01 := MODULE
+    EXPORT mod := Std.Crypto.PublicKeyEncryptionFromBuffer('SHA256', pubKey, privKey, '');
+    EXPORT DATA dat1 := mod.Encrypt(            (DATA)'256The quick brown fox jumps over the lazy dog');
+    EXPORT TS01  := ASSERT(mod.Decrypt(dat1)  = (DATA)'256The quick brown fox jumps over the lazy dog');
+  
+    EXPORT TS011 := ASSERT(mod.Decrypt(dat1) != (DATA)'Hello World');
+
+    EXPORT DATA dat2 := mod.Encrypt(           (DATA)'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
+    EXPORT TS012 := ASSERT(mod.Decrypt(dat2) = (DATA)'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
+
+    EXPORT DATA dat3 := mod.Encrypt(           (DATA)'0123456789~`!@#$%^&*()-_=+|][}{;:?.>,<');
+    EXPORT TS013 := ASSERT(mod.Decrypt(dat3) = (DATA)'0123456789~`!@#$%^&*()-_=+|][}{;:?.>,<');
+  END;
+
+  EXPORT TestPKE02 := MODULE
+    EXPORT mod := Std.Crypto.PublicKeyEncryptionFromBuffer('SHA256', pubKey, privKey, '0123456789');//uses a passphrase
+    EXPORT DATA dat1 := mod.Encrypt(            (DATA)'256The quick brown fox jumps over the lazy dog');
+    EXPORT TS02  := ASSERT(mod.Decrypt(dat1)  = (DATA)'256The quick brown fox jumps over the lazy dog');
+  
+    EXPORT TS021 := ASSERT(mod.Decrypt(dat1) != (DATA)'Hello World');
+
+    EXPORT DATA dat2 := mod.Encrypt(           (DATA)'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
+    EXPORT TS022 := ASSERT(mod.Decrypt(dat2) = (DATA)'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
+
+    EXPORT DATA dat3 := mod.Encrypt(           (DATA)'0123456789~`!@#$%^&*()-_=+|][}{;:?.>,<');
+    EXPORT TS023 := ASSERT(mod.Decrypt(dat3) = (DATA)'0123456789~`!@#$%^&*()-_=+|][}{;:?.>,<');
+  END;
+
+  //Digital Signatures
+
+  EXPORT TestPKE03 := MODULE
+    EXPORT mod := Std.Crypto.PublicKeyEncryptionFromBuffer('SHA256', pubKey, privKey, '');
+    EXPORT DATA sig1 := mod.Sign(                           (DATA)'The quick brown fox jumps over the lazy dog');
+    EXPORT TS03 := ASSERT( TRUE = mod.VerifySignature(sig1, (DATA)'The quick brown fox jumps over the lazy dog'));
+ 
+    EXPORT TS031:= ASSERT( FALSE = mod.VerifySignature(sig1, (DATA)'Hello World'));
+
+    EXPORT DATA sig2 := mod.Sign(                            (DATA)'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
+    EXPORT TS032 := ASSERT( TRUE = mod.VerifySignature(sig2, (DATA)'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'));
+
+    EXPORT DATA sig3 := mod.Sign(                           (DATA)'0123456789~`!@#$%^&*()-_=+|][}{;:?.>,<');
+    EXPORT S033 := ASSERT( TRUE = mod.VerifySignature(sig3, (DATA)'0123456789~`!@#$%^&*()-_=+|][}{;:?.>,<'));
+  END; 
+
+  EXPORT TestPKE04 := MODULE
+    EXPORT mod := Std.Crypto.PublicKeyEncryptionFromBuffer('SHA256', pubKey, privKey, '0123456789');//uses a passphrase
+    EXPORT DATA sig1 := mod.Sign(                           (DATA)'The quick brown fox jumps over the lazy dog');
+    EXPORT TS03 := ASSERT( TRUE = mod.VerifySignature(sig1, (DATA)'The quick brown fox jumps over the lazy dog'));
+ 
+    EXPORT TS031:= ASSERT( FALSE = mod.VerifySignature(sig1, (DATA)'Hello World'));
+
+    EXPORT DATA sig2 := mod.Sign(                            (DATA)'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
+    EXPORT TS032 := ASSERT( TRUE = mod.VerifySignature(sig2, (DATA)'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'));
+
+    EXPORT DATA sig3 := mod.Sign(                           (DATA)'0123456789~`!@#$%^&*()-_=+|][}{;:?.>,<');
+    EXPORT S033 := ASSERT( TRUE = mod.VerifySignature(sig3, (DATA)'0123456789~`!@#$%^&*()-_=+|][}{;:?.>,<'));
+  END; 
+END;
+

+ 42 - 0
ecllibrary/teststd/Crypto/TestCrypto_SKE.ecl

@@ -0,0 +1,42 @@
+/*##############################################################################
+## HPCC SYSTEMS software Copyright (C) 2019 HPCC Systems®.  All rights reserved.
+############################################################################## */
+
+IMPORT Std;
+
+
+EXPORT TestCrypto_SKE := MODULE
+
+  EXPORT TestSupportedSKE := MODULE
+    EXPORT TS01 := ASSERT(Std.Crypto.SupportedSymmetricCipherAlgorithms() = ['aes-256-cbc', 'aes-192-cbc', 'aes-128-cbc']);
+  END;
+
+  EXPORT TestSKE01 := MODULE
+    EXPORT mod := Std.Crypto.SymmetricEncryption( 'aes-256-cbc', '01234567890123456789012345678901' );
+    EXPORT DATA dat := mod.Encrypt(           (DATA)'256The quick brown fox jumps over the lazy dog');
+    EXPORT TS01  := ASSERT(mod.Decrypt(dat) = (DATA)'256The quick brown fox jumps over the lazy dog');
+    EXPORT TS011 := ASSERT(mod.Decrypt(dat) != (DATA)'Hello World');
+  END;
+
+  EXPORT TestSKE02 := MODULE
+    EXPORT mod := Std.Crypto.SymmetricEncryption( 'aes-192-cbc', '012345678901234567890123' );
+    EXPORT DATA dat := mod.Encrypt(          (DATA)'192The quick brown fox jumps over the lazy dog');
+    EXPORT TS02 := ASSERT(mod.Decrypt(dat) = (DATA)'192The quick brown fox jumps over the lazy dog');
+  END;
+
+  EXPORT TestSKE03 := MODULE
+    EXPORT mod := Std.Crypto.SymmetricEncryption( 'aes-128-cbc', '0123456789012345' );
+    EXPORT DATA dat := mod.Encrypt(          (DATA)'128The quick brown fox jumps over the lazy dog');
+    EXPORT TS03 := ASSERT(mod.Decrypt(dat) = (DATA)'128The quick brown fox jumps over the lazy dog');
+  END;
+
+  EXPORT TestSKE04 := MODULE
+    EXPORT mod := Std.Crypto.SymmetricEncryption( 'aes-256-cbc', '01234567890123456789012345678901' );
+    EXPORT DATA dat := mod.Encrypt(          (DATA)'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
+    EXPORT TS04 := ASSERT(mod.Decrypt(dat) = (DATA)'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
+
+    EXPORT DATA dat2 := mod.Encrypt(          (DATA)'0123456789~`!@#$%^&*()-_=+|][}{;:?.>,<');
+    EXPORT TS05 := ASSERT(mod.Decrypt(dat2) = (DATA)'0123456789~`!@#$%^&*()-_=+|][}{;:?.>,<');
+  END;
+END;
+

+ 3 - 0
plugins/CMakeLists.txt

@@ -41,3 +41,6 @@ add_subdirectory (exampleplugin)
 add_subdirectory (couchbase)
 add_subdirectory (sqs)
 add_subdirectory (spark)
+IF (USE_OPENSSL)
+add_subdirectory (cryptolib)
+ENDIF()

+ 48 - 0
plugins/cryptolib/CMakeLists.txt

@@ -0,0 +1,48 @@
+################################################################################
+#    HPCC SYSTEMS software Copyright (C) 2019 HPCC Systems®.
+#
+#    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.
+################################################################################
+
+
+# Component: cryptolib
+
+#####################################################
+# Description:
+# ------------
+#    Cmake Input File for cryptolib
+#####################################################
+
+project( cryptolib )
+
+set (    SRCS
+         cryptolib.cpp
+    )
+
+include_directories (
+         ${HPCC_SOURCE_DIR}/system/include
+         ${HPCC_SOURCE_DIR}/system/jlib
+         ${HPCC_SOURCE_DIR}/rtl/include
+         ${HPCC_SOURCE_DIR}/system/security/cryptohelper
+         ${OPENSSL_INCLUDE_DIR}
+    )
+
+ADD_DEFINITIONS( -D_USRDLL -DCRYPTOLIB_EXPORTS )
+
+HPCC_ADD_LIBRARY( cryptolib SHARED ${SRCS} )
+install ( TARGETS cryptolib DESTINATION plugins )
+target_link_libraries ( 
+        cryptolib
+        jlib
+        ${ZLIB_LIBRARIES}
+    )

+ 610 - 0
plugins/cryptolib/cryptolib.cpp

@@ -0,0 +1,610 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2019 HPCC Systems®.
+
+    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.
+############################################################################## */
+
+#include "jutil.hpp"
+#include "jexcept.hpp"
+#include "digisign.hpp"
+#include "ske.hpp"
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <unordered_map>
+
+#include "cryptolib.hpp"
+
+using namespace std;
+
+#define CRYPTOLIB_VERSION "CRYPTOLIB 1.0.00"
+
+using namespace cryptohelper;
+
+
+static const char * EclDefinition = nullptr;//Definitions specified in lib_cryptolib.ecllib
+
+CRYPTOLIB_API bool getECLPluginDefinition(ECLPluginDefinitionBlock *pb)
+{
+    //  Warning:    This function may be called without the plugin being loaded fully.  
+    //              It should not make any library calls or assume that dependent modules
+    //              have been loaded or that it has been initialized.
+    //
+    //              Specifically:  "The system does not call DllMain for process and thread 
+    //              initialization and termination.  Also, the system does not load 
+    //              additional executable modules that are referenced by the specified module."
+
+    if (pb->size != sizeof(ECLPluginDefinitionBlock))
+        return false;
+
+    pb->magicVersion = PLUGIN_VERSION;
+    pb->version = CRYPTOLIB_VERSION;
+    pb->moduleName = "lib_cryptolib";
+    pb->ECL = EclDefinition;
+    pb->flags = PLUGIN_IMPLICIT_MODULE;
+    pb->description = "CryptoLib cryptography services library";
+    return true;
+}
+
+namespace nsCryptolib {
+    IPluginContext * parentCtx = nullptr;
+}
+using namespace nsCryptolib;
+
+CRYPTOLIB_API void setPluginContext(IPluginContext * _ctx) { parentCtx = _ctx; }
+
+//-------------------------------------------------------------------------------------------------------------------------------------------
+//  C++ to ECL helpers
+//-------------------------------------------------------------------------------------------------------------------------------------------
+
+size32_t addToECLSetOfString(void * set, const char * str)
+{
+    size32_t len = strlen(str);
+    if (len)
+    {
+        memcpy(set, &len, sizeof(len));//copy 4 byte length. String Set memory buffer should already be allocated within the context
+        memcpy((char *)set + sizeof(len), str, strlen(str));//followed by string
+    }
+    return len + sizeof(len);//return length copied to memory buffer
+}
+
+void stringArrayToECLSetOfString(const StringArray & arr, void * * set, size32_t * len)
+{
+    //STRING is a variable length string stored as a 4 byte length, followed by the string.  A set of strings has
+    //the strings in this format repeated, and the total size returned in the __lenResult parameter.  The __result value should be allocated
+    //on the heap.
+    size32_t currLen = 0;
+    for (aindex_t idx = 0; idx < arr.length(); idx++)
+        currLen += strlen(arr.item(idx)) + sizeof(size32_t);
+    void * pSet = CTXMALLOC(parentCtx, currLen);
+    assertex(set);
+
+    *len = currLen;
+    *set = pSet;
+    currLen = 0;
+    for (aindex_t idx = 0; idx < arr.length(); idx++)
+        currLen += addToECLSetOfString((char*)pSet + currLen, arr.item(idx));
+}
+
+//-------------------------------------------------------------------------------------------------------------------------------------------
+// CIPHER SYMMETRIC SUPPORT
+//-------------------------------------------------------------------------------------------------------------------------------------------
+
+//NB: It should be noted that we count on the cryptohelper library to call OpenSSL_add_all_algorithms() at init time
+void my_clAlgorithmsCallback(const OBJ_NAME * _obj, void * _pRes)
+{
+    ((StringArray*)_pRes)->append((const char*)_obj->name);//add this digest to string array
+}
+
+//NB: CRYPTOLIB call signatures can be gleaned from the generated workunit CPP file
+
+//Symmetric block/stream digest algorithms
+CRYPTOLIB_API void CRYPTOLIB_CALL clInstalledSymmetricCipherAlgorithms(bool & __isAllResult, size32_t & __lenResult, void * & __result)
+{
+    __isAllResult = false;
+    StringArray algorithms;
+    OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, my_clAlgorithmsCallback, (void*)&algorithms);
+    stringArrayToECLSetOfString(algorithms, &__result, &__lenResult);
+}
+
+CRYPTOLIB_API void CRYPTOLIB_CALL clSupportedSymmetricCipherAlgorithms(bool & __isAllResult, size32_t & __lenResult, void * & __result)
+{
+    __isAllResult = false;
+    StringArray algorithms;
+    algorithms.appendList("aes-256-cbc,aes-192-cbc,aes-128-cbc", ",");//make sure this list matches loadEVP_Cipher()
+    stringArrayToECLSetOfString(algorithms, &__result, &__lenResult);
+}
+
+
+//-------------------------------------------------------------------------------------------------------------------------------------------
+
+//Helpers to build the DATA buffer returned from clSymmetricEncrypt, and sent to clSymmetricDecrypt
+//Buffer is structured as:
+// (size32_t)lenIV, IV excluding NULL, (size32_t)LenPlainText excluding NULL, (size32_t)LenCipher, Cipher
+static void symmDeserialize(const void * pBuffer, StringBuffer & sbIV, StringBuffer & sbCipher, size32_t * lenPlainText)
+{
+    size32_t len;
+    const char * finger = (const char *)pBuffer;
+
+    memcpy(&len, finger, sizeof(size32_t));//extract IV
+    finger += sizeof(size32_t);
+    sbIV.append(len, finger);
+
+    finger += len;
+    memcpy(lenPlainText, finger, sizeof(size32_t));//extract length of plain text
+
+    finger += sizeof(size32_t);
+    memcpy(&len, finger, sizeof(size32_t));//extract cipher
+    finger += sizeof(size32_t);
+    sbCipher.append(len, finger);
+}
+
+static void symmSerialize(void * & result, size32_t & lenResult, const char * pIV, size32_t lenIV, size32_t lenPlainText, size32_t lenCipherBuff, const void * pCipherBuff)
+{
+    //Allocate return DATA buffer
+    lenResult = sizeof(size32_t) + lenIV + sizeof(size32_t) + sizeof(size32_t) + lenCipherBuff;
+    result = CTXMALLOC(parentCtx, lenResult);
+
+    //build result DATA buffer in the form:
+
+    char * pRes = (char *)result;
+    memcpy(pRes, &lenIV, sizeof(size32_t));//copy size of IV
+    pRes += sizeof(size32_t);
+    memcpy(pRes, pIV, lenIV);//copy the IV
+    pRes += lenIV;
+    memcpy(pRes, &lenPlainText, sizeof(size32_t));
+    pRes += sizeof(size32_t);
+    memcpy(pRes, &lenCipherBuff, sizeof(size32_t));
+    pRes += sizeof(size32_t);
+    memcpy(pRes, pCipherBuff, lenCipherBuff);
+}
+
+//-------------------------------------------------------------------------------------------------------------------------------------------
+
+void verifySymmetricAlgorithm(const char * algorithm, size32_t len)
+{
+     if (strieq(algorithm, "aes-128-cbc"))
+     {
+         if (len != 16)
+             throw MakeStringException(-1, "Invalid Key Length %d specified for algorithm %s, try 16", len, algorithm);
+     }
+     else if (strieq(algorithm, "aes-192-cbc"))
+     {
+         if (len != 24)
+             throw MakeStringException(-1, "Invalid Key Length %d specified for algorithm %s, try 24", len, algorithm);
+     }
+     else if (strieq(algorithm, "aes-256-cbc"))
+     {
+         if (len != 32)
+             throw MakeStringException(-1, "Invalid Key Length %d specified for algorithm %s, try 32", len, algorithm);
+     }
+     else
+         throw MakeStringException(-1, "Unsupported symmetric algorithm (%s) specified", algorithm);
+}
+
+CRYPTOLIB_API void CRYPTOLIB_CALL clSymmetricEncrypt(size32_t & __lenResult, void * & __result,
+                                                    const char * algorithm,
+                                                    const char * key,
+                                                    size32_t lenInputdata,const void * inputdata)
+{
+    verifySymmetricAlgorithm(algorithm, strlen(key) );
+
+    //Create a unique Initialization Vector
+    unsigned char iv[EVP_MAX_IV_LENGTH];
+    RAND_bytes(iv, EVP_MAX_IV_LENGTH);
+
+    //temporary buffer for result
+    MemoryBuffer out;
+    aesEncrypt(out, lenInputdata, inputdata, strlen(key), key, (const char *)iv);
+
+    //build result DATA buffer in the form:
+    // (size32_t)EVP_MAX_IV_LENGTH, IV, (size32_t)LenPlainText excluding NULL, (size32_t)LenCipher, Cipher
+    symmSerialize(__result, __lenResult, (const char *)iv, sizeof(iv), lenInputdata, out.length(), (const void *)out.bufferBase());
+}
+
+CRYPTOLIB_API void CRYPTOLIB_CALL clSymmetricDecrypt(size32_t & __lenResult,void * & __result,
+                                                const char * algorithm,
+                                                const char * key,
+                                                size32_t lenEncrypteddata,const void * encrypteddata)
+{
+    verifySymmetricAlgorithm(algorithm, strlen(key));
+
+    //Decompose DATA buffer
+
+    StringBuffer sbIV;
+    StringBuffer sbCipher;
+    size32_t     lenPlainText;
+    symmDeserialize(encrypteddata, sbIV, sbCipher, &lenPlainText);
+
+    __result = (char *)CTXMALLOC(parentCtx, lenPlainText);
+    __lenResult = lenPlainText;
+
+    MemoryBuffer decrypted;
+    size32_t len = aesDecrypt(decrypted, sbCipher.length(), sbCipher.str(), strlen(key), key, sbIV.str());
+    memcpy(__result, decrypted.toByteArray(), __lenResult);
+}
+
+
+
+//-------------------------------------------------------------------------------------------------------------------------------------------
+// HASH SUPPORT
+//-------------------------------------------------------------------------------------------------------------------------------------------
+
+CRYPTOLIB_API void CRYPTOLIB_CALL clInstalledHashAlgorithms(bool & __isAllResult, size32_t & __lenResult, void * & __result)
+{
+    __isAllResult = false;
+    StringArray algorithms;
+    OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH, my_clAlgorithmsCallback, (void*)&algorithms);
+    stringArrayToECLSetOfString(algorithms, &__result, &__lenResult);
+}
+
+CRYPTOLIB_API void CRYPTOLIB_CALL clSupportedHashAlgorithms(bool & __isAllResult, size32_t & __lenResult, void * & __result)
+{
+    __isAllResult = false;
+    StringArray algorithms;
+    algorithms.appendList("SHA1,SHA224,SHA256,SHA384,SHA512", ",");//make sure these match algorithms in clHash()
+    stringArrayToECLSetOfString(algorithms, &__result, &__lenResult);
+}
+
+void throwHashError(const char * str)
+{
+    unsigned long err = ERR_get_error();
+    char errStr[1024];
+    ERR_error_string_n(err, errStr, sizeof(errStr));
+    throw MakeStringException(-1, "%s : ERROR %ld (0x%lX) : %s", str, err, err, errStr);
+}
+
+CRYPTOLIB_API void CRYPTOLIB_CALL clHash(size32_t & __lenResult, void * & __result,
+                                         const char * algorithm,
+                                         size32_t lenInputData, const void * inputData)
+{
+    //Make sure each algorithm is included in clHashAlgorithms()
+    if (strieq("SHA1", algorithm))
+    {
+        SHA_CTX context;
+        if (!SHA1_Init(&context))
+            throwHashError("OpenSSL ERROR calling SHA1_Init");
+
+        if (!SHA1_Update(&context, (unsigned char*)inputData, lenInputData))
+            throwHashError("OpenSSL ERROR calling SHA1_Update");
+
+        __lenResult = SHA_DIGEST_LENGTH;//20 bytes
+        __result = CTXMALLOC(parentCtx, __lenResult);
+
+        if (!SHA1_Final((unsigned char *)__result, &context))
+        {
+            free(__result);
+            throwHashError("OpenSSL ERROR calling SHA1_Final");
+        }
+    }
+    else if (strieq("SHA224", algorithm))
+    {
+        SHA256_CTX context;//SHA224 uses the SHA256 context
+        if (!SHA224_Init(&context))
+            throwHashError("OpenSSL ERROR calling SHA224_Init");
+
+        if (!SHA224_Update(&context, (unsigned char*)inputData, lenInputData))
+            throwHashError("OpenSSL ERROR calling SHA224_Update");
+
+        __lenResult = SHA224_DIGEST_LENGTH;//28 bytes
+        __result = CTXMALLOC(parentCtx, __lenResult);
+
+        if (!SHA224_Final((unsigned char *)__result, &context))
+        {
+            free(__result);
+            throwHashError("OpenSSL ERROR calling SHA224_Final");
+        }
+    }
+    else if (strieq("SHA256", algorithm))
+    {
+        SHA256_CTX context;
+        if (!SHA256_Init(&context))
+            throwHashError("OpenSSL ERROR calling SHA256_Init");
+
+        if (!SHA256_Update(&context, (unsigned char*)inputData, lenInputData))
+            throwHashError("OpenSSL ERROR calling SHA256_Update");
+
+        __lenResult = SHA256_DIGEST_LENGTH;//32 bytes
+        __result = CTXMALLOC(parentCtx, __lenResult);
+
+        if (!SHA256_Final((unsigned char *)__result, &context))
+        {
+            free(__result);
+            throwHashError("OpenSSL ERROR calling SHA256_Final");
+        }
+    }
+    else if (strieq("SHA384", algorithm))
+    {
+        SHA512_CTX context;//SHA384 uses the SHA512 context
+        if (!SHA384_Init(&context))
+            throwHashError("OpenSSL ERROR calling SHA384_Init");
+
+        if (!SHA384_Update(&context, (unsigned char*)inputData, lenInputData))
+            throwHashError("OpenSSL ERROR calling SHA384_Update");
+
+        __lenResult = SHA384_DIGEST_LENGTH;//48 bytes
+        __result = CTXMALLOC(parentCtx, __lenResult);
+
+        if (!SHA384_Final((unsigned char *)__result, &context))
+        {
+            free(__result);
+            throwHashError("OpenSSL ERROR calling SHA384_Final");
+        }
+    }
+    else if (strieq("SHA512", algorithm))
+    {
+        SHA512_CTX context;
+        if (!SHA512_Init(&context))
+            throwHashError("OpenSSL ERROR calling SHA512_Init");
+
+        if (!SHA512_Update(&context, (unsigned char*)inputData, lenInputData))
+            throwHashError("OpenSSL ERROR calling SHA512_Update");
+
+        __lenResult = SHA512_DIGEST_LENGTH;//64 bytes
+        __result = CTXMALLOC(parentCtx, __lenResult);
+
+        if (!SHA512_Final((unsigned char *)__result, &context))
+        {
+            free(__result);
+            throwHashError("OpenSSL ERROR calling SHA512_Final");
+        }
+    }
+    else
+    {
+        throw MakeStringException(-1, "Unsupported hash algorithm '%s' specified", algorithm);
+    }
+}
+
+//-------------------------------------------------------------------------------------------------------------------------------------------
+// PUBLIC KEY SUPPORT
+//-------------------------------------------------------------------------------------------------------------------------------------------
+
+CRYPTOLIB_API void CRYPTOLIB_CALL clInstalledPublicKeyAlgorithms(bool & __isAllResult, size32_t & __lenResult, void * & __result)
+{
+    __isAllResult = false;
+    StringArray algorithms;
+    OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_PKEY_METH, my_clAlgorithmsCallback, (void*)&algorithms);
+    stringArrayToECLSetOfString(algorithms, &__result, &__lenResult);
+}
+
+CRYPTOLIB_API void CRYPTOLIB_CALL clSupportedPublicKeyAlgorithms(bool & __isAllResult, size32_t & __lenResult, void * & __result)
+{
+    __isAllResult = false;
+    StringArray algorithms;
+    algorithms.appendList("SHA256", ",");
+    stringArrayToECLSetOfString(algorithms, &__result, &__lenResult);
+}
+
+//signature helper function
+void doPKISign(size32_t & __lenResult, void * & __result,
+        IDigitalSignatureManager * pDSM,
+        size32_t lenInputdata, const void * inputdata)
+{
+    StringBuffer sbSig;
+    if (pDSM->digiSign(sbSig, lenInputdata, inputdata))
+    {
+        __result = CTXMALLOC(parentCtx, sbSig.length());
+        __lenResult = sbSig.length();
+        memcpy(__result, sbSig.str(), __lenResult);
+    }
+    else
+    {
+        throw MakeStringException(-1, "Unable to create Digital Signature");
+    }
+}
+
+void verifyPKIAlgorithm(const char * pkAlgorithm)
+{
+    if (!strieq(pkAlgorithm, "SHA256"))
+        throw MakeStringException(-1, "Unsupported PKI algorithm (%s) specified", pkAlgorithm);
+}
+
+
+//-----------------------------------------------------------------
+//  Simple cache for instances of Digital Signature Managers
+//-----------------------------------------------------------------
+class CDSMCache
+{
+private:
+    CriticalSection csDSMCache;//guards modifications to the cache map
+    typedef std::unordered_map<string, Owned<IDigitalSignatureManager>> DSMCache;
+    DSMCache dsmCache;
+
+public:
+    IDigitalSignatureManager * getInstance(const char * algo, const char * pubKeyFS, const char * pubKeyBuff, const char * privKeyFS, const char * privKeyBuff, const char * passphrase)
+    {
+        VStringBuffer searchKey("%s_%s_%s_%s_%s_%s", algo, isEmptyString(pubKeyFS) ? "" : pubKeyFS, isEmptyString(pubKeyBuff) ? "" : pubKeyBuff,
+                                isEmptyString(privKeyFS) ? "" : privKeyFS, isEmptyString(privKeyBuff) ? "" : privKeyBuff, passphrase);
+        CriticalBlock block(csDSMCache);
+        DSMCache::iterator it = dsmCache.find(searchKey.str());
+        IDigitalSignatureManager * ret = nullptr;
+        if (it != dsmCache.end())//exists in cache
+        {
+            ret = (*it).second;
+        }
+        else
+        {
+            IDigitalSignatureManager * pDSM = nullptr;
+            if (!isEmptyString(pubKeyFS) && !isEmptyString(privKeyFS))
+                pDSM = createDigitalSignatureManagerInstanceFromFiles(pubKeyFS, privKeyFS, passphrase);
+            else
+                pDSM = createDigitalSignatureManagerInstanceFromKeys(pubKeyBuff, privKeyBuff, passphrase);
+
+            dsmCache.insert(pair<string, IDigitalSignatureManager*>(searchKey.str(), pDSM));
+            ret = pDSM;
+        }
+        return LINK(ret);
+    }
+};
+static CDSMCache g_DSMCache;
+
+//Sign given data using private key
+CRYPTOLIB_API void CRYPTOLIB_CALL clPKISign(size32_t & __lenResult,void * & __result,
+                                        const char * pkalgorithm,
+                                        const char * privatekeyfile,
+                                        const char * passphrase,
+                                        size32_t lenInputdata,const void * inputdata)
+{
+    verifyPKIAlgorithm(pkalgorithm);//TODO extend cryptohelper to support more algorithms
+    Owned<IDigitalSignatureManager> pDSM = g_DSMCache.getInstance(pkalgorithm, nullptr, nullptr, privatekeyfile, nullptr, passphrase);
+    if (pDSM)
+    {
+        doPKISign(__lenResult, __result, pDSM, lenInputdata, inputdata);
+    }
+    else
+    {
+        throw MakeStringException(-1, "Unable to create Digital Signature Manager");
+    }
+}
+
+CRYPTOLIB_API void CRYPTOLIB_CALL clPKISignBuff(size32_t & __lenResult, void * & __result,
+                                            const char * pkalgorithm,
+                                            const char * privatekeybuff,
+                                            const char * passphrase,
+                                            size32_t lenInputdata, const void * inputdata)
+{
+    verifyPKIAlgorithm(pkalgorithm);
+    Owned<IDigitalSignatureManager> pDSM = g_DSMCache.getInstance(pkalgorithm, nullptr, nullptr, nullptr, privatekeybuff, passphrase);
+    if (pDSM)
+    {
+        doPKISign(__lenResult, __result, pDSM, lenInputdata, inputdata);
+    }
+    else
+    {
+        throw MakeStringException(-1, "Unable to create Digital Signature Manager");
+    }
+}
+
+CRYPTOLIB_API bool CRYPTOLIB_CALL clPKIVerifySignature(const char * pkalgorithm,
+                                                    const char * publickeyfile,
+                                                    const char * passphrase,
+                                                    size32_t lenSignature,const void * signature,
+                                                    size32_t lenSigneddata,const void * signeddata)
+{
+    verifyPKIAlgorithm(pkalgorithm);
+    Owned<IDigitalSignatureManager> pDSM = g_DSMCache.getInstance(pkalgorithm, publickeyfile, nullptr, nullptr, nullptr, passphrase);
+    if (pDSM)
+    {
+        StringBuffer sbSig(lenSignature, (const char *)signature);
+        bool rc = pDSM->digiVerify(sbSig.str(), lenSigneddata, signeddata);
+        return rc;
+    }
+    else
+    {
+        throw MakeStringException(-1, "Unable to create Digital Signature Manager");
+    }
+}
+
+CRYPTOLIB_API bool CRYPTOLIB_CALL clPKIVerifySignatureBuff(const char * pkalgorithm,
+                                                       const char * publicKeyBuff,
+                                                       const char * passphrase,
+                                                       size32_t lenSignature, const void * signature,
+                                                       size32_t lenSigneddata, const void * signeddata)
+{
+    verifyPKIAlgorithm(pkalgorithm);
+    Owned<IDigitalSignatureManager> pDSM = g_DSMCache.getInstance(pkalgorithm, nullptr, publicKeyBuff, nullptr, nullptr, passphrase);
+    if (pDSM)
+    {
+        StringBuffer sbSig(lenSignature, (const char *)signature);
+        bool rc = pDSM->digiVerify(sbSig.str(), lenSigneddata, signeddata);
+        return rc;
+    }
+    else
+    {
+        throw MakeStringException(-1, "Unable to create Digital Signature Manager");
+    }
+}
+
+
+//------------------------------------
+//Encryption helper
+//------------------------------------
+static void doPKIEncrypt(size32_t & __lenResult,void * & __result,
+                  CLoadedKey * publicKey,
+                  size32_t lenInputdata,const void * inputdata)
+{
+    MemoryBuffer pkeMb;
+    __lenResult = publicKeyEncrypt(pkeMb, lenInputdata, inputdata, *publicKey);
+    if (__lenResult)
+    {
+        __result = CTXMALLOC(parentCtx, __lenResult);
+        memcpy(__result, pkeMb.bytes(), __lenResult);
+    }
+}
+
+//------------------------------------
+//Decryption helper
+//------------------------------------
+static void doPKIDecrypt(size32_t & __lenResult,void * & __result,
+                  CLoadedKey * privateKey,
+                  size32_t lenInputdata,const void * inputdata)
+{
+    MemoryBuffer pkeMb;
+    __lenResult = privateKeyDecrypt(pkeMb, lenInputdata, inputdata, *privateKey);
+    if (__lenResult)
+    {
+        __result = CTXMALLOC(parentCtx, __lenResult);
+        memcpy(__result, pkeMb.bytes(), __lenResult);
+    }
+}
+
+
+
+//encryption functions that take filespecs of key files
+CRYPTOLIB_API void CRYPTOLIB_CALL clPKIEncrypt(size32_t & __lenResult,void * & __result,
+                                            const char * pkalgorithm,
+                                            const char * publickeyfile,
+                                            const char * passphrase,
+                                            size32_t lenInputdata,const void * inputdata)
+{
+    verifyPKIAlgorithm(pkalgorithm);
+    Owned<CLoadedKey> publicKey = loadPublicKeyFromFile(publickeyfile, passphrase);
+    doPKIEncrypt(__lenResult, __result, publicKey, lenInputdata, inputdata);
+}
+
+
+CRYPTOLIB_API void CRYPTOLIB_CALL clPKIDecrypt(size32_t & __lenResult,void * & __result,
+                                            const char * pkalgorithm,
+                                            const char * privatekeyfile,
+                                            const char * passphrase,
+                                            size32_t lenEncrypteddata,const void * encrypteddata)
+{
+    verifyPKIAlgorithm(pkalgorithm);
+    Owned<CLoadedKey> privateKey = loadPrivateKeyFromFile(privatekeyfile, passphrase);
+    doPKIDecrypt(__lenResult, __result, privateKey, lenEncrypteddata, encrypteddata);
+}
+
+//encryption functions that take keys in a buffer
+
+CRYPTOLIB_API void CRYPTOLIB_CALL clPKIEncryptBuff(size32_t & __lenResult,void * & __result,
+                                                const char * pkalgorithm,
+                                                const char * publickeybuff,
+                                                const char * passphrase,
+                                                size32_t lenInputdata,const void * inputdata)
+{
+    verifyPKIAlgorithm(pkalgorithm);
+    Owned<CLoadedKey> publicKey = loadPublicKeyFromMemory(publickeybuff, passphrase);
+    doPKIEncrypt(__lenResult, __result, publicKey, lenInputdata, inputdata);
+}
+
+CRYPTOLIB_API void CRYPTOLIB_CALL clPKIDecryptBuff(size32_t & __lenResult,void * & __result,
+                                                const char * pkalgorithm,
+                                                const char * privatekeybuff,
+                                                const char * passphrase,
+                                                size32_t lenEncrypteddata,const void * encrypteddata)
+{
+    verifyPKIAlgorithm(pkalgorithm);
+    Owned<CLoadedKey> privateKey = loadPrivateKeyFromMemory(privatekeybuff, passphrase);
+    doPKIDecrypt(__lenResult, __result, privateKey, lenEncrypteddata, encrypteddata);
+}

+ 75 - 0
plugins/cryptolib/cryptolib.hpp

@@ -0,0 +1,75 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2019 HPCC Systems®.
+
+    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.
+############################################################################## */
+
+#ifndef CRYPTOLIB_INCL
+#define CRYPTOLIB_INCL
+
+#ifdef _WIN32
+#define CRYPTOLIB_CALL _cdecl
+#else
+#define CRYPTOLIB_CALL
+#endif
+
+#ifdef CRYPTOLIB_EXPORTS
+#define CRYPTOLIB_API DECL_EXPORT
+#else
+#define CRYPTOLIB_API DECL_IMPORT
+#endif
+
+#include "hqlplugins.hpp"
+#include "eclhelper.hpp"
+
+extern "C"
+{
+
+#ifdef CRYPTOLIB_EXPORTS
+  CRYPTOLIB_API bool getECLPluginDefinition(ECLPluginDefinitionBlock *pb);
+  CRYPTOLIB_API void setPluginContext(IPluginContext * _ctx);
+#endif
+
+
+//Following prototypes can be found in workunit CPP file (/var/lib/HPCCSystems/myeclccserver)
+
+//Hasing encryption/decryption
+//CRYPTOLIB_API void CRYPTOLIB_CALL clInstalledHashAlgorithms(bool & __isAllResult, size32_t & __lenResult, void * & __result);
+CRYPTOLIB_API void CRYPTOLIB_CALL clSupportedHashAlgorithms(bool & __isAllResult, size32_t & __lenResult, void * & __result);
+CRYPTOLIB_API void CRYPTOLIB_CALL clHash(size32_t & __lenResult,void * & __result,const char * algorithm,size32_t lenInputdata,const void * inputdata);
+
+
+//Cipher symmetric encryption/decryption
+//CRYPTOLIB_API void CRYPTOLIB_CALL clInstalledSymmetricCipherAlgorithms(bool & __isAllResult, size32_t & __lenResult, void * & __result);
+CRYPTOLIB_API void CRYPTOLIB_CALL clSupportedSymmetricCipherAlgorithms(bool & __isAllResult, size32_t & __lenResult, void * & __result);
+CRYPTOLIB_API void CRYPTOLIB_CALL clSymmetricEncrypt(size32_t & __lenResult,void * & __result,const char * algorithm,const char * key,size32_t lenInputdata,const void * inputdata);
+CRYPTOLIB_API void CRYPTOLIB_CALL clSymmetricDecrypt(size32_t & __lenResult,void * & __result,const char * algorithm,const char * key,size32_t lenEncrypteddata,const void * encrypteddata);
+
+//Public Key encryption/decryption
+//CRYPTOLIB_API void CRYPTOLIB_CALL clInstalledPublicKeyAlgorithms(bool & __isAllResult, size32_t & __lenResult, void * & __result);
+CRYPTOLIB_API void CRYPTOLIB_CALL clSupportedPublicKeyAlgorithms(bool & __isAllResult, size32_t & __lenResult, void * & __result);
+CRYPTOLIB_API void CRYPTOLIB_CALL clPKIEncrypt(size32_t & __lenResult,void * & __result,const char * pkalgorithm,const char * publickeyfile,const char * passphrase,size32_t lenInputdata,const void * inputdata);
+CRYPTOLIB_API void CRYPTOLIB_CALL clPKIDecrypt(size32_t & __lenResult,void * & __result,const char * pkalgorithm,const char * privatekeyfile,const char * passphrase,size32_t lenEncrypteddata,const void * encrypteddata);
+
+CRYPTOLIB_API void CRYPTOLIB_CALL clPKISign(size32_t & __lenResult,void * & __result,const char * pkalgorithm,const char * privatekeyfile,const char * passphrase,size32_t lenInputdata,const void * inputdata);
+CRYPTOLIB_API bool CRYPTOLIB_CALL clPKIVerifySignature(const char * pkalgorithm,const char * publickeyfile,const char * passphrase,size32_t lenSignature,const void * signature,size32_t lenSigneddata,const void * signeddata);
+
+
+CRYPTOLIB_API void CRYPTOLIB_CALL clPKIEncryptBuff(size32_t & __lenResult,void * & __result,const char * pkalgorithm,const char * publickeybuff,const char * passphrase,size32_t lenInputdata,const void * inputdata);
+CRYPTOLIB_API void CRYPTOLIB_CALL clPKIDecryptBuff(size32_t & __lenResult,void * & __result,const char * pkalgorithm,const char * privatekeybuff,const char * passphrase,size32_t lenEncrypteddata,const void * encrypteddata);
+
+CRYPTOLIB_API void CRYPTOLIB_CALL clPKISignBuff(size32_t & __lenResult,void * & __result,const char * pkalgorithm,const char * privatekeybuff,const char * passphrase,size32_t lenInputdata,const void * inputdata);
+CRYPTOLIB_API bool CRYPTOLIB_CALL clPKIVerifySignatureBuff(const char * pkalgorithm,const char * publickeybuff,const char * passphrase,size32_t lenSignature,const void * signature,size32_t lenSigneddata,const void * signeddata);
+}
+#endif

+ 26 - 0
plugins/cryptolib/sourcedoc.xml

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+################################################################################
+#    HPCC SYSTEMS software Copyright (C) 2019 HPCC Systems®.
+#
+#    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.
+################################################################################
+-->
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
+<section>
+    <title>plugins/cryptolib</title>
+
+    <para>
+        The plugins/cryptolib directory contains the sources for the plugins/cryptolib library.
+    </para>
+</section>

+ 3 - 0
plugins/proxies/CMakeLists.txt

@@ -20,3 +20,6 @@ install ( FILES ${CMAKE_CURRENT_SOURCE_DIR}/lib_metaphone.ecllib DESTINATION plu
 install ( FILES ${CMAKE_CURRENT_SOURCE_DIR}/lib_thorlib.ecllib DESTINATION plugins COMPONENT Runtime)
 install ( FILES ${CMAKE_CURRENT_SOURCE_DIR}/lib_word.ecllib DESTINATION plugins COMPONENT Runtime)
 
+IF (USE_OPENSSL)
+install ( FILES ${CMAKE_CURRENT_SOURCE_DIR}/lib_cryptolib.ecllib DESTINATION plugins COMPONENT Runtime)
+ENDIF()

+ 48 - 0
plugins/proxies/lib_cryptolib.ecllib

@@ -0,0 +1,48 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2019 HPCC Systems®.
+
+    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.
+############################################################################## */
+
+/* Proxy plugin definition for crypto plugin library version CRYPTO 1.0.0 */
+
+export CryptoLib := SERVICE : plugin('cryptolib')
+
+  //Hashing
+  
+  SET OF STRING SupportedHashAlgorithms() : c, pure, fold, entrypoint='clSupportedHashAlgorithms';
+  DATA   Hash(CONST VARSTRING algorithm, CONST DATA inputData) : c, pure, entrypoint='clHash';
+
+  //Symmetric Encryption
+      
+  SET OF STRING SupportedSymmetricCipherAlgorithms() : c, pure, fold, entrypoint='clSupportedSymmetricCipherAlgorithms';
+  DATA  SymmetricEncrypt(CONST VARSTRING algorithm, CONST VARSTRING passphrase, CONST DATA inputData) : c, pure, entrypoint='clSymmetricEncrypt';
+  DATA SymmetricDecrypt( CONST VARSTRING algorithm, CONST VARSTRING passphrase, CONST DATA encryptedData) : c, pure, entrypoint='clSymmetricDecrypt';
+
+  //Asymmetric Public Key Encryption
+  
+  SET OF STRING SupportedPublicKeyAlgorithms() : c, pure, fold, entrypoint='clSupportedPublicKeyAlgorithms';
+
+  //Accepts key data as file specification
+  DATA    Encrypt(CONST VARSTRING pkAlgorithm, CONST VARSTRING publicKeyFile, CONST VARSTRING passphrase, CONST DATA inputData) : c, pure, entrypoint='clPKIEncrypt';
+  DATA    Decrypt(CONST VARSTRING pkAlgorithm, CONST VARSTRING privateKeyFile, CONST VARSTRING passphrase, CONST DATA encryptedData) : c, pure, entrypoint='clPKIDecrypt';
+  DATA    Sign(CONST VARSTRING pkAlgorithm, CONST VARSTRING privateKeyFile, CONST VARSTRING passphrase, CONST DATA inputData) : c, pure, entrypoint='clPKISign';
+  BOOLEAN VerifySignature(CONST VARSTRING pkAlgorithm, CONST VARSTRING publicKeyFile, CONST VARSTRING passphrase, CONST DATA signature, CONST DATA signedData) : c, pure, entrypoint='clPKIVerifySignature';
+  
+  //Accepts key data as memory buffer
+  DATA    EncryptBuff(CONST VARSTRING pkAlgorithm, CONST VARSTRING publicKeyBuff, CONST VARSTRING passphrase, CONST DATA inputData) : c, pure, entrypoint='clPKIEncryptBuff';
+  DATA    DecryptBuff(CONST VARSTRING pkAlgorithm, CONST VARSTRING privateKeyBuff, CONST VARSTRING passphrase, CONST DATA encryptedData) : c, pure, entrypoint='clPKIDecryptBuff';
+  DATA    SignBuff(CONST VARSTRING pkAlgorithm, CONST VARSTRING privateKeyBuff, CONST VARSTRING passphrase, CONST DATA inputData) : c, pure, entrypoint='clPKISignBuff';
+  BOOLEAN VerifySignatureBuff(CONST VARSTRING pkAlgorithm, CONST VARSTRING publicKeyBuff, CONST VARSTRING passphrase, CONST DATA signature, CONST DATA signedData) : c, pure, entrypoint='clPKIVerifySignatureBuff';
+ END;

+ 1 - 0
plugins/sourcedoc.xml

@@ -33,4 +33,5 @@
     <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="stringlib/sourcedoc.xml"/>
     <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="unicodelib/sourcedoc.xml"/>
     <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="workunitservices/sourcedoc.xml"/>
+    <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="cryptolib/sourcedoc.xml"/>
 </section>

+ 71 - 0
testing/regress/ecl/cryptoplugin_hash.ecl

@@ -0,0 +1,71 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2019 HPCC Systems®.
+
+    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.
+############################################################################## */
+import Std;
+
+output(Std.Crypto.SupportedHashAlgorithms());
+
+output('SHA1 tests');
+hashModuleSHA1 := Std.Crypto.Hashing('sha1');
+DATA hashedValue     := hashModuleSHA1.Hash((DATA)'SHA1The quick brown fox jumps over the lazy dog');
+DATA hashedValueEx   := hashModuleSHA1.Hash((DATA)'SHA1The most beautiful thing in the world is, of course, the world itself!');
+DATA hashedValueExEx := hashModuleSHA1.Hash((DATA)'SHA1The most beautiful thing in the world is, of course, the world itself!');
+
+output( hashedValue );
+output( hashedValueEx );
+output( hashedValueExEx);
+
+
+output('SHA224 tests');
+hashModuleSHA224 := Std.Crypto.Hashing('sha224');
+DATA hashedValue224 := hashModuleSHA224.Hash((DATA)'SHA224The quick brown fox jumps over the lazy dog');
+output( hashedValue224 );
+
+output('SHA256 tests');
+hashModuleSHA256 := Std.Crypto.Hashing('sha256');
+DATA hashedValue256 := hashModuleSHA256.Hash((DATA)'SHA256The quick brown fox jumps over the lazy dog');
+output( hashedValue256 );
+
+output('SHA384 tests');
+hashModuleSHA384 := Std.Crypto.Hashing('sha256');
+DATA hashedValue384 := hashModuleSHA384.Hash((DATA)'SHA384The quick brown fox jumps over the lazy dog');
+output( hashedValue384 );
+
+output('SHA512 tests');
+hashModuleSHA512 := Std.Crypto.Hashing('sha512');
+DATA hashedValue512 := hashModuleSHA512.Hash((DATA)'SHA512The quick brown fox jumps over the lazy dog');
+output( hashedValue512 );
+
+
+//Try again on previously instantiated modules
+output('Combined SHA* tests');
+
+DATA RehashedValue := hashModuleSHA1.Hash((DATA)'SHA1The quick brown fox jumps over the lazy dog');
+output( RehashedValue );
+
+DATA RehashedValue224 := hashModuleSHA224.Hash((DATA)'SHA224The quick brown fox jumps over the lazy dog');
+output( RehashedValue224 );
+
+DATA RehashedValue256 := hashModuleSHA256.Hash((DATA)'SHA256The quick brown fox jumps over the lazy dog');
+output( RehashedValue256 );
+
+DATA RehashedValue384 := hashModuleSHA384.Hash((DATA)'SHA384The quick brown fox jumps over the lazy dog');
+output( RehashedValue384 );
+
+DATA RehashedValue512 := hashModuleSHA512.Hash((DATA)'SHA512The quick brown fox jumps over the lazy dog');
+output( RehashedValue512 );
+
+

+ 107 - 0
testing/regress/ecl/cryptoplugin_pke.ecl

@@ -0,0 +1,107 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2019 HPCC Systems®.
+
+    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.
+############################################################################## */
+import Std;
+
+output('PKIEncryption Tests enumerating supported algorithms');
+
+output(Std.Crypto.SupportedPublicKeyAlgorithms());
+
+
+STRING pubKey := '-----BEGIN PUBLIC KEY-----' + '\n' +
+'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr64RncTp5pV0KMnWRAof' + '\n' +
+'od+3AUS/IDngT39j3Iovv9aI2N8g4W5ipqhKftRESmzQ6I/TiUQcmi42soUXmCeE' + '\n' +
+'BHqlMDydw9aHOQG17CB30GYsw3Lf8iZo7RC7ocQE3OcRzH0eBkOryW6X3efWnMoy' + '\n' +
+'hIR9MexCldF+3WM/X0IX0ApSs7kuVPVG4Yj202+1FVO/XNwjMukJG5ASuxpYAQvv' + '\n' +
+'/oKj6q7kInEIvhLiGfcm3bpTzWQ66zVz3z/huLbEXEy5oj2fQaC5E3s5mdpk/CW3' + '\n' +
+'J6Tk4NY3NySWzE/2/ZOWxZdR79XC+goNL6v/5gPI8B/a3Z8OeM2PfSZwPMnVuvU0' + '\n' +
+'bwIDAQAB' + '\n' +
+'-----END PUBLIC KEY-----';
+
+
+STRING privKey := '-----BEGIN RSA PRIVATE KEY-----' + '\n' +
+'MIIEowIBAAKCAQEAr64RncTp5pV0KMnWRAofod+3AUS/IDngT39j3Iovv9aI2N8g' + '\n' +
+'4W5ipqhKftRESmzQ6I/TiUQcmi42soUXmCeEBHqlMDydw9aHOQG17CB30GYsw3Lf' + '\n' +
+'8iZo7RC7ocQE3OcRzH0eBkOryW6X3efWnMoyhIR9MexCldF+3WM/X0IX0ApSs7ku' + '\n' +
+'VPVG4Yj202+1FVO/XNwjMukJG5ASuxpYAQvv/oKj6q7kInEIvhLiGfcm3bpTzWQ6' + '\n' +
+'6zVz3z/huLbEXEy5oj2fQaC5E3s5mdpk/CW3J6Tk4NY3NySWzE/2/ZOWxZdR79XC' + '\n' +
+'+goNL6v/5gPI8B/a3Z8OeM2PfSZwPMnVuvU0bwIDAQABAoIBAQCnGAtNYkOOu8wW' + '\n' +
+'F5Oid3aKwnwPytF211WQh3v2AcFU17qle+SMRi+ykBL6+u5RU5qH+HSc9Jm31AjW' + '\n' +
+'V1yPrdYVZInFjYIJCPzorcXY5zDOmMAuzg5PBVV7VhUA0a5GZck6FC8AilDUcEom' + '\n' +
+'GCK6Ul8mR9XELBFQ6keeTo2yDu0TQ4oBXrPBMN61uMHCxh2tDb2yvl8Zz+EllADG' + '\n' +
+'70pztRWNOrCzrC+ARlmmDfYOUgVFtZin53jq6O6ullPLzhkm3/+QFRGYWsFgQB6J' + '\n' +
+'Z9HJtW5YB47RT5RbLHKXeMc6IJW+d+5HrzgTdK79P7wAZk8JCIDyHe2AaNAUzc/G' + '\n' +
+'sB0cNeURAoGBAOKtaVFa6z2F4Q+koMBXCt4m7dCJnaC+qthF249uEOIBeF3ds9Fq' + '\n' +
+'f0jhhvuV0OcN8lYbR/ZlYRJDUs6mHh/2BYSkdeaLKojXTxKR2bA4xQk5dtJCdoPf' + '\n' +
+'0c15AlTgOYk2oNXP/azDICJYT/cdvIdUL9P4IoZthu1FjwG266GacEnNAoGBAMZn' + '\n' +
+'1wRUXS1dbqemoc+g48wj5r3/qsIG8PsZ2Y8W+oYW7diNA5o6acc8YPEWE2RbJDbX' + '\n' +
+'YEADBnRSdzzOdo0JEj4VbNZEtx6nQhBOOrtYKnnqHVI/XOz3VVu6kedUKdBR87KC' + '\n' +
+'eCzO1VcEeZtsTHuLO4t7NmdHGqNxTV+jLvzBoQsrAoGAI+fOD+nz6znirYSpRe5D' + '\n' +
+'tW67KtYxlr28+CcQoUaQ/Au5kjzE9/4DjXrT09QmVAMciNEnc/sZBjiNzFf525wv' + '\n' +
+'wZP/bPZMVYKtbsaVkdlcNJranHGUrkzswbxSRzmBQ5/YmCWrDAuYcnhEqmMWcuU9' + '\n' +
+'8jiS13JP9hOXlHDyIBYDhV0CgYBV6TznuQgnzp9NpQ/H8ijxilItz3lHTu4mLMlR' + '\n' +
+'9mdAjMkszdLTg5uuE+z+N8rp17VUseoRjb3LvLG4+MXIyDbH/0sDdPm+IjqvCNDR' + '\n' +
+'spmh9MgBh0JbsbWaZK0s9/qrI/FcSLZ04JLsfRmTPU/Y5y8/dHjYO6fDQhp44RZF' + '\n' +
+'iCqNxQKBgHf7KZIOKgV4YNyphk1UYWHNz8YY5o7WtaQ51Q+kIbU8PRd9rqJLZyk2' + '\n' +
+'tKf8e6z+wtKjxi8GKQzE/IdkQqiFmB1yEjjRHQ81WS+K5NnjN1t0IEscJqOAwv9s' + '\n' +
+'iIhG5ueb6xoj/N0LuXa8loUT5aChKWxRHEYdegqU48f+qxUcJj9R' + '\n' +
+'-----END RSA PRIVATE KEY-----';
+
+
+encModule := Std.Crypto.PublicKeyEncryptionFromBuffer('SHA256', pubKey, privKey, '');
+
+//Digital Signature tests
+
+DATA signature := encModule.Sign((DATA)'The quick brown fox jumps over the lazy dog');
+output( TRUE = encModule.VerifySignature(signature, (DATA)'The quick brown fox jumps over the lazy dog'));
+output(FALSE = encModule.VerifySignature(signature, (DATA)'Your Name Here'));
+
+DATA bogus := (DATA)'Not a valid signature';
+output(FALSE = encModule.VerifySignature(bogus, (DATA)'Not a valid signature'));
+
+
+DATA sig256Ex := encModule.Sign((DATA)'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTTUVWXYZ`~!@#$%^&*()_-+=|}]{[":;?/>.<,');
+output(TRUE = encModule.VerifySignature(sig256Ex, (DATA)'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTTUVWXYZ`~!@#$%^&*()_-+=|}]{[":;?/>.<,'));
+
+//Encrypt/Decrypt tests
+
+DATA encrypted := encModule.Encrypt((DATA)'The quick brown fox jumps over the lazy dog');
+output( (STRING)encModule.Decrypt(encrypted) );
+output( (STRING)encModule.Decrypt(encrypted) );
+output( (STRING)encModule.Decrypt(encrypted) );
+output( (STRING)encModule.Decrypt(encrypted) );
+output( (STRING)encModule.Decrypt(encrypted) );
+
+
+encModuleBuff := Std.Crypto.PublicKeyEncryptionFromBuffer('SHA256', pubKey, privKey, '');
+
+DATA sigBuff := encModuleBuff.Sign((DATA)'The quick brown fox jumps over the lazy dog');
+output(encModuleBuff.VerifySignature(sigBuff, (DATA)'The quick brown fox jumps over the lazy dog'));//TRUE
+output(encModuleBuff.VerifySignature(sigBuff, (DATA)'The quick brown fox jumps over the lazy dog'));//TRUE
+output(encModuleBuff.VerifySignature(sigBuff, (DATA)'The quick brown fox jumps over the lazy dog'));//TRUE
+output(encModuleBuff.VerifySignature(sigBuff, (DATA)'The quick brown fox jumps over the lazy dog'));//TRUE
+output(encModuleBuff.VerifySignature(sigBuff, (DATA)'The quick brown fox jumps over the lazy dog'));//TRUE
+output(encModuleBuff.VerifySignature(sigBuff, (DATA)'The quick brown fox jumps over the lazy dog'));//TRUE
+
+DATA pkiDat := encModuleBuff.Encrypt((DATA)'The quick brown fox jumps over the lazy dog');
+output( (STRING)encModuleBuff.Decrypt(pkiDat) );
+output( (STRING)encModuleBuff.Decrypt(pkiDat) );
+output( (STRING)encModuleBuff.Decrypt(pkiDat) );
+output( (STRING)encModuleBuff.Decrypt(pkiDat) );
+output( (STRING)encModuleBuff.Decrypt(pkiDat) );
+output( (STRING)encModuleBuff.Decrypt(pkiDat) );
+
+

+ 55 - 0
testing/regress/ecl/cryptoplugin_ske.ecl

@@ -0,0 +1,55 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2019 HPCC Systems®.
+
+    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.
+############################################################################## */
+import Std;
+
+output(Std.Crypto.SupportedSymmetricCipherAlgorithms());
+
+output('aes-256-cbc tests');
+SymmModule256 := Std.Crypto.SymmetricEncryption( 'aes-256-cbc', '01234567890123456789012345678901' );
+DATA dat256 := SymmModule256.Encrypt( (DATA)'The quick brown fox jumps over the lazy dog');
+output( (STRING)SymmModule256.Decrypt(dat256) );
+
+DATA dat256Ex := SymmModule256.Encrypt( (DATA)'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTTUVWXYZ`~!@#$%^&*()_-+=|}]{[":;?/>.<,');
+output( (STRING)SymmModule256.Decrypt(dat256Ex) );
+
+output('aes-192-cbc tests');
+SymmModule192 := Std.Crypto.SymmetricEncryption( 'aes-192-cbc', '012345678901234567890123' );
+DATA dat192 := SymmModule192.Encrypt( (DATA)'The quick brown fox jumps over the lazy dog');
+output( (STRING)SymmModule192.Decrypt(dat192) );
+
+output('aes-128-cbc tests');
+SymmModule128 := Std.Crypto.SymmetricEncryption( 'aes-128-cbc', '0123456789012345' );
+DATA dat128 := SymmModule128.Encrypt( (DATA)'The quick brown fox jumps over the lazy dog');
+output( (STRING)SymmModule128.Decrypt(dat128) );
+
+//Try again on previously instantiated modules
+
+output('aes-xxx-cbc combined tests');
+DATA dat256ExEx := SymmModule256.Encrypt( (DATA)'256The quick brown fox jumps over the lazy dog');
+output ( (STRING)SymmModule256.Decrypt(dat256ExEx) );
+output ( (STRING)SymmModule256.Decrypt(dat256ExEx) );
+output ( (STRING)SymmModule256.Decrypt(dat256ExEx) );
+
+DATA dat192Ex := SymmModule192.Encrypt( (DATA)'192The quick brown fox jumps over the lazy dog');
+output ( (STRING)SymmModule192.Decrypt(dat192Ex) );
+output ( (STRING)SymmModule192.Decrypt(dat192Ex) );
+output ( (STRING)SymmModule192.Decrypt(dat192Ex) );
+
+DATA dat128Ex := SymmModule128.Encrypt( (DATA)'128The quick brown fox jumps over the lazy dog');
+output( (STRING)SymmModule128.Decrypt(dat128Ex) );
+output( (STRING)SymmModule128.Decrypt(dat128Ex) );
+output( (STRING)SymmModule128.Decrypt(dat128Ex) );

+ 57 - 0
testing/regress/ecl/key/cryptoplugin_hash.xml

@@ -0,0 +1,57 @@
+<Dataset name='Result 1'>
+ <Row><Result_1><Item>SHA1</Item><Item>SHA224</Item><Item>SHA256</Item><Item>SHA384</Item><Item>SHA512</Item></Result_1></Row>
+</Dataset>
+<Dataset name='Result 2'>
+ <Row><Result_2>SHA1 tests</Result_2></Row>
+</Dataset>
+<Dataset name='Result 3'>
+ <Row><Result_3>23BAFEB89163FFC27029B3736311810FD4BDFD9D</Result_3></Row>
+</Dataset>
+<Dataset name='Result 4'>
+ <Row><Result_4>0E86AFC81C17EAE6C7D6E9304A43A34E0809B25F</Result_4></Row>
+</Dataset>
+<Dataset name='Result 5'>
+ <Row><Result_5>0E86AFC81C17EAE6C7D6E9304A43A34E0809B25F</Result_5></Row>
+</Dataset>
+<Dataset name='Result 6'>
+ <Row><Result_6>SHA224 tests</Result_6></Row>
+</Dataset>
+<Dataset name='Result 7'>
+ <Row><Result_7>FE3E6060CE32A22BAC04E7CB699942516E8CFA69090C9543526B6FEF</Result_7></Row>
+</Dataset>
+<Dataset name='Result 8'>
+ <Row><Result_8>SHA256 tests</Result_8></Row>
+</Dataset>
+<Dataset name='Result 9'>
+ <Row><Result_9>10E051175BC5400D5F3B6D9953DCB17677B4B9493E178F47C35D9D8A8DB7D510</Result_9></Row>
+</Dataset>
+<Dataset name='Result 10'>
+ <Row><Result_10>SHA384 tests</Result_10></Row>
+</Dataset>
+<Dataset name='Result 11'>
+ <Row><Result_11>AB0FE7E8C4129D243AD821280024B59575DE83296203B446E68D58695BE022A8</Result_11></Row>
+</Dataset>
+<Dataset name='Result 12'>
+ <Row><Result_12>SHA512 tests</Result_12></Row>
+</Dataset>
+<Dataset name='Result 13'>
+ <Row><Result_13>18C8C050337567DFB8AB37B6D7132404A2FD0A9104F78C7A981283DF4AF2B84CF0A88A7D25D6E2640A5B176CA7BF453B60026A9A88507C6B0AF352F185AB831D</Result_13></Row>
+</Dataset>
+<Dataset name='Result 14'>
+ <Row><Result_14>Combined SHA* tests</Result_14></Row>
+</Dataset>
+<Dataset name='Result 15'>
+ <Row><Result_15>23BAFEB89163FFC27029B3736311810FD4BDFD9D</Result_15></Row>
+</Dataset>
+<Dataset name='Result 16'>
+ <Row><Result_16>FE3E6060CE32A22BAC04E7CB699942516E8CFA69090C9543526B6FEF</Result_16></Row>
+</Dataset>
+<Dataset name='Result 17'>
+ <Row><Result_17>10E051175BC5400D5F3B6D9953DCB17677B4B9493E178F47C35D9D8A8DB7D510</Result_17></Row>
+</Dataset>
+<Dataset name='Result 18'>
+ <Row><Result_18>AB0FE7E8C4129D243AD821280024B59575DE83296203B446E68D58695BE022A8</Result_18></Row>
+</Dataset>
+<Dataset name='Result 19'>
+ <Row><Result_19>18C8C050337567DFB8AB37B6D7132404A2FD0A9104F78C7A981283DF4AF2B84CF0A88A7D25D6E2640A5B176CA7BF453B60026A9A88507C6B0AF352F185AB831D</Result_19></Row>
+</Dataset>

+ 69 - 0
testing/regress/ecl/key/cryptoplugin_pke.xml

@@ -0,0 +1,69 @@
+<Dataset name='Result 1'>
+ <Row><Result_1>PKIEncryption Tests enumerating supported algorithms</Result_1></Row>
+</Dataset>
+<Dataset name='Result 2'>
+ <Row><Result_2><Item>SHA256</Item></Result_2></Row>
+</Dataset>
+<Dataset name='Result 3'>
+ <Row><Result_3>true</Result_3></Row>
+</Dataset>
+<Dataset name='Result 4'>
+ <Row><Result_4>true</Result_4></Row>
+</Dataset>
+<Dataset name='Result 5'>
+ <Row><Result_5>true</Result_5></Row>
+</Dataset>
+<Dataset name='Result 6'>
+ <Row><Result_6>true</Result_6></Row>
+</Dataset>
+<Dataset name='Result 7'>
+ <Row><Result_7>The quick brown fox jumps over the lazy dog</Result_7></Row>
+</Dataset>
+<Dataset name='Result 8'>
+ <Row><Result_8>The quick brown fox jumps over the lazy dog</Result_8></Row>
+</Dataset>
+<Dataset name='Result 9'>
+ <Row><Result_9>The quick brown fox jumps over the lazy dog</Result_9></Row>
+</Dataset>
+<Dataset name='Result 10'>
+ <Row><Result_10>The quick brown fox jumps over the lazy dog</Result_10></Row>
+</Dataset>
+<Dataset name='Result 11'>
+ <Row><Result_11>The quick brown fox jumps over the lazy dog</Result_11></Row>
+</Dataset>
+<Dataset name='Result 12'>
+ <Row><Result_12>true</Result_12></Row>
+</Dataset>
+<Dataset name='Result 13'>
+ <Row><Result_13>true</Result_13></Row>
+</Dataset>
+<Dataset name='Result 14'>
+ <Row><Result_14>true</Result_14></Row>
+</Dataset>
+<Dataset name='Result 15'>
+ <Row><Result_15>true</Result_15></Row>
+</Dataset>
+<Dataset name='Result 16'>
+ <Row><Result_16>true</Result_16></Row>
+</Dataset>
+<Dataset name='Result 17'>
+ <Row><Result_17>true</Result_17></Row>
+</Dataset>
+<Dataset name='Result 18'>
+ <Row><Result_18>The quick brown fox jumps over the lazy dog</Result_18></Row>
+</Dataset>
+<Dataset name='Result 19'>
+ <Row><Result_19>The quick brown fox jumps over the lazy dog</Result_19></Row>
+</Dataset>
+<Dataset name='Result 20'>
+ <Row><Result_20>The quick brown fox jumps over the lazy dog</Result_20></Row>
+</Dataset>
+<Dataset name='Result 21'>
+ <Row><Result_21>The quick brown fox jumps over the lazy dog</Result_21></Row>
+</Dataset>
+<Dataset name='Result 22'>
+ <Row><Result_22>The quick brown fox jumps over the lazy dog</Result_22></Row>
+</Dataset>
+<Dataset name='Result 23'>
+ <Row><Result_23>The quick brown fox jumps over the lazy dog</Result_23></Row>
+</Dataset>

+ 54 - 0
testing/regress/ecl/key/cryptoplugin_ske.xml

@@ -0,0 +1,54 @@
+<Dataset name='Result 1'>
+ <Row><Result_1><Item>aes-256-cbc</Item><Item>aes-192-cbc</Item><Item>aes-128-cbc</Item></Result_1></Row>
+</Dataset>
+<Dataset name='Result 2'>
+ <Row><Result_2>aes-256-cbc tests</Result_2></Row>
+</Dataset>
+<Dataset name='Result 3'>
+ <Row><Result_3>The quick brown fox jumps over the lazy dog</Result_3></Row>
+</Dataset>
+<Dataset name='Result 4'>
+ <Row><Result_4>0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTTUVWXYZ`~!@#$%^&amp;*()_-+=|}]{[&quot;:;?/&gt;.&lt;,</Result_4></Row>
+</Dataset>
+<Dataset name='Result 5'>
+ <Row><Result_5>aes-192-cbc tests</Result_5></Row>
+</Dataset>
+<Dataset name='Result 6'>
+ <Row><Result_6>The quick brown fox jumps over the lazy dog</Result_6></Row>
+</Dataset>
+<Dataset name='Result 7'>
+ <Row><Result_7>aes-128-cbc tests</Result_7></Row>
+</Dataset>
+<Dataset name='Result 8'>
+ <Row><Result_8>The quick brown fox jumps over the lazy dog</Result_8></Row>
+</Dataset>
+<Dataset name='Result 9'>
+ <Row><Result_9>aes-xxx-cbc combined tests</Result_9></Row>
+</Dataset>
+<Dataset name='Result 10'>
+ <Row><Result_10>256The quick brown fox jumps over the lazy dog</Result_10></Row>
+</Dataset>
+<Dataset name='Result 11'>
+ <Row><Result_11>256The quick brown fox jumps over the lazy dog</Result_11></Row>
+</Dataset>
+<Dataset name='Result 12'>
+ <Row><Result_12>256The quick brown fox jumps over the lazy dog</Result_12></Row>
+</Dataset>
+<Dataset name='Result 13'>
+ <Row><Result_13>192The quick brown fox jumps over the lazy dog</Result_13></Row>
+</Dataset>
+<Dataset name='Result 14'>
+ <Row><Result_14>192The quick brown fox jumps over the lazy dog</Result_14></Row>
+</Dataset>
+<Dataset name='Result 15'>
+ <Row><Result_15>192The quick brown fox jumps over the lazy dog</Result_15></Row>
+</Dataset>
+<Dataset name='Result 16'>
+ <Row><Result_16>128The quick brown fox jumps over the lazy dog</Result_16></Row>
+</Dataset>
+<Dataset name='Result 17'>
+ <Row><Result_17>128The quick brown fox jumps over the lazy dog</Result_17></Row>
+</Dataset>
+<Dataset name='Result 18'>
+ <Row><Result_18>128The quick brown fox jumps over the lazy dog</Result_18></Row>
+</Dataset>