📄 cypher.cxx
字号:
/*
* cypher.cxx
*
* Encryption support classes.
*
* Portable Windows Library
*
* Copyright (c) 1993-2002 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Contributor(s): ______________________________________.
*
* $Log: cypher.cxx,v $
* Revision 1.1 2006/06/29 04:18:02 joegenbaclor
* *** empty log message ***
*
* Revision 1.47 2005/01/26 05:37:57 csoutheren
* Added ability to remove config file support
*
* Revision 1.46 2004/07/06 10:12:52 csoutheren
* Added static integer o factory template to assist in ensuring factories are instantiated
*
* Revision 1.45 2004/06/29 12:22:22 rjongbloed
* Fixed incorrect usage of result (now object rather than scalar), thanks Michal Zygmuntowicz
*
* Revision 1.44 2004/04/09 06:52:17 rjongbloed
* Removed #pargma linker command for /delayload of DLL as documentations sais that
* you cannot do this.
*
* Revision 1.43 2004/04/03 23:53:09 csoutheren
* Added various changes to improce compatibility with the Sun Forte compiler
* Thanks to Brian Cameron
* Added detection of readdir_r version
*
* Revision 1.42 2004/03/23 05:59:17 csoutheren
* Moved the Base64 routines into cypher.cxx, which is a more sensible
* place and reduces the inclusion of unrelated code
*
* Revision 1.41 2004/03/14 10:03:47 rjongbloed
* Fixed "security patch" that cleared entire object (including the vtable!) isntead of
* clearing the "sensitive" information it was supposed to clear.
*
* Revision 1.40 2004/03/02 12:08:27 rjongbloed
* Added missing pragmas to automatically include libraries for OpenSSL
*
* Revision 1.39 2004/02/23 23:52:19 csoutheren
* Added pragmas to avoid every Windows application needing to include libs explicitly
*
* Revision 1.38 2003/04/27 23:52:57 craigs
* Fixed problem with SHA1 not calling Start
*
* Revision 1.37 2003/04/17 12:12:59 robertj
* Added windows library inclusion for optional openssl.
*
* Revision 1.36 2003/04/17 07:34:46 robertj
* Fixed correct test for P_SSL
*
* Revision 1.35 2003/04/17 01:21:55 craigs
* Fixed problem with delete'ing a void *
*
* Revision 1.33 2003/04/10 07:14:27 craigs
* Fixed link problem in MD5 class
*
* Revision 1.32 2003/04/10 06:16:09 craigs
* Added SHA-1 digest
*
* Revision 1.31 2002/11/06 22:47:24 robertj
* Fixed header comment (copyright etc)
*
* Revision 1.30 2002/06/05 12:29:15 craigs
* Changes for gcc 3.1
*
* Revision 1.29 2001/03/01 03:55:59 robertj
* Fixed MSVC warnings.
*
* Revision 1.28 2001/02/28 21:10:47 craigs
* Fixed problem in Decode function
* Added randomizer to fill data in Decode
*
* Revision 1.27 2000/02/17 12:05:02 robertj
* Added better random number generator after finding major flaws in MSVCRT version.
*
* Revision 1.26 1998/11/30 04:50:45 robertj
* New directory structure
*
* Revision 1.25 1998/09/23 06:21:56 robertj
* Added open source copyright license.
*
* Revision 1.24 1998/07/24 06:58:13 robertj
* Improved robustness of encrypted data decoding, error on illegal tail block size.
*
* Revision 1.23 1998/02/16 00:14:36 robertj
* Fixed ability to register in one stage instead of always having to use 2.
*
* Revision 1.22 1998/01/26 02:49:14 robertj
* GNU support.
*
* Revision 1.21 1997/10/30 10:19:19 robertj
* Fixed bug with having empty string in encrypted text.
*
* Revision 1.20 1997/10/10 10:43:41 robertj
* Fixed bug in password encryption, missing string terminator.
*
* Revision 1.19 1997/08/04 10:39:53 robertj
* Fixed bug for decoding empty string.
*
* Revision 1.18 1997/07/26 11:35:38 robertj
* Fixed bug where illegal data errors were not propagated.
*
* Revision 1.17 1996/11/16 10:50:26 robertj
* ??
*
* Revision 1.16 1996/08/17 09:56:02 robertj
* Fixed big endian processor platform conformance.
*
* Revision 1.15 1996/07/15 10:33:42 robertj
* Changed memory block base64 conversion functions to be void *.
* Changed memory block cypher conversion functions to be void *.
* Changed endian classes to be memory mapped.
*
* Revision 1.14 1996/06/18 12:35:49 robertj
* Fixed bug in registration when language is not English.
*
* Revision 1.13 1996/06/10 10:01:23 robertj
* Fixed bug in getting cypher key, not copying all the bytes.
*
* Revision 1.12 1996/05/26 03:46:31 robertj
* Compatibility to GNU 2.7.x
*
* Revision 1.11 1996/04/09 03:32:45 robertj
* Fixed bug in registration so now works in time zones other than Eastern Australia.
*
* Revision 1.11 1996/04/08 05:18:38 robertj
* Fixed bug in registering programs in a different time zone.
*
* Revision 1.10 1996/03/17 05:47:19 robertj
* Changed secured config to allow for expiry dates.
*
* Revision 1.9 1996/03/16 04:37:20 robertj
* Redesign of secure config to accommodate expiry dates and option values passed in security key code.
*
* Revision 1.8 1996/03/11 10:28:53 robertj
* Fixed bug in C++ optimising compiler.
*
* Revision 1.7 1996/03/02 03:20:52 robertj
* Fixed secured config parameters so leading/trailing blanks not significant.
*
* Revision 1.6 1996/02/25 11:22:42 robertj
* Added assertion if try and SetValidation when not pending.
*
* Revision 1.5 1996/02/25 02:53:05 robertj
* Further secure config development.
*
* Revision 1.4 1996/02/15 14:43:28 robertj
* Allowed no secured config data at all to be "valid". All vars will then be guarenteed to default.
*
* Revision 1.3 1996/01/28 14:14:12 robertj
* Further implementation of secure config.
*
* Revision 1.2 1996/01/28 02:49:00 robertj
* Removal of MemoryPointer classes as usage didn't work for GNU.
* Added the secure configuration mechanism for protecting applications.
*
* Revision 1.1 1996/01/23 13:05:58 robertj
* Initial revision
*
*/
#ifdef __GNUC__
#pragma implementation "cypher.h"
#endif
#define P_DISABLE_FACTORY_INSTANCES
#include <ptlib.h>
#include <ptclib/cypher.h>
#include <ptclib/mime.h>
#include <ptclib/random.h>
///////////////////////////////////////////////////////////////////////////////
// PBase64
PBase64::PBase64()
{
StartEncoding();
StartDecoding();
}
void PBase64::StartEncoding(BOOL useCRLF)
{
encodedString = "";
encodeLength = nextLine = saveCount = 0;
useCRLFs = useCRLF;
}
void PBase64::ProcessEncoding(const PString & str)
{
ProcessEncoding((const char *)str);
}
void PBase64::ProcessEncoding(const char * cstr)
{
ProcessEncoding((const BYTE *)cstr, strlen(cstr));
}
void PBase64::ProcessEncoding(const PBYTEArray & data)
{
ProcessEncoding(data, data.GetSize());
}
static const char Binary2Base64[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
void PBase64::OutputBase64(const BYTE * data)
{
char * out = encodedString.GetPointer(((encodeLength+7)&~255) + 256);
out[encodeLength++] = Binary2Base64[data[0] >> 2];
out[encodeLength++] = Binary2Base64[((data[0]&3)<<4) | (data[1]>>4)];
out[encodeLength++] = Binary2Base64[((data[1]&15)<<2) | (data[2]>>6)];
out[encodeLength++] = Binary2Base64[data[2]&0x3f];
if (++nextLine > 18) { // 76 columns
if (useCRLFs)
out[encodeLength++] = '\r';
out[encodeLength++] = '\n';
nextLine = 0;
}
}
void PBase64::ProcessEncoding(const void * dataPtr, PINDEX length)
{
if (length == 0)
return;
const BYTE * data = (const BYTE *)dataPtr;
while (saveCount < 3) {
saveTriple[saveCount++] = *data++;
if (--length == 0)
return;
}
OutputBase64(saveTriple);
PINDEX i;
for (i = 0; i+2 < length; i += 3)
OutputBase64(data+i);
saveCount = length - i;
switch (saveCount) {
case 2 :
saveTriple[0] = data[i++];
saveTriple[1] = data[i];
break;
case 1 :
saveTriple[0] = data[i];
}
}
PString PBase64::GetEncodedString()
{
PString retval = encodedString;
encodedString = "";
encodeLength = 0;
return retval;
}
PString PBase64::CompleteEncoding()
{
char * out = encodedString.GetPointer(encodeLength + 5)+encodeLength;
switch (saveCount) {
case 1 :
*out++ = Binary2Base64[saveTriple[0] >> 2];
*out++ = Binary2Base64[(saveTriple[0]&3)<<4];
*out++ = '=';
*out = '=';
break;
case 2 :
*out++ = Binary2Base64[saveTriple[0] >> 2];
*out++ = Binary2Base64[((saveTriple[0]&3)<<4) | (saveTriple[1]>>4)];
*out++ = Binary2Base64[((saveTriple[1]&15)<<2)];
*out = '=';
}
return encodedString;
}
PString PBase64::Encode(const PString & str)
{
return Encode((const char *)str);
}
PString PBase64::Encode(const char * cstr)
{
return Encode((const BYTE *)cstr, strlen(cstr));
}
PString PBase64::Encode(const PBYTEArray & data)
{
return Encode(data, data.GetSize());
}
PString PBase64::Encode(const void * data, PINDEX length)
{
PBase64 encoder;
encoder.ProcessEncoding(data, length);
return encoder.CompleteEncoding();
}
void PBase64::StartDecoding()
{
perfectDecode = TRUE;
quadPosition = 0;
decodedData.SetSize(0);
decodeSize = 0;
}
BOOL PBase64::ProcessDecoding(const PString & str)
{
return ProcessDecoding((const char *)str);
}
BOOL PBase64::ProcessDecoding(const char * cstr)
{
static const BYTE Base642Binary[256] = {
96, 99, 99, 99, 99, 99, 99, 99, 99, 99, 98, 99, 99, 98, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 62, 99, 99, 99, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 99, 99, 99, 97, 99, 99,
99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 99, 99, 99, 99, 99,
99, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99
};
for (;;) {
BYTE value = Base642Binary[(BYTE)*cstr++];
switch (value) {
case 96 : // end of string
return FALSE;
case 97 : // '=' sign
if (quadPosition == 3 || (quadPosition == 2 && *cstr == '=')) {
quadPosition = 0; // Reset this to zero, as have a perfect decode
return TRUE; // Stop decoding now as must be at end of data
}
perfectDecode = FALSE; // Ignore '=' sign but flag decode as suspect
break;
case 98 : // CRLFs
break; // Ignore totally
case 99 : // Illegal characters
perfectDecode = FALSE; // Ignore rubbish but flag decode as suspect
break;
default : // legal value from 0 to 63
BYTE * out = decodedData.GetPointer(((decodeSize+1)&~255) + 256);
switch (quadPosition) {
case 0 :
out[decodeSize] = (BYTE)(value << 2);
break;
case 1 :
out[decodeSize++] |= (BYTE)(value >> 4);
out[decodeSize] = (BYTE)((value&15) << 4);
break;
case 2 :
out[decodeSize++] |= (BYTE)(value >> 2);
out[decodeSize] = (BYTE)((value&3) << 6);
break;
case 3 :
out[decodeSize++] |= (BYTE)value;
break;
}
quadPosition = (quadPosition+1)&3;
}
}
}
PBYTEArray PBase64::GetDecodedData()
{
perfectDecode = quadPosition == 0;
decodedData.SetSize(decodeSize);
PBYTEArray retval = decodedData;
retval.MakeUnique();
decodedData.SetSize(0);
decodeSize = 0;
return retval;
}
BOOL PBase64::GetDecodedData(void * dataBlock, PINDEX length)
{
perfectDecode = quadPosition == 0;
BOOL bigEnough = length >= decodeSize;
memcpy(dataBlock, decodedData, bigEnough ? decodeSize : length);
decodedData.SetSize(0);
decodeSize = 0;
return bigEnough;
}
PString PBase64::Decode(const PString & str)
{
PBYTEArray data;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -