|
|
@ -11,6 +11,7 @@ |
|
|
|
#include <openssl/pkcs12.h> |
|
|
|
#include <openssl/pkcs12.h> |
|
|
|
#include <openssl/x509.h> |
|
|
|
#include <openssl/x509.h> |
|
|
|
#include "openssl/bio.h" |
|
|
|
#include "openssl/bio.h" |
|
|
|
|
|
|
|
#include "openssl/des.h" |
|
|
|
#include "openssl/ssl.h" |
|
|
|
#include "openssl/ssl.h" |
|
|
|
#include <openssl/err.h> |
|
|
|
#include <openssl/err.h> |
|
|
|
#include <vector> |
|
|
|
#include <vector> |
|
|
@ -21,6 +22,8 @@ |
|
|
|
#include <cstdio> |
|
|
|
#include <cstdio> |
|
|
|
#include <cassert> |
|
|
|
#include <cassert> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <iostream> //! @todo remove (debug only) |
|
|
|
|
|
|
|
|
|
|
|
/*! @defgroup gopenssl C++ Wrapper around OpenSSL API */ |
|
|
|
/*! @defgroup gopenssl C++ Wrapper around OpenSSL API */ |
|
|
|
//@{
|
|
|
|
//@{
|
|
|
|
//! @defgroup openssllib OpenSSL C++ Library
|
|
|
|
//! @defgroup openssllib OpenSSL C++ Library
|
|
|
@ -55,6 +58,13 @@ namespace openssl { |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
class encryption_error: public openssl_error { |
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
encryption_error(const std::string& reason) throw(): |
|
|
|
|
|
|
|
openssl_error("encryption: "+reason) { |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
class pkcs12_error: public openssl_error { |
|
|
|
class pkcs12_error: public openssl_error { |
|
|
|
public: |
|
|
|
public: |
|
|
|
pkcs12_error(const std::string& reason) throw(): |
|
|
|
pkcs12_error(const std::string& reason) throw(): |
|
|
@ -90,6 +100,13 @@ namespace openssl { |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
class cannot_encrypt: public encryption_error { |
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
cannot_encrypt(std::string reason) throw(): |
|
|
|
|
|
|
|
encryption_error("cannot encrypt text: "+reason) { |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
class allocation_failed: public x509_error { |
|
|
|
class allocation_failed: public x509_error { |
|
|
|
public: |
|
|
|
public: |
|
|
|
allocation_failed() throw(): |
|
|
|
allocation_failed() throw(): |
|
|
@ -225,6 +242,193 @@ namespace openssl { |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline std::string desEnc(const std::string& txt, DES_cblock key1) { |
|
|
|
|
|
|
|
std::string res(txt); |
|
|
|
|
|
|
|
if (txt.size()%8!=0) |
|
|
|
|
|
|
|
throw cannot_encrypt("text size must be a multiple of eight"); |
|
|
|
|
|
|
|
DES_key_schedule ks1; |
|
|
|
|
|
|
|
DES_set_key_unchecked(&(DES_cblock&)key1, &ks1); |
|
|
|
|
|
|
|
for (std::string::size_type pos(0); pos<txt.size(); pos+=8) { |
|
|
|
|
|
|
|
union { |
|
|
|
|
|
|
|
DES_cblock array; |
|
|
|
|
|
|
|
const char* text; |
|
|
|
|
|
|
|
} in, out; |
|
|
|
|
|
|
|
in.text = txt.begin().operator->()+pos; |
|
|
|
|
|
|
|
out.text = res.begin().operator->()+pos; |
|
|
|
|
|
|
|
DES_ecb_encrypt(&in.array, &out.array, &ks1, DES_ENCRYPT); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return res; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline std::string desDec(const std::string& txt, DES_cblock key1) { |
|
|
|
|
|
|
|
std::string res(txt); |
|
|
|
|
|
|
|
if (txt.size()%8!=0) |
|
|
|
|
|
|
|
throw cannot_encrypt("text size must be a multiple of eight"); |
|
|
|
|
|
|
|
DES_key_schedule ks1; |
|
|
|
|
|
|
|
DES_set_key_unchecked(&(DES_cblock&)key1, &ks1); |
|
|
|
|
|
|
|
for (std::string::size_type pos(0); pos<txt.size(); pos+=8) { |
|
|
|
|
|
|
|
union { |
|
|
|
|
|
|
|
DES_cblock array; |
|
|
|
|
|
|
|
const char* text; |
|
|
|
|
|
|
|
} in, out; |
|
|
|
|
|
|
|
in.text = txt.begin().operator->()+pos; |
|
|
|
|
|
|
|
out.text = res.begin().operator->()+pos; |
|
|
|
|
|
|
|
DES_ecb_encrypt(&in.array, &out.array, &ks1, DES_DECRYPT); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return res; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CBlock8 { |
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
CBlock8() { |
|
|
|
|
|
|
|
_cb[0] = _cb[1] = _cb[2] = _cb[3] = |
|
|
|
|
|
|
|
_cb[4] = _cb[5] = _cb[6] = _cb[7] = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
CBlock8(unsigned char c1, unsigned char c2, unsigned char c3, |
|
|
|
|
|
|
|
unsigned char c4, unsigned char c5, unsigned char c6, |
|
|
|
|
|
|
|
unsigned char c7, unsigned char c8) { |
|
|
|
|
|
|
|
_cb[0] = c1; |
|
|
|
|
|
|
|
_cb[1] = c2; |
|
|
|
|
|
|
|
_cb[2] = c3; |
|
|
|
|
|
|
|
_cb[3] = c4; |
|
|
|
|
|
|
|
_cb[4] = c5; |
|
|
|
|
|
|
|
_cb[5] = c6; |
|
|
|
|
|
|
|
_cb[6] = c7; |
|
|
|
|
|
|
|
_cb[7] = c8; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
//! String must contain exactly 8 char.
|
|
|
|
|
|
|
|
CBlock8(const std::string& s) { |
|
|
|
|
|
|
|
assert(s.size()==8); |
|
|
|
|
|
|
|
_cb[0] = s[0]; |
|
|
|
|
|
|
|
_cb[1] = s[1]; |
|
|
|
|
|
|
|
_cb[2] = s[3]; |
|
|
|
|
|
|
|
_cb[3] = s[4]; |
|
|
|
|
|
|
|
_cb[4] = s[5]; |
|
|
|
|
|
|
|
_cb[5] = s[6]; |
|
|
|
|
|
|
|
_cb[6] = s[7]; |
|
|
|
|
|
|
|
_cb[7] = s[8]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
operator DES_cblock&() { |
|
|
|
|
|
|
|
return _cb; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
operator DES_cblock*() { |
|
|
|
|
|
|
|
return &_cb; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
operator std::string() const { |
|
|
|
|
|
|
|
return std::string((char*)_cb, 8); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
private: |
|
|
|
|
|
|
|
DES_cblock _cb; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*! @param txt If the length is not an integral multiple of eight
|
|
|
|
|
|
|
|
bytes, it is zero filled. The output is always an |
|
|
|
|
|
|
|
integral multiple of eight bytes. */ |
|
|
|
|
|
|
|
inline std::string desCbcEnc(std::string txt, CBlock8 key, CBlock8& ivec) { |
|
|
|
|
|
|
|
if (txt.size()%8!=0) txt.resize((txt.size()/8+1)*8, 0); |
|
|
|
|
|
|
|
std::string res(txt.size(), 0); |
|
|
|
|
|
|
|
DES_key_schedule ks; |
|
|
|
|
|
|
|
DES_set_key_unchecked(key, &ks); |
|
|
|
|
|
|
|
DES_ncbc_encrypt((unsigned char*)&txt[0], (unsigned char*)&res[0], |
|
|
|
|
|
|
|
txt.size(), &ks, ivec, DES_ENCRYPT); |
|
|
|
|
|
|
|
return res; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*! @param txt If the length is not an integral multiple of eight
|
|
|
|
|
|
|
|
bytes, it is zero filled. The output is always an |
|
|
|
|
|
|
|
integral multiple of eight bytes. */ |
|
|
|
|
|
|
|
inline std::string desCbcEnc(const std::string& txt, const CBlock8& key) { |
|
|
|
|
|
|
|
CBlock8 ivec; |
|
|
|
|
|
|
|
return desCbcEnc(txt, key, ivec); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*! @param txt If the length is not an integral multiple of eight
|
|
|
|
|
|
|
|
bytes, it is zero filled. The output is always an |
|
|
|
|
|
|
|
integral multiple of eight bytes. */ |
|
|
|
|
|
|
|
inline std::string desCbcDec(std::string txt, CBlock8 key, CBlock8& ivec) { |
|
|
|
|
|
|
|
if (txt.size()%8!=0) txt.resize((txt.size()/8+1)*8, 0); |
|
|
|
|
|
|
|
std::string res(txt.size(), 0); |
|
|
|
|
|
|
|
DES_key_schedule ks; |
|
|
|
|
|
|
|
DES_set_key_unchecked(key, &ks); |
|
|
|
|
|
|
|
DES_ncbc_encrypt((unsigned char*)&txt[0], (unsigned char*)&res[0], |
|
|
|
|
|
|
|
txt.size(), &ks, ivec, DES_DECRYPT); |
|
|
|
|
|
|
|
return res; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*! @param txt If the length is not an integral multiple of eight
|
|
|
|
|
|
|
|
bytes, it is zero filled. The output is always an |
|
|
|
|
|
|
|
integral multiple of eight bytes. */ |
|
|
|
|
|
|
|
inline std::string desCbcDec(const std::string& txt, const CBlock8& key) { |
|
|
|
|
|
|
|
CBlock8 ivec; |
|
|
|
|
|
|
|
return desCbcDec(txt, key, ivec); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*! @param txt If the length is not an integral multiple of eight
|
|
|
|
|
|
|
|
bytes, it is zero filled. The output is always an |
|
|
|
|
|
|
|
integral multiple of eight bytes. */ |
|
|
|
|
|
|
|
inline std::string des2edeCbcEnc(std::string txt, |
|
|
|
|
|
|
|
CBlock8 key1, CBlock8 key2, |
|
|
|
|
|
|
|
CBlock8 ivec = CBlock8()) { |
|
|
|
|
|
|
|
if (txt.size()%8!=0) txt.resize((txt.size()/8+1)*8, 0); |
|
|
|
|
|
|
|
std::string res(txt.size(), 0); |
|
|
|
|
|
|
|
DES_key_schedule ks1, ks2; |
|
|
|
|
|
|
|
DES_set_key_unchecked(key1, &ks1); |
|
|
|
|
|
|
|
DES_set_key_unchecked(key2, &ks2); |
|
|
|
|
|
|
|
DES_ede2_cbc_encrypt((unsigned char*)&txt[0], (unsigned char*)&res[0], |
|
|
|
|
|
|
|
txt.size(), &ks1, &ks2, ivec, DES_ENCRYPT); |
|
|
|
|
|
|
|
return res; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*! @param txt If the length is not an integral multiple of eight
|
|
|
|
|
|
|
|
bytes, it is zero filled. The output is always an |
|
|
|
|
|
|
|
integral multiple of eight bytes. */ |
|
|
|
|
|
|
|
inline std::string des2edeCbcDec(std::string txt, |
|
|
|
|
|
|
|
CBlock8 key1, CBlock8 key2, |
|
|
|
|
|
|
|
CBlock8 ivec = CBlock8()) { |
|
|
|
|
|
|
|
if (txt.size()%8!=0) txt.resize((txt.size()/8+1)*8, 0); |
|
|
|
|
|
|
|
std::string res(txt.size(), 0); |
|
|
|
|
|
|
|
DES_key_schedule ks1, ks2; |
|
|
|
|
|
|
|
DES_set_key_unchecked(key1, &ks1); |
|
|
|
|
|
|
|
DES_set_key_unchecked(key2, &ks2); |
|
|
|
|
|
|
|
DES_ede2_cbc_encrypt((unsigned char*)&txt[0], (unsigned char*)&res[0], |
|
|
|
|
|
|
|
txt.size(), &ks1, &ks2, ivec, DES_DECRYPT); |
|
|
|
|
|
|
|
return res; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! @todo untested
|
|
|
|
|
|
|
|
inline std::string des2ecbEnc(std::string txt, |
|
|
|
|
|
|
|
CBlock8 key1, CBlock8 key2) { |
|
|
|
|
|
|
|
std::string res; |
|
|
|
|
|
|
|
if (txt.size()%8!=0) |
|
|
|
|
|
|
|
throw cannot_encrypt("text size must be a multiple of eight"); |
|
|
|
|
|
|
|
DES_key_schedule ks1, ks2; |
|
|
|
|
|
|
|
DES_set_key_unchecked(key1, &ks1); |
|
|
|
|
|
|
|
DES_set_key_unchecked(key2, &ks2); |
|
|
|
|
|
|
|
for (std::string::size_type pos(0); pos<txt.size(); pos+=8) { |
|
|
|
|
|
|
|
CBlock8 out, in(txt.substr(pos, 8)); |
|
|
|
|
|
|
|
DES_ecb2_encrypt(in, out, &ks1, &ks2, DES_ENCRYPT); |
|
|
|
|
|
|
|
res+=out; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return res; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! @todo untested
|
|
|
|
|
|
|
|
inline std::string des2ecbDec(std::string txt, |
|
|
|
|
|
|
|
CBlock8 key1, CBlock8 key2) { |
|
|
|
|
|
|
|
std::string res; |
|
|
|
|
|
|
|
if (txt.size()%8!=0) |
|
|
|
|
|
|
|
throw cannot_encrypt("text size must be a multiple of eight"); |
|
|
|
|
|
|
|
DES_key_schedule ks1, ks2; |
|
|
|
|
|
|
|
DES_set_key_unchecked(key1, &ks1); |
|
|
|
|
|
|
|
DES_set_key_unchecked(key2, &ks2); |
|
|
|
|
|
|
|
for (std::string::size_type pos(0); pos<txt.size(); pos+=8) { |
|
|
|
|
|
|
|
CBlock8 out, in(txt.substr(pos, 8)); |
|
|
|
|
|
|
|
DES_ecb2_encrypt(in, out, &ks1, &ks2, DES_DECRYPT); |
|
|
|
|
|
|
|
res+=out; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return res; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//============================================================================
|
|
|
|
class X509 { |
|
|
|
class X509 { |
|
|
|
public: |
|
|
|
public: |
|
|
|