commit b49a3d0301dedc30380097e5ae7cb954e07644a8 Author: Chord Date: Thu Apr 21 21:45:12 2016 -0400 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fa0d5b8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +*.o +*.so +*.dll +*.exe +*.a +*.pyc +*.stackdump +.gdb_history diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..e5954a7 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "external/psf-cryptopp"] + path = external/psf-cryptopp + url = https://github.com/psforever/psf-cryptopp.git diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0013374 --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +CRYPTOPP_DIR=external/psf-cryptopp +CRYPTOPP_LIB=$(CRYPTOPP_DIR)/libcryptopp.a +PSCRYPTO=pscrypto/pscrypto.dll + +all : $(CRYPTOPP_LIB) $(PSCRYPTO) + +$(CRYPTOPP_LIB) : + $(MAKE) -C $(CRYPTOPP_DIR) + +$(PSCRYPTO) : $(CRYPTOPP_LIB) + $(MAKE) -C pscrypto/ + +clean : + $(MAKE) -C pscrypto/ clean + $(MAKE) -C $(CRYPTOPP_DIR) clean diff --git a/README.md b/README.md new file mode 100644 index 0000000..40ec814 --- /dev/null +++ b/README.md @@ -0,0 +1,28 @@ +# PSCrypto +A wrapper around CryptoPP for use with Scala or Java. + +```shell +$ git clone --recursive https://github.com/psforever/psf-cryptopp.git +``` + +Or if you already cloned without getting the submodules + +```shell +git submodule update --init --recursive +``` + +## Building +GNU Make and a c++ compiler required. + +```shell +$ make -j4 +``` + +## Cross Compiling +Use the environment variable `PREFIX` to define a compiler tuple for building. For example + +```shell +$ PREFIX=x86_64-w64-mingw32- make -j4 +``` + +This will build a `pscrypto.dll` for 64-bit Windows. diff --git a/external/psf-cryptopp b/external/psf-cryptopp new file mode 160000 index 0000000..d9be78c --- /dev/null +++ b/external/psf-cryptopp @@ -0,0 +1 @@ +Subproject commit d9be78c72cbe270efecd90193f16b10007b6aa1d diff --git a/pscrypto/.gitignore b/pscrypto/.gitignore new file mode 100644 index 0000000..a623115 --- /dev/null +++ b/pscrypto/.gitignore @@ -0,0 +1,2 @@ +pscrypto +test diff --git a/pscrypto/Makefile b/pscrypto/Makefile new file mode 100644 index 0000000..3d22f5d --- /dev/null +++ b/pscrypto/Makefile @@ -0,0 +1,43 @@ +SRCS = pscrypto.cpp +OBJS := $(SRCS:.cpp=.o) + +# TODO: this needs to be fixed for linux +LIB = pscrypto.dll +TEST = pscrypto + +AR = $(PREFIX)ar +CXX = $(PREFIX)g++ +LD = $(PREFIX)g++ +STRIP = $(PREFIX)strip + +CXXFLAGS := $(CFLAGS) -DBUILD_DLL -I../external/psf-cryptopp -fPIC +LDFLAGS := -L../external/psf-cryptopp -static-libgcc -static-libstdc++ + +ifdef DEBUG +CXXFLAGS += -g +else +CXXFLAGS += -O2 -DNDEBUG +endif + +LIB_FLAGS=$(LDFLAGS) -Wl,-soname=$(LIB) +LIBS=-lcryptopp + +all : $(OBJS) $(LIB) $(TEST) + +%.o : %.cpp + $(CXX) $(CXXFLAGS) -c $< -o $@ + +$(LIB) : $(OBJS) + $(CXX) -shared $< -o $(LIB) $(LIB_FLAGS) $(LIBS) +ifndef DEBUG + $(STRIP) $(LIB) +endif + +$(TEST) : $(OBJS) + $(CXX) $(OBJS) -o $(TEST) $(LDFLAGS) $(LIBS) +ifndef DEBUG + $(STRIP) $(TEST) +endif + +clean : + rm -f $(OBJS) $(LIB) *.pyc diff --git a/pscrypto/__init__.py b/pscrypto/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pscrypto/pscrypto.cpp b/pscrypto/pscrypto.cpp new file mode 100644 index 0000000..2dbc1f9 --- /dev/null +++ b/pscrypto/pscrypto.cpp @@ -0,0 +1,401 @@ +// PSCrypto - PSForever +// https://cryptopp.com/wiki/Diffie-Hellman + +#ifdef BUILD_DLL +#define DLL_EXPORT extern "C" __declspec(dllexport) +#else +#define DLL_EXPORT extern "C" __declspec(dllimport) +#endif + +#include "osrng.h" +using CryptoPP::AutoSeededRandomPool; + +#include +using std::cout; +using std::cerr; +using std::endl; + +#include +using std::string; + +#include +using std::exit; + +#include "cryptlib.h" +using CryptoPP::Exception; + +#include "hmac.h" +using CryptoPP::HMAC; + +#include "sha.h" +using CryptoPP::SHA256; + +#include "md5.h" +using CryptoPP::MD5; + +#include "rc5.h" +using CryptoPP::RC5; + +#include "dh.h" +using CryptoPP::DH; +using CryptoPP::DH_Domain; +using CryptoPP::DL_GroupParameters_GFP_DefaultSafePrime; +using CryptoPP::DL_GroupParameters_IntegerBasedImpl; + +#include "integer.h" +using CryptoPP::Integer; + +#include "hex.h" +using CryptoPP::HexEncoder; +using CryptoPP::HexDecoder; + +#include "md5mac.h" +using CryptoPP::MD5MAC; + +#include "filters.h" +using CryptoPP::StringSink; +using CryptoPP::StringSource; +using CryptoPP::HashFilter; +using CryptoPP::HashVerificationFilter; + +#include "secblock.h" +using CryptoPP::SecByteBlock; + +#include +#include +#include +using namespace std; + +DLL_EXPORT DH * DH_Start(const byte * p, const byte * g, byte * privKey, byte * pubKey); +bool ValidateMD5MAC(); + +#define min(x, y) (((x) > (y)) ? (y) : (x)) + +/*key = "377b60f8790f91b35a9da82945743da9" +label = "master secret" +msg = "b4aea1559444a20b6112a2892de40eac00000000c8aea155b53d187076b79abab59001b600000000" +#msg = "" +expect = "5aa15de41f5220cf5cca489155e1438c5aa15de4" + +print "Key: " + key +print "Msg: " + msg + +# append the label +msg = label + hexToBin(msg)*/ + +int main(int argc, char* argv[]) +{ + DH dh; + AutoSeededRandomPool rnd(0x128); + + cout << "Generating parameters..." << endl; + dh.AccessGroupParameters().Initialize(rnd, 128); + // for server, we are given p and g + // use this: dh.AccessGroupParameters().Initialize(p, g); + + cout << "Generating Keypair..." << endl; + + SecByteBlock privKey(dh.PrivateKeyLength()); + SecByteBlock pubKey(dh.PublicKeyLength()); + dh.GenerateKeyPair(rnd, privKey, pubKey); + + const Integer& p = dh.GetGroupParameters().GetModulus(); + cout << "P: " << hex << p << endl; + + Integer q = (p-1)/2; + cout << "Q: " << q << endl; + + const Integer& g = dh.GetGroupParameters().GetGenerator(); + cout << "G: " << g << endl; + + Integer r = dh.GetGroupParameters().GetSubgroupOrder(); + cout << "Subgroup order: " << r << endl; + + cout << "Key generation test..." << endl; + + byte buf1[16] = { + 'a','a','b','b', + 'a','a','b','b', + 'a','a','b','b', + 'a','a','b','c'}; + byte buf2[16]; + byte buf3[16]; + + + cout << "Output " << DH_Start(buf1, buf1, buf2, buf3) << endl; + + return 0; +} + +DLL_EXPORT DH * DH_Start(const byte * p, const byte * g, byte * privKey, byte * pubKey) +{ + DH * dh = new DH(); + if(!dh) + return NULL; + + AutoSeededRandomPool rnd(0x128); + Integer pInt(p, 0x10); + Integer gInt(g, 0x10); + + dh->AccessGroupParameters().Initialize(pInt, gInt); + dh->GenerateKeyPair(rnd, privKey, pubKey); + + return dh; +} + +DLL_EXPORT DH * DH_Start_Generate(byte * privKey, byte * pubKey, byte * p, byte * g) +{ + DH * dh = new DH(); + AutoSeededRandomPool rnd; + + if(!dh) + return NULL; + + dh->AccessGroupParameters().Initialize(rnd, 128); + dh->GenerateKeyPair(rnd, privKey, pubKey); + + const Integer& pInt = dh->GetGroupParameters().GetModulus(); + const Integer& gInt = dh->GetGroupParameters().GetGenerator(); + + pInt.Encode(p, 0x10); + gInt.Encode(g, 0x10); + + return dh; +} + +DLL_EXPORT bool DH_Agree(DH * dh, byte * agreedValue, const byte * privKey, + const byte * otherPubKey) +{ + if(!dh || !agreedValue || !privKey || !otherPubKey) + return false; + + return dh->Agree(agreedValue, privKey, otherPubKey, true); +} + +DLL_EXPORT void * RC5_Init(byte * key, size_t keyLen, bool encrypt) +{ + if(!key || !keyLen) + return NULL; + + if(encrypt) + return new RC5::Encryption(key, keyLen); + else + return new RC5::Decryption(key, keyLen); + +} + +DLL_EXPORT bool RC5_Decrypt(RC5::Decryption * dec, byte * ct, size_t ctLen, byte * pt) +{ + if(!dec || !ct || !pt || ctLen & (dec->BlockSize()-1)) + return false; + + for(int i = 0; i < ctLen; i+=dec->BlockSize()) + dec->ProcessAndXorBlock(ct+i, NULL, pt+i); + + return true; +} + +DLL_EXPORT bool RC5_Encrypt(RC5::Encryption * enc, byte * pt, size_t ptLen, byte * ct) +{ + if(!enc || !ct || !pt || ptLen & (enc->BlockSize()-1)) + return false; + + for(int i = 0; i < ptLen; i+= enc->BlockSize()) + enc->ProcessAndXorBlock(pt+i, NULL, ct+i); + + return true; +} + +DLL_EXPORT bool MD5_MAC(byte * key, size_t keyLen, byte * msg, size_t msgLen, byte * outBuf, size_t outBufLen) +{ + if(!key || !msg || !outBuf) + return false; + + byte localKey[16]; + byte digest[MD5MAC::DIGESTSIZE]; + + memset(digest, 0, sizeof(digest)); + memset(localKey, 0, sizeof(localKey)); + memcpy(localKey, key, min(keyLen, 16)); + + // key length of 16 bytes or less + MD5MAC mac(localKey); + + mac.Update(msg, msgLen); + mac.Final(digest); + + for(size_t i = 0; i < outBufLen; i += MD5MAC::DIGESTSIZE) + memcpy(outBuf+i, digest, min(MD5MAC::DIGESTSIZE, outBufLen-i)); + + return true; +} + +DLL_EXPORT void Free_DH(DH * ptr) +{ + delete ptr; +} + +DLL_EXPORT void Free_RC5(RC5 * ptr) +{ + delete ptr; +} + +DLL_EXPORT void MD5Test() +{ + const byte key[] = {0x37, 0x7b, 0x60, 0xf8, 0x79, 0x0f, 0x91, 0xb3, 0x5a, 0x9d, 0xa8, 0x29, 0x45, 0x74, 0x3d, 0xa9}; + const byte msg[] = {'m', 'a', 's', 't', 'e', 'r', ' ', 's', 'e', 'c', 'r', 'e', 't', + 0xb4, 0xae, 0xa1, 0x55, 0x94, 0x44, 0xa2, 0x0b, 0x61, 0x12, 0xa2, 0x89, 0x2d, 0xe4, 0x0e, 0xac, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xae, 0xa1, 0x55, 0xb5, 0x3d, 0x18, 0x70, 0x76, 0xb7, 0x9a, 0xba, 0xb5, 0x90, 0x01, 0xb6, 0x00, 0x00, 0x00, 0x00}; + const byte output[] = {0x5a, 0xa1, 0x5d, 0xe4, 0x1f, 0x52, 0x20, 0xcf, 0x5c, 0xca, 0x48, 0x91, 0x55, 0xe1, 0x43, 0x8c, 0x5a, 0xa1, 0x5d, 0xe4}; + byte digest[MD5MAC::DIGESTSIZE+4]; + string encoded; + + std::ios::sync_with_stdio(true); + + MD5MAC mac(key); + + StringSource(key, sizeof(key), true, + new HexEncoder( + new StringSink(encoded) + ) // HexEncoder + ); // StringSource + cout << "key: " << encoded << endl; + + encoded = ""; + + StringSource(msg, sizeof(msg), true, + new HexEncoder( + new StringSink(encoded) + ) // HexEncoder + ); // StringSource + cout << "msg: " << encoded << endl; + + encoded = ""; + + StringSource(output, sizeof(output), true, + new HexEncoder( + new StringSink(encoded) + ) // HexEncoder + ); // StringSource + cout << "expected: " << encoded << endl; + + mac.Update(msg, sizeof(msg)); + mac.Final(digest); + + encoded = ""; + + StringSource(digest, sizeof(digest), true, + new HexEncoder( + new StringSink(encoded) + ) // HexEncoder + ); // StringSource + cout << "got: " << encoded << endl; + +} + +void HMACTest() +{ + AutoSeededRandomPool prng; + + unsigned char fixedKey[16] = {0x37, 0x7b, 0x60, 0xf8, 0x79, 0x0f, 0x91, 0xb3, 0x5a, 0x9d, 0xa8, 0x29, 0x45, 0x74, 0x3d, 0xa9}; + SecByteBlock key(fixedKey, 16); + + //for(int i = 0; i++; i < 16) + //key[i] = fixedKey[i]; + //prng.GenerateBlock(key, key.size()); + + string plain = "master secret"; + string mac, encoded; + + /*********************************\ + \*********************************/ + + // Pretty print key + encoded.clear(); + StringSource(key, key.size(), true, + new HexEncoder( + new StringSink(encoded) + ) // HexEncoder + ); // StringSource + cout << "key: " << encoded << endl; + + cout << "plain text: " << plain << endl; + + /*********************************\ + \*********************************/ + + try + { + HMAC< MD5 > hmac(key, key.size()); + + StringSource(plain, true, + new HashFilter(hmac, + new StringSink(mac) + ) // HashFilter + ); // StringSource + } + catch(const CryptoPP::Exception& e) + { + cerr << e.what() << endl; + exit(1); + } +} + +bool ValidateMD5MAC() +{ + const byte keys[2][MD5MAC::KEYLENGTH]={ + {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff}, + {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10}}; + + const char *TestVals[7]={ + "", + "a", + "abc", + "message digest", + "abcdefghijklmnopqrstuvwxyz", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"}; + + const byte output[2][7][MD5MAC::DIGESTSIZE]={ + {{0x1f,0x1e,0xf2,0x37,0x5c,0xc0,0xe0,0x84,0x4f,0x98,0xe7,0xe8,0x11,0xa3,0x4d,0xa8}, + {0x7a,0x76,0xee,0x64,0xca,0x71,0xef,0x23,0x7e,0x26,0x29,0xed,0x94,0x52,0x73,0x65}, + {0xe8,0x01,0x3c,0x11,0xf7,0x20,0x9d,0x13,0x28,0xc0,0xca,0xa0,0x4f,0xd0,0x12,0xa6}, + {0xc8,0x95,0x53,0x4f,0x22,0xa1,0x74,0xbc,0x3e,0x6a,0x25,0xa2,0xb2,0xef,0xd6,0x30}, + {0x91,0x72,0x86,0x7e,0xb6,0x00,0x17,0x88,0x4c,0x6f,0xa8,0xcc,0x88,0xeb,0xe7,0xc9}, + {0x3b,0xd0,0xe1,0x1d,0x5e,0x09,0x4c,0xb7,0x1e,0x35,0x44,0xac,0xa9,0xb8,0xbf,0xa2}, + {0x93,0x37,0x16,0x64,0x44,0xcc,0x95,0x35,0xb7,0xd5,0xb8,0x0f,0x91,0xe5,0x29,0xcb}}, + {{0x2f,0x6e,0x73,0x13,0xbf,0xbb,0xbf,0xcc,0x3a,0x2d,0xde,0x26,0x8b,0x59,0xcc,0x4d}, + {0x69,0xf6,0xca,0xff,0x40,0x25,0x36,0xd1,0x7a,0xe1,0x38,0x03,0x2c,0x0c,0x5f,0xfd}, + {0x56,0xd3,0x2b,0x6c,0x34,0x76,0x65,0xd9,0x74,0xd6,0xf7,0x5c,0x3f,0xc6,0xf0,0x40}, + {0xb8,0x02,0xb2,0x15,0x4e,0x59,0x8b,0x6f,0x87,0x60,0x56,0xc7,0x85,0x46,0x2c,0x0b}, + {0x5a,0xde,0xf4,0xbf,0xf8,0x04,0xbe,0x08,0x58,0x7e,0x94,0x41,0xcf,0x6d,0xbd,0x57}, + {0x18,0xe3,0x49,0xa5,0x24,0x44,0xb3,0x0e,0x5e,0xba,0x5a,0xdd,0xdc,0xd9,0xf1,0x8d}, + {0xf2,0xb9,0x06,0xa5,0xb8,0x4b,0x9b,0x4b,0xbe,0x95,0xed,0x32,0x56,0x4e,0xe7,0xeb}}}; + + byte digest[MD5MAC::DIGESTSIZE]; + bool pass=true, fail; + + cout << "\nMD5MAC validation suite running...\n"; + + for (int k=0; k<2; k++) + { + MD5MAC mac(keys[k]); + cout << "\nKEY: "; + for (int j=0;j +#include +#include + +int +main(int argc, char **argv) +{ + void *handle; + char *error; + + handle = dlopen("./libpscrypto.so", RTLD_LAZY); + if (!handle) { + fprintf(stderr, "%s\n", dlerror()); + exit(EXIT_FAILURE); + } + + dlclose(handle); + + return 0; +}