Initial commit

This commit is contained in:
Chord 2016-04-21 21:45:12 -04:00
commit b49a3d0301
11 changed files with 621 additions and 0 deletions

8
.gitignore vendored Normal file
View file

@ -0,0 +1,8 @@
*.o
*.so
*.dll
*.exe
*.a
*.pyc
*.stackdump
.gdb_history

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "external/psf-cryptopp"]
path = external/psf-cryptopp
url = https://github.com/psforever/psf-cryptopp.git

15
Makefile Normal file
View file

@ -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

28
README.md Normal file
View file

@ -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.

1
external/psf-cryptopp vendored Submodule

@ -0,0 +1 @@
Subproject commit d9be78c72cbe270efecd90193f16b10007b6aa1d

2
pscrypto/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
pscrypto
test

43
pscrypto/Makefile Normal file
View file

@ -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

0
pscrypto/__init__.py Normal file
View file

401
pscrypto/pscrypto.cpp Normal file
View file

@ -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 <iostream>
using std::cout;
using std::cerr;
using std::endl;
#include <string>
using std::string;
#include <cstdlib>
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 <stdint.h>
#include <iostream>
#include <iomanip>
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<MD5MAC::KEYLENGTH;j++)
cout << setw(2) << setfill('0') << hex << (int)keys[k][j];
cout << endl << endl;
for (int i=0;i<7;i++)
{
mac.Update((byte *)TestVals[i], strlen(TestVals[i]));
mac.Final(digest);
fail = memcmp(digest, output[k][i], MD5MAC::DIGESTSIZE)
|| !mac.VerifyDigest(output[k][i], (byte *)TestVals[i], strlen(TestVals[i]));
pass = pass && !fail;
cout << (fail ? "FAILED " : "passed ");
for (int j=0;j<MD5MAC::DIGESTSIZE;j++)
cout << setw(2) << setfill('0') << hex << (int)digest[j];
cout << " \"" << TestVals[i] << '\"' << endl;
}
}
return pass;
}

100
pscrypto/pscrypto.py Normal file
View file

@ -0,0 +1,100 @@
#!/usr/bin/env python2
from binascii import hexlify
from ctypes import *
import os
lib = cdll.LoadLibrary(os.path.dirname(os.path.realpath(__file__)) + "/pscrypto.dll")
lib.MD5_MAC.restype = c_bool
lib.MD5_MAC.prototype = [c_char_p, c_uint, c_char_p, c_uint, c_char_p, c_uint]
lib.DH_Start.restype = c_void_p
lib.DH_Start.prototype = [c_char_p, c_char_p, c_char_p]
lib.DH_Agree.restype = c_bool
lib.DH_Agree.prototype = [c_void_p, c_char_p, c_char_p, c_char_p]
lib.RC5_Init.restype = c_void_p
lib.RC5_Init.prototype = [c_char_p, c_uint, c_bool]
lib.RC5_Decrypt.restype = c_bool
lib.RC5_Decrypt.prototype = [c_void_p, c_char_p, c_uint, c_char_p]
lib.RC5_Encrypt.restype = c_bool
lib.RC5_Encrypt.prototype = [c_void_p, c_char_p, c_uint, c_char_p]
def hexToBin(data):
return data.decode('hex')
def binToHex(data):
return hexlify(data)
def md5mac(key, msg, outSz):
outBuf = create_string_buffer(outSz)
lib.MD5_MAC(key, len(key), msg, len(msg), outBuf, outSz)
return outBuf.raw
def ServerDHStart(p, g):
outPrivate = create_string_buffer(16)
outPublic = create_string_buffer(16)
dhHandle = lib.DH_Start(p, g, outPrivate, outPublic)
return (dhHandle, outPrivate.raw, outPublic.raw)
def ServerDHAgree(dhHandle, privKey, otherPubKey):
outAgree = create_string_buffer(16)
status = lib.DH_Agree(dhHandle, outAgree, privKey, otherPubKey)
return (status, outAgree.raw)
def ServerInitEnc(key):
return lib.RC5_Init(key, len(key), True)
def ServerInitDec(key):
return lib.RC5_Init(key, len(key), False)
def ServerDec(decHandle, ct):
pt = create_string_buffer(len(ct))
ret = lib.RC5_Decrypt(decHandle, ct, len(ct), pt)
if not ret:
print "Decryption failed!"
return ""
return pt.raw
def ServerEnc(encHandle, pt):
ct = create_string_buffer(len(pt))
ret = lib.RC5_Encrypt(encHandle, pt, len(pt), ct)
if not ret:
print "Encryption failed!"
return ""
return ct.raw
def main():
raw_input()
(dhHandle, priv, pub) = ServerDHStart("\x41\x75"*8, "\x01"*15 + "\x03")
print "Started"
print ServerDHAgree(dhHandle, priv, "A"*16)
key = "377b60f8790f91b35a9da82945743da9"
label = "master secret"
msg = "b4aea1559444a20b6112a2892de40eac00000000c8aea155b53d187076b79abab59001b600000000"
expect = "5aa15de41f5220cf5cca489155e1438c5aa15de4"
print "Key: " + key
print "Msg: " + msg
# append the label
key = hexToBin(key)
msg = label + hexToBin(msg)
outBuf = md5mac(key, msg, 20)
print "Expect: " + expect
print "Got: " + binToHex(outBuf)
if __name__ == "__main__":
main()

20
pscrypto/test.c Normal file
View file

@ -0,0 +1,20 @@
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
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;
}