⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cryptmis.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#ifndef EBCDIC_CHARS__
  static const FAR_BSS BYTE asciiToBin[ 256 ] =
	{ BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BEOF, BERR, BERR, BEOF, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, 0x3E, BERR, BERR, BERR, 0x3F,
	  0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
	  0x3C, 0x3D, BERR, BERR, BERR, BEOF, BERR, BERR,
	  BERR, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
	  0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
	  0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
	  0x17, 0x18, 0x19, BERR, BERR, BERR, BERR, BERR,
	  BERR, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
	  0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
	  0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
	  0x31, 0x32, 0x33, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR
	};
#else
  /* EBCDIC character mappings:
		A-I C1-C9
		J-R D1-D9
		S-Z E2-E9
		a-i 81-89
		j-r 91-99
		s-z A2-A9
		0-9 F0-F9
		+   4E
		/   61
		=   7E  Uses BEOF in table */
static const FAR_BSS BYTE asciiToBin[ 256 ] =
	{ BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,	/*00*/
	  BERR, BERR, BEOF, BERR, BERR, BEOF, BERR, BERR,	/* CR, LF */
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,	/*10*/
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,	/*20*/
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,	/*30*/
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,	/*40*/
	  BERR, BERR, BERR, BERR, BERR, BERR, 0x3E, BERR,	/* + */
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,	/*50*/
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, 0x3F, BERR, BERR, BERR, BERR, BERR, BERR,	/*60*/	/* / */
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,	/*70*/
	  BERR, BERR, BERR, BERR, BERR, BERR, BEOF, BERR,			/* = */
	  BERR, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,	/*80*/	/* a-i */
	  0x21, 0x22, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,	/*90*/	/* j-r */
	  0x2A, 0x2B, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31,	/*A0*/	/* s-z */
	  0x32, 0x33, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,	/*B0*/
	  BERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,	/*C0*/	/* A-I */
	  0x07, 0x08, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,	/*D0*/	/* J-R */
	  0x10, 0x11, BERR, BERR, BERR, BERR, BERR, BERR,
	  BERR, BERR, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,	/*E0*/	/* S-Z */
	  0x18, 0x19, BERR, BERR, BERR, BERR, BERR, BERR,
	  0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,	/*F0*/	/* 0-9 */
	  0x3C, 0x3D, BERR, BERR, BERR, BERR, BERR, BERR
	};
#endif /* Different character code mappings */

/* The size of lines for PEM-type formatting.  This is only used for encoding,
   for decoding we adjust to whatever size the sender has used */

#define TEXT_LINESIZE	64
#define BINARY_LINESIZE	48

/* Basic single-char en/decode functions.  We cast the value to an unsigned
   char to avoid generating negative array offsets if the sign bit is set,
   since the strings are passed as char *'s */

#define encode(data)	binToAscii[ ( BYTE ) data ]
#define decode(data)	asciiToBin[ ( BYTE ) data ]

/* The headers and trailers used for base64-encoded certificate objects */

static const FAR_BSS struct {
	const CRYPT_CERTTYPE_TYPE type;
	const char *header, *trailer;
	} headerInfo[] = {
	{ CRYPT_CERTTYPE_CERTIFICATE,
	  "-----BEGIN CERTIFICATE-----" EOL,
	  "-----END CERTIFICATE-----" EOL },
	{ CRYPT_CERTTYPE_ATTRIBUTE_CERT,
	  "-----BEGIN ATTRIBUTE CERTIFICATE-----" EOL,
	  "-----END ATTRIBUTE CERTIFICATE-----" EOL },
	{ CRYPT_CERTTYPE_CERTCHAIN,
	  "-----BEGIN CERTIFICATE CHAIN-----" EOL,
	  "-----END CERTIFICATE CHAIN-----" EOL },
	{ CRYPT_CERTTYPE_CERTREQUEST,
	  "-----BEGIN NEW CERTIFICATE REQUEST-----" EOL,
	  "-----END NEW CERTIFICATE REQUEST-----" EOL },
	{ CRYPT_CERTTYPE_REQUEST_CERT,
	  "-----BEGIN NEW CERTIFICATE REQUEST-----" EOL,
	  "-----END NEW CERTIFICATE REQUEST-----" EOL },
	{ CRYPT_CERTTYPE_CRL,
	  "-----BEGIN CERTIFICATE REVOCATION LIST-----"  EOL,
	  "-----END CERTIFICATE REVOCATION LIST-----" EOL },
	{ CRYPT_CERTTYPE_NONE,			/* Universal catch-all */
	  "-----BEGIN CERTIFICATE OBJECT-----"  EOL,
	  "-----END CERTIFICATE OBJECT-----" EOL }
	};

/* Check whether a data item has a header that identifies it as some form of
   encoded certificate object and return the start position of the encoded
   data.  For S/MIME certificate data this can in theory get quite complex
   because there are many possible variations in the headers.  Some early
   S/MIME agents used a content type of "application/x-pkcs7-mime",
   "application/x-pkcs7-signature", and "application/x-pkcs10", while newer
   ones use the same without the "x-" at the start.  In addition Netscape
   have their own MIME data types for certificates, "application/x-x509-"
   "{user-cert|ca-cert|email-cert}, and there are further types in the
   endless stream of RFCs that PKIX churns out.  There are a whole pile of
   other possible headers as well, none of them terribly relevant for our
   purposes, so all we check for is the base64 indicator.  For PEM we just
   check for the '-----..' header which is fairly simple.  Finally we check
   for raw base64-encoded data that can occur if an object is extracted from
   a MIME message and the headers discarded */

static int readLine( STREAM *stream, char *buffer, const int maxSize )
	{
	MIME_STATE state;
	int status;

	initMIMEstate( &state, maxSize );
	do
		{
		const int ch = sgetc( stream );

		status = ( cryptStatusError( ch ) ) ? ch : \
				 addMIMEchar( &state, buffer, ch );
		}
	while( cryptStatusOK( status ) );
	if( cryptStatusError( status ) && status != OK_SPECIAL )
		return( status );
	return( endMIMEstate( &state ) );
	}

CRYPT_CERTFORMAT_TYPE base64checkHeader( const char *data,
										 const int dataLength, int *startPos )
	{
	STREAM stream;
	BOOLEAN seenTransferEncoding = FALSE;
	char buffer[ 1024 ];
	int position, ch1, ch2, status;

	/* Clear return value */
	*startPos = 0;

	/* If the item is too small to contain any useful data, we don't even try
	   and examine it */
	if( dataLength < 64 )
		return( CRYPT_CERTFORMAT_NONE );

	sMemConnect( &stream, data, dataLength );

	/* Sometimes the object can be preceded by a few blank lines.  We're
	   fairly lenient with this */
	do
		ch1 = sgetc( &stream );
	while( ch1 == '\r' || ch1 == '\n' );
	ch2 = sgetc( &stream );
	position = stell( &stream ) - 2;

	/* Perform a quick check to weed out non-encoded cert data, which is
	   usually the case */
	if( ( ch1 == 0x30 ) && ( !isAlpha( ch2 ) || \
							!isAlpha( sgetc( &stream ) ) || \
							!isAlpha( sgetc( &stream ) ) ) )
		{
		sMemDisconnect( &stream );
		return( CRYPT_CERTFORMAT_NONE );
		}
	sseek( &stream, position );

	/* If it starts with a dash, check for PEM header encapsulation */
	if( ch1 == '-' )
		{
		int i;

		/* We always have to start with 5 dashes and 'BEGIN '.  After this
		   there can be all sorts of stuff, but it has to end with another
		   five dashes and a newline */
		if( cryptStatusError( sread( &stream, buffer, 11 ) ) || \
			memcmp( buffer, "-----BEGIN ", 11 ) )
			{
			sMemDisconnect( &stream );
			return( CRYPT_CERTFORMAT_NONE );
			}
		for( i = 0; i < 40; i++ )
			if( sgetc( &stream ) == '-' )
				break;
		if( i == 40 )
			{
			sMemDisconnect( &stream );
			return( CRYPT_CERTFORMAT_NONE );
			}
		if( cryptStatusError( sread( &stream, buffer, 4 ) ) || \
			memcmp( buffer, "----", 4 ) )
			{
			sMemDisconnect( &stream );
			return( CRYPT_CERTFORMAT_NONE );
			}
		ch1 = sgetc( &stream );
		if( ch1 != '\n' )
			{
			if( ch1 == '\r' )
				{
				if( sPeek( &stream ) == '\n' )
					sgetc( &stream );
				}
			else
				{
				sMemDisconnect( &stream );
				return( CRYPT_CERTFORMAT_NONE );
				}
			}

		/* Return the start position of the payload */
		*startPos = stell( &stream );
		sMemDisconnect( &stream );
		return( CRYPT_CERTFORMAT_TEXT_CERTIFICATE );
		}

	/* It's not PEM header encapsulation, check for raw base64 containing
	   some form of encoded cert.  There isn't a 100% reliable check for
	   this, but if the first 60 chars (the minimum base64 line length) are
	   all valid base64 chars and the first chars match the required values
	   then it's reasonably certain that it's base64 cert data.

	   First we do a quick check to see if the content is some form of
	   encoded cert.  For cert data that begins with 30 8x, the
	   corresponding base64 values are MI... */
	if( ch1 == 'M' && ch2 == 'I' )
		{
		BOOLEAN base64OK = TRUE;
		int i;

		/* It looks like an encoded cert, make sure that it's really base64
		   data */
		for( i = 0; i < 15; i++ )
			{
			status = sread( &stream, buffer, 4 );
			if( cryptStatusError( status ) )
				{
				base64OK = FALSE;
				break;
				}
			else
				{
				const BYTE c0 = decode( buffer[ 0 ] );
				const BYTE c1 = decode( buffer[ 1 ] );
				const BYTE c2 = decode( buffer[ 2 ] );
				const BYTE c3 = decode( buffer[ 3 ] );
				const BYTE cx = c0 | c1 | c2 | c3;

				if( cx == BEOF || cx == BERR )
					{
					base64OK = FALSE;
					break;
					}
				}
			}

		/* If everything was OK, it's raw base64 */
		if( base64OK )
			{
			sMemDisconnect( &stream );
			*startPos = position;
			return( CRYPT_CERTFORMAT_TEXT_CERTIFICATE );
			}
		}
	sseek( &stream, position );

	/* It doesn't look like raw base64, check for an S/MIME header */
	do
		{
		status = readLine( &stream, buffer, 1024 );
		if( !cryptStatusError( status ) && status >= 32 && \
			strCompare( buffer, "Content-Transfer-Encoding: bas64", 32 ) )
			seenTransferEncoding = TRUE;
		}
	while( status > 0 );
	if( cryptStatusError( status ) || !seenTransferEncoding )
		{
		sMemDisconnect( &stream );
		return( CRYPT_CERTFORMAT_NONE );
		}

	/* Skip trailing blank lines */
	do
		ch1 = sgetc( &stream );
	while( ch1 == '\r' || ch1 == '\n' );

	/* Make sure that the content is some form of encoded cert.  For cert
	   data that begins with 30 8x, the corredponding base64 values are
	   MI... */
	*startPos = stell( &stream ) - 1;
	status = CRYPT_ICERTFORMAT_SMIME_CERTIFICATE;
	if( ch1 != 'M' || sgetc( &stream ) != 'I' )
		status = CRYPT_CERTFORMAT_NONE;
	sMemDisconnect( &stream );
	return( status );
	}

/* Encode a block of binary data into the base64 format, returning the total
   number of output bytes */

int base64encode( char *outBuffer, const void *inBuffer, const int count,
				  const CRYPT_CERTTYPE_TYPE certType )
	{
	BYTE *inBufferPtr = ( BYTE * ) inBuffer;
	int srcIndex = 0, destIndex = 0, lineCount = 0, remainder = count % 3;
	int headerInfoIndex;

	/* If it's a certificate object, add the header */
	if( certType != CRYPT_CERTTYPE_NONE )
		{
		for( headerInfoIndex = 0;
			 headerInfo[ headerInfoIndex ].type != certType && \
				headerInfo[ headerInfoIndex ].type != CRYPT_CERTTYPE_NONE;
			 headerInfoIndex++ );
		assert( headerInfo[ headerInfoIndex ].type != CRYPT_CERTTYPE_NONE );
		strcpy( outBuffer, headerInfo[ headerInfoIndex ].header );
		destIndex = strlen( headerInfo[ headerInfoIndex ].header );
		}

	/* Encode the data */
	while( srcIndex < count )
		{
		/* If we've reached the end of a line of binary data and it's a
		   certificate, add the EOL marker */
		if( certType != CRYPT_CERTTYPE_NONE && lineCount == BINARY_LINESIZE )
			{
			strcpy( outBuffer + destIndex, EOL );
			destIndex += EOL_LEN;
			lineCount = 0;
			}
		lineCount += 3;

		/* Encode a block of data from the input buffer */
		outBuffer[ destIndex++ ] = encode( inBufferPtr[ srcIndex ] >> 2 );
		outBuffer[ destIndex++ ] = encode( ( ( inBufferPtr[ srcIndex ] << 4 ) & 0x30 ) |
										   ( ( inBufferPtr[ srcIndex + 1 ] >> 4 ) & 0x0F ) );
		srcIndex++;
		outBuffer[ destIndex++ ] = encode( ( ( inBufferPtr[ srcIndex ] <

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -