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

📄 base64.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:
			else
				if( src[ srcIndex ] == '\r' )
					{
					srcIndex++;

					/* Some broken implementations emit two CRs before the
					   LF.  Stripping these extra CRs clashes with other
					   broken implementations that emit only CRs, which means
					   that we'll be stripping the EOT blank line in MIME
					   encapsulation, however it looks like the two-CR bug
					   (usually from Netscape) appears to be more prevalent
					   than the CR-only bug (old Mac software) */
					if( src[ srcIndex ] == '\r' )
						srcIndex++;

					if( src[ srcIndex ] == '\n' )
						srcIndex++;
					}
			lineCount = 0;

			/* Check for '\0' or EOL (S/MIME) or '----END...' (PEM) after 
			   EOL */
			if( ( format == CRYPT_ICERTFORMAT_SMIME_CERTIFICATE && \
				  ( !src[ srcIndex ] || src[ srcIndex ] == '\n' || \
					 src[ srcIndex ] == '\r' ) ) || \
				( format == CRYPT_CERTFORMAT_TEXT_CERTIFICATE && \
				  !strCompare( src + srcIndex, "-----END ", 9 ) ) )
				{
				c0 = c1 = c2 = BEOF;
				srcIndex += 4;
				break;
				}

			/* Make sure that we haven't run off into the weeds */
			if( srcIndex >= srcLen )
				break;
			}

		/* Decode a block of data from the input buffer */
		c0 = decode( src[ srcIndex++ ] );
		c1 = decode( src[ srcIndex++ ] );
		c2 = decode( src[ srcIndex++ ] );
		c3 = decode( src[ srcIndex++ ] );
		cx = c0 | c1 | c2 | c3;
		if( c0 == BEOF || cx == BEOF )
			/* We need to check c0 separately since hitting an EOF at c0 may
			   cause later chars to be decoded as BERR */
			break;
		else
			if( cx == BERR )
				return( CRYPT_ERROR_BADDATA );
		lineCount += 4;

		/* Copy the decoded data to the output buffer */
		destPtr[ destIndex++ ] = ( c0 << 2 ) | ( c1 >> 4 );
		destPtr[ destIndex++ ] = ( c1 << 4 ) | ( c2 >> 2 );
		destPtr[ destIndex++ ] = ( c2 << 6 ) | ( c3 );
		if( destIndex > destMaxLen )
			return( CRYPT_ERROR_OVERFLOW );
		}

	/* Handle the truncation of data at the end.  Due to the 3 -> 4 encoding,
	   we have the following mapping: 0 chars -> nothing, 1 char -> 2 + 2 pad,
	   2 chars = 3 + 1 pad */
	if( c0 == BEOF )
		/* No padding, move back 4 chars */
		srcIndex -= 4;
	else
		{
		/* 2 chars padding, decode 1 from 2 */
		destPtr[ destIndex++ ] = ( c0 << 2 ) | ( c1 >> 4 );
		if( c2 != BEOF )
			/* 1 char padding, decode 2 from 3 */
			destPtr[ destIndex++ ] = ( c1 << 4 ) | ( c2 >> 2);
		}

	/* Return count of decoded bytes */
	return( destIndex );
	}

/* Calculate the size of a quantity of data once it's en/decoded */

int base64decodeLen( const char *data, const int dataLength )
	{
	STREAM stream;
	int ch, length;

	assert( isReadPtr( data, dataLength ) );

	/* Skip ahead until we find the end of the decodable data */
	sMemConnect( &stream, data, dataLength );
	do
		{
		ch = sgetc( &stream );
		if( cryptStatusError( ch ) || ch == BPAD )
			break;
		ch = decode( ch );
		}
	while( ch != BERR );
	length = stell( &stream );
	sMemDisconnect( &stream );

	/* Return a rough estimate of how much room the decoded data will occupy.
	   This ignores the EOL size so it always overestimates, but a strict
	   value isn't necessary since it's only used for memory buffer
	   allocation */
	return( ( length * 3 ) / 4 );
	}

int base64encodeLen( const int dataLength,
					 const CRYPT_CERTTYPE_TYPE certType )
	{
	int length = roundUp( ( dataLength * 4 ) / 3, 4 ), headerInfoIndex;

	for( headerInfoIndex = 0;
		 headerInfo[ headerInfoIndex ].type != certType && \
			headerInfo[ headerInfoIndex ].type != CRYPT_CERTTYPE_NONE;
		 headerInfoIndex++ );
	assert( headerInfo[ headerInfoIndex ].type != CRYPT_CERTTYPE_NONE );

	/* Calculate extra length due to EOL's */
	length += ( ( roundUp( length, TEXT_LINESIZE ) / TEXT_LINESIZE ) * EOL_LEN );

	/* Return the total length due to delimiters */
	return( strlen( headerInfo[ headerInfoIndex ].header ) + length + \
			strlen( headerInfo[ headerInfoIndex ].trailer ) );
	}

/****************************************************************************
*																			*
*						PKI User ID En/Decoding Functions					*
*																			*
****************************************************************************/

/* En/decode text representations of binary keys */

static const char codeTable[] = \
						"ABCDEFGHJKLMNPQRSTUVWXYZ23456789";	/* No O/0, I/1 */
static const int hiMask[] = { 0x00, 0x00, 0x00, 0x00, 0x0F, 0x07, 0x03, 0x01 };
static const int loMask[] = { 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0 };

BOOLEAN isPKIUserValue( const char *encVal, const int encValLength )
	{
	int i = 0;

	assert( isReadPtr( encVal, encValLength ) );

	/* Check whether a user value is of the form XXXXX-XXXXX-XXXXX{-XXXXX} */
	if( ( encValLength != ( 3 * 5 ) + 2 ) && \
		( encValLength != ( 4 * 5 ) + 3 ) )
		return( FALSE );
	while( i < encValLength )
		{
		int j;

		for( j = 0; j < 5; j++ )
			{
			const int ch = encVal[ i++ ];

			if( !isAlnum( ch ) )
				return( FALSE );
			}
		if( i < encValLength && encVal[ i++ ] != '-' )
			return( FALSE );
		}
	return( TRUE );
	}

int adjustPKIUserValue( BYTE *value, const int noCodeGroups )
	{
	const int noBits = noCodeGroups * 25;
	const int length = ( roundUp( noBits, 8 ) / 8 ) - 1;

	assert( isWritePtr( value, roundUp( noCodeGroups * 25, 8 ) / 8 ) );

	/* Mask off any bits at the end of the data that can't be encoded using
	   the given number of code groups */
	value[ length - 1 ] &= 0xFF << ( 8 - ( noBits % 8 ) );
	return( length );
	}

int encodePKIUserValue( char *encVal, const BYTE *value,
						const int noCodeGroups )
	{
	BYTE valBuf[ 128 ];
	const int dataBytes = ( roundUp( noCodeGroups * 25, 8 ) / 8 );
	int i, byteCount = 0, bitCount = 0, length;

	assert( isReadPtr( value, dataBytes ) );

	/* Copy across the data bytes, leaving a gap at the start for the
	   checksum */
	memcpy( valBuf + 1, value, dataBytes );
	length = adjustPKIUserValue( valBuf + 1, noCodeGroups ) + 1;

	/* Calculate the Fletcher checksum and prepend it to the data bytes
	   This is easier than handling the addition of a non-byte-aligned
	   quantity to the end of the data */
	valBuf[ 0 ] = checksumData( valBuf + 1, length - 1 ) & 0xFF;

	/* Encode the binary data as text */
	for( length = 0, i = 1; i <= noCodeGroups * 5; i++ )
		{
		int chunkValue;

		/* Extract the next 5-bit chunk and convert it to text form */
		if( bitCount < 3 )
			/* Everything's present in one byte, shift it down to the LSB */
			chunkValue = ( valBuf[ byteCount ] >> ( 3 - bitCount ) ) & 0x1F;
		else
			if( bitCount == 3 )
				/* It's the 5 LSB's */
				chunkValue = valBuf[ byteCount ] & 0x1F;
			else
				/* The data spans two bytes, shift the bits from the high
				   byte up and the bits from the low byte down */
				chunkValue = ( ( valBuf[ byteCount ] & \
								hiMask[ bitCount ] ) << ( bitCount - 3 ) ) | \
							( ( valBuf[ byteCount + 1 ] & \
								loMask[ bitCount ] ) >> ( 11 - bitCount ) );
		encVal[ length++ ] = codeTable[ chunkValue ];
		if( !( i % 5 ) && i < noCodeGroups * 5 )
			encVal[ length++ ] = '-';

		/* Advance by 5 bits */
		bitCount += 5;
		if( bitCount >= 8 )
			{
			bitCount -= 8;
			byteCount++;
			}
		}

	return( length );
	}

int decodePKIUserValue( BYTE *value, const char *encVal,
						const int encValLength )
	{
	BYTE valBuf[ 128 ];
	char encBuf[ 128 ], *encBufPtr = encBuf;
	int i = 0, byteCount = 0, bitCount = 0, length = 0;

	assert( isReadPtr( encVal, encValLength ) );

	/* Undo the formatting of the encoded value */
	while( i < encValLength )
		{
		int j;

		for( j = 0; j < 5; j++ )
			{
			const int ch = encVal[ i++ ];

			if( !isAlnum( ch ) || length >= encValLength )
				return( CRYPT_ERROR_BADDATA );
			encBuf[ length++ ] = toUpper( ch );
			}
		if( i < encValLength && encVal[ i++ ] != '-' )
			return( CRYPT_ERROR_BADDATA );
		}
	if( length % 5 )
		return( CRYPT_ERROR_BADDATA );

	/* Decode the text data into binary */
	memset( valBuf, 0, 128 );
	for( i = 0; i < length; i ++ )
		{
		const int ch = *encBufPtr++;
		int chunkValue;

		for( chunkValue = 0; chunkValue < 0x20; chunkValue++ )
			if( codeTable[ chunkValue ] == ch )
				break;
		if( chunkValue == 0x20 )
			return( CRYPT_ERROR_BADDATA );

		/* Extract the next 5-bit chunk and convert it to text form */
		if( bitCount < 3 )
			/* Everything's present in one byte, shift it up into position */
			valBuf[ byteCount ] |= chunkValue << ( 3 - bitCount );
		else
			if( bitCount == 3 )
				/* It's the 5 LSB's */
				valBuf[ byteCount ] |= chunkValue;
			else
				{
				/* The data spans two bytes, shift the bits from the high
				   byte down and the bits from the low byte up */
				valBuf[ byteCount ] |= \
							( chunkValue >> ( bitCount - 3 ) ) & hiMask[ bitCount ];
				valBuf[ byteCount + 1 ] = \
							( chunkValue << ( 11 - bitCount ) ) & loMask[ bitCount ];
				}

		/* Advance by 5 bits */
		bitCount += 5;
		if( bitCount >= 8 )
			{
			bitCount -= 8;
			byteCount++;
			}
		}

	/* Calculate the Fletcher checksum and make sure that it matches the
	   value at the start of the data bytes */
	if( bitCount )
		byteCount++;	/* More bits in the last partial byte */
	if( valBuf[ 0 ] != ( checksumData( valBuf + 1, byteCount - 1 ) & 0xFF ) )
		return( CRYPT_ERROR_BADDATA );

	/* Return the decoded value to the caller */
	if( value != NULL )
		memcpy( value, valBuf + 1, byteCount - 1 );
	return( byteCount - 1 );
	}

⌨️ 快捷键说明

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