📄 cypher.cxx
字号:
{
Encode((const BYTE *)cstr, strlen(cstr), result);
}
PString PMessageDigestSHA1::Encode(const PBYTEArray & data)
{
return Encode(data, data.GetSize());
}
void PMessageDigestSHA1::Encode(const PBYTEArray & data, Result & result)
{
Encode(data, data.GetSize(), result);
}
PString PMessageDigestSHA1::Encode(const void * data, PINDEX length)
{
Result result;
Encode(data, length, result);
return PBase64::Encode(result.GetPointer(), result.GetSize());
}
void PMessageDigestSHA1::Encode(const void * data, PINDEX len, Result & result)
{
PMessageDigestSHA1 stomach;
stomach.Process(data, len);
stomach.CompleteDigest(result);
}
#endif
///////////////////////////////////////////////////////////////////////////////
// PCypher
PCypher::PCypher(PINDEX blkSize, BlockChainMode mode)
: blockSize(blkSize),
chainMode(mode)
{
}
PCypher::PCypher(const void * keyData, PINDEX keyLength,
PINDEX blkSize, BlockChainMode mode)
: key((const BYTE *)keyData, keyLength),
blockSize(blkSize),
chainMode(mode)
{
}
PString PCypher::Encode(const PString & str)
{
return Encode((const char *)str, str.GetLength());
}
PString PCypher::Encode(const PBYTEArray & clear)
{
return Encode((const BYTE *)clear, clear.GetSize());
}
PString PCypher::Encode(const void * data, PINDEX length)
{
PBYTEArray coded;
Encode(data, length, coded);
return PBase64::Encode(coded);
}
void PCypher::Encode(const PBYTEArray & clear, PBYTEArray & coded)
{
Encode((const BYTE *)clear, clear.GetSize(), coded);
}
void PCypher::Encode(const void * data, PINDEX length, PBYTEArray & coded)
{
PAssert((blockSize%8) == 0, PUnsupportedFeature);
Initialise(TRUE);
const BYTE * in = (const BYTE *)data;
BYTE * out = coded.GetPointer(
blockSize > 1 ? (length/blockSize+1)*blockSize : length);
while (length >= blockSize) {
EncodeBlock(in, out);
in += blockSize;
out += blockSize;
length -= blockSize;
}
if (blockSize > 1) {
PBYTEArray extra(blockSize);
PINDEX i;
for (i = 0; i < length; i++)
extra[i] = *in++;
PTime now;
PRandom rand((DWORD)now.GetTimestamp());
for (; i < blockSize-1; i++)
extra[i] = (BYTE)rand.Generate();
extra[blockSize-1] = (BYTE)length;
EncodeBlock(extra, out);
}
}
PString PCypher::Decode(const PString & cypher)
{
PString clear;
if (Decode(cypher, clear))
return clear;
return PString();
}
BOOL PCypher::Decode(const PString & cypher, PString & clear)
{
clear = PString();
PBYTEArray clearText;
if (!Decode(cypher, clearText))
return FALSE;
if (clearText.IsEmpty())
return TRUE;
PINDEX sz = clearText.GetSize();
memcpy(clear.GetPointer(sz+1), (const BYTE *)clearText, sz);
return TRUE;
}
BOOL PCypher::Decode(const PString & cypher, PBYTEArray & clear)
{
PBYTEArray coded;
if (!PBase64::Decode(cypher, coded))
return FALSE;
return Decode(coded, clear);
}
PINDEX PCypher::Decode(const PString & cypher, void * data, PINDEX length)
{
PBYTEArray coded;
PBase64::Decode(cypher, coded);
PBYTEArray clear;
if (!Decode(coded, clear))
return 0;
memcpy(data, clear, PMIN(length, clear.GetSize()));
return clear.GetSize();
}
PINDEX PCypher::Decode(const PBYTEArray & coded, void * data, PINDEX length)
{
PBYTEArray clear;
if (!Decode(coded, clear))
return 0;
memcpy(data, clear, PMIN(length, clear.GetSize()));
return clear.GetSize();
}
BOOL PCypher::Decode(const PBYTEArray & coded, PBYTEArray & clear)
{
PAssert((blockSize%8) == 0, PUnsupportedFeature);
if (coded.IsEmpty() || (coded.GetSize()%blockSize) != 0)
return FALSE;
Initialise(FALSE);
const BYTE * in = coded;
PINDEX length = coded.GetSize();
BYTE * out = clear.GetPointer(length);
for (PINDEX count = 0; count < length; count += blockSize) {
DecodeBlock(in, out);
in += blockSize;
out += blockSize;
}
if (blockSize != 1) {
if (*--out >= blockSize)
return FALSE;
clear.SetSize(length - blockSize + *out);
}
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
// PTEACypher
PTEACypher::PTEACypher(BlockChainMode chainMode)
: PCypher(8, chainMode)
{
GenerateKey(*(Key*)key.GetPointer(sizeof(Key)));
}
PTEACypher::PTEACypher(const Key & keyData, BlockChainMode chainMode)
: PCypher(&keyData, sizeof(Key), 8, chainMode)
{
}
void PTEACypher::SetKey(const Key & newKey)
{
memcpy(key.GetPointer(sizeof(Key)), &newKey, sizeof(Key));
}
void PTEACypher::GetKey(Key & newKey) const
{
memcpy(&newKey, key, sizeof(Key));
}
void PTEACypher::GenerateKey(Key & newKey)
{
static PRandom rand; //=1 // Explicitly set seed if need known random sequence
for (size_t i = 0; i < sizeof(Key); i++)
newKey.value[i] = (BYTE)rand;
}
static const DWORD TEADelta = 0x9e3779b9; // Magic number for key schedule
void PTEACypher::Initialise(BOOL)
{
k0 = ((const PUInt32l *)(const BYTE *)key)[0];
k1 = ((const PUInt32l *)(const BYTE *)key)[1];
k2 = ((const PUInt32l *)(const BYTE *)key)[2];
k3 = ((const PUInt32l *)(const BYTE *)key)[3];
}
void PTEACypher::EncodeBlock(const void * in, void * out)
{
DWORD y = ((PUInt32b*)in)[0];
DWORD z = ((PUInt32b*)in)[1];
DWORD sum = 0;
for (PINDEX count = 32; count > 0; count--) {
sum += TEADelta; // Magic number for key schedule
y += (z<<4)+k0 ^ z+sum ^ (z>>5)+k1;
z += (y<<4)+k2 ^ y+sum ^ (y>>5)+k3; /* end cycle */
}
((PUInt32b*)out)[0] = y;
((PUInt32b*)out)[1] = z;
}
void PTEACypher::DecodeBlock(const void * in, void * out)
{
DWORD y = ((PUInt32b*)in)[0];
DWORD z = ((PUInt32b*)in)[1];
DWORD sum = TEADelta<<5;
for (PINDEX count = 32; count > 0; count--) {
z -= (y<<4)+k2 ^ y+sum ^ (y>>5)+k3;
y -= (z<<4)+k0 ^ z+sum ^ (z>>5)+k1;
sum -= TEADelta; // Magic number for key schedule
}
((PUInt32b*)out)[0] = y;
((PUInt32b*)out)[1] = z;
}
///////////////////////////////////////////////////////////////////////////////
// PSecureConfig
#ifdef P_CONFIG_FILE
static const char DefaultSecuredOptions[] = "Secured Options";
static const char DefaultSecurityKey[] = "Validation";
static const char DefaultExpiryDateKey[] = "Expiry Date";
static const char DefaultOptionBitsKey[] = "Option Bits";
static const char DefaultPendingPrefix[] = "Pending:";
PSecureConfig::PSecureConfig(const PTEACypher::Key & prodKey,
const PStringArray & secKeys,
Source src)
: PConfig(PString(DefaultSecuredOptions), src),
securedKeys(secKeys),
securityKey(DefaultSecurityKey),
expiryDateKey(DefaultExpiryDateKey),
optionBitsKey(DefaultOptionBitsKey),
pendingPrefix(DefaultPendingPrefix)
{
productKey = prodKey;
}
PSecureConfig::PSecureConfig(const PTEACypher::Key & prodKey,
const char * const * secKeys,
PINDEX count,
Source src)
: PConfig(PString(DefaultSecuredOptions), src),
securedKeys(count, secKeys),
securityKey(DefaultSecurityKey),
expiryDateKey(DefaultExpiryDateKey),
optionBitsKey(DefaultOptionBitsKey),
pendingPrefix(DefaultPendingPrefix)
{
productKey = prodKey;
}
void PSecureConfig::GetProductKey(PTEACypher::Key & prodKey) const
{
prodKey = productKey;
}
PSecureConfig::ValidationState PSecureConfig::GetValidation() const
{
PString str;
BOOL allEmpty = TRUE;
PMessageDigest5 digestor;
for (PINDEX i = 0; i < securedKeys.GetSize(); i++) {
str = GetString(securedKeys[i]);
if (!str.IsEmpty()) {
digestor.Process(str.Trim());
allEmpty = FALSE;
}
}
str = GetString(expiryDateKey);
if (!str.IsEmpty()) {
digestor.Process(str);
allEmpty = FALSE;
}
str = GetString(optionBitsKey);
if (!str.IsEmpty()) {
digestor.Process(str);
allEmpty = FALSE;
}
PString vkey = GetString(securityKey);
if (allEmpty)
return (!vkey || GetBoolean(pendingPrefix + securityKey)) ? Pending : Defaults;
PMessageDigest5::Code code;
digestor.Complete(code);
if (vkey.IsEmpty())
return Invalid;
BYTE info[sizeof(code)+1+sizeof(DWORD)];
PTEACypher crypt(productKey);
if (crypt.Decode(vkey, info, sizeof(info)) != sizeof(info))
return Invalid;
if (memcmp(info, &code, sizeof(code)) != 0)
return Invalid;
PTime now;
if (now > GetTime(expiryDateKey))
return Expired;
return IsValid;
}
BOOL PSecureConfig::ValidatePending()
{
if (GetValidation() != Pending)
return FALSE;
PString vkey = GetString(securityKey);
if (vkey.IsEmpty())
return TRUE;
PMessageDigest5::Code code;
BYTE info[sizeof(code)+1+sizeof(DWORD)];
PTEACypher crypt(productKey);
if (crypt.Decode(vkey, info, sizeof(info)) != sizeof(info))
return FALSE;
PTime expiryDate(0, 0, 0,
1, info[sizeof(code)]&15, (info[sizeof(code)]>>4)+1996, PTime::GMT);
PString expiry = expiryDate.AsString("d MMME yyyy", PTime::GMT);
// This is for alignment problems on processors that care about such things
PUInt32b opt;
void * dst = &opt;
void * src = &info[sizeof(code)+1];
memcpy(dst, src, sizeof(opt));
PString options(PString::Unsigned, (DWORD)opt);
PMessageDigest5 digestor;
PINDEX i;
for (i = 0; i < securedKeys.GetSize(); i++)
digestor.Process(GetString(pendingPrefix + securedKeys[i]).Trim());
digestor.Process(expiry);
digestor.Process(options);
digestor.Complete(code);
if (memcmp(info, &code, sizeof(code)) != 0)
return FALSE;
SetString(expiryDateKey, expiry);
SetString(optionBitsKey, options);
for (i = 0; i < securedKeys.GetSize(); i++) {
PString str = GetString(pendingPrefix + securedKeys[i]);
if (!str.IsEmpty())
SetString(securedKeys[i], str);
DeleteKey(pendingPrefix + securedKeys[i]);
}
DeleteKey(pendingPrefix + securityKey);
return TRUE;
}
void PSecureConfig::ResetPending()
{
if (GetBoolean(pendingPrefix + securityKey)) {
for (PINDEX i = 0; i < securedKeys.GetSize(); i++)
DeleteKey(securedKeys[i]);
}
else {
SetBoolean(pendingPrefix + securityKey, TRUE);
for (PINDEX i = 0; i < securedKeys.GetSize(); i++) {
PString str = GetString(securedKeys[i]);
if (!str.IsEmpty())
SetString(pendingPrefix + securedKeys[i], str);
DeleteKey(securedKeys[i]);
}
}
DeleteKey(expiryDateKey);
DeleteKey(optionBitsKey);
}
#endif // P_CONFIG_FILE
///////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -