📄 base64impl.c
字号:
/* Copyright 2003-2006, Voltage Security, all rights reserved.
*/
#include "vibecrypto.h"
#include "environment.h"
#include "base.h"
#include "libctx.h"
#include "algobj.h"
#include "encode.h"
#include "base64.h"
#include "errorctx.h"
/* For ease in viewing, #define the special characters.
* IIII Invalid character.
* NNNN New line
* EEEE Equal sign
*/
#define IIII 0xff
#define NNNN 0x80
#define EEEE 0x7f
static unsigned char base64DecodeChars[256] =
{
IIII, IIII, IIII, IIII, IIII, IIII, IIII, IIII,
IIII, IIII, NNNN, IIII, IIII, NNNN, IIII, IIII,
IIII, IIII, IIII, IIII, IIII, IIII, IIII, IIII,
IIII, IIII, IIII, IIII, IIII, IIII, IIII, IIII,
IIII, IIII, IIII, IIII, IIII, IIII, IIII, IIII,
IIII, IIII, IIII, 0x3e, IIII, IIII, IIII, 0x3f,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
0x3c, 0x3d, IIII, IIII, IIII, EEEE, IIII, IIII,
IIII, 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, IIII, IIII, IIII, IIII, IIII,
IIII, 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, IIII, IIII, IIII, IIII, IIII,
IIII, IIII, IIII, IIII, IIII, IIII, IIII, IIII,
IIII, IIII, IIII, IIII, IIII, IIII, IIII, IIII,
IIII, IIII, IIII, IIII, IIII, IIII, IIII, IIII,
IIII, IIII, IIII, IIII, IIII, IIII, IIII, IIII,
IIII, IIII, IIII, IIII, IIII, IIII, IIII, IIII,
IIII, IIII, IIII, IIII, IIII, IIII, IIII, IIII,
IIII, IIII, IIII, IIII, IIII, IIII, IIII, IIII,
IIII, IIII, IIII, IIII, IIII, IIII, IIII, IIII,
IIII, IIII, IIII, IIII, IIII, IIII, IIII, IIII,
IIII, IIII, IIII, IIII, IIII, IIII, IIII, IIII,
IIII, IIII, IIII, IIII, IIII, IIII, IIII, IIII,
IIII, IIII, IIII, IIII, IIII, IIII, IIII, IIII,
IIII, IIII, IIII, IIII, IIII, IIII, IIII, IIII,
IIII, IIII, IIII, IIII, IIII, IIII, IIII, IIII,
IIII, IIII, IIII, IIII, IIII, IIII, IIII, IIII,
IIII, IIII, IIII, IIII, IIII, IIII, IIII, IIII
};
static unsigned char base64EncodeChars[64] =
{
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
};
/* Encode one block of bytes.
* <p>The block size must be a multiple of 3 bytes.
*
* @param input The data to encode.
* @param blockSize The size, in bytes, of one block.
* @param newLineChar Indicates what the new line char or chars should
* be. The input must be either VT_BASE64_NO_NEW_LINE,
* VT_BASE64_NEW_LINE_LF or VT_BASE64_NEW_LINE_CR_LF.
* @param output The buffer into which the result will be placed.
* @param outputLen The address where the function will go to deposit
* the number of bytes placed into the output buffer.
* @return None.
*/
static void VOLT_CALLING_CONV DoEncodeUpdate VOLT_PROTO_LIST ((
unsigned char *input,
int blockSize,
unsigned int newLineChar,
unsigned char *output,
unsigned int *outputLen
));
int Base64GetOutputSize (
VoltAlgorithmObject *obj,
unsigned int callFlag,
unsigned char *input,
unsigned int inputLen,
unsigned int *outputSize,
VtRandomObject random
)
{
int status;
unsigned int totalLen, blockCount, extra, padLen;
VoltEncodeClassCtx *encodeCtx = (VoltEncodeClassCtx *)(obj->classCtx);
VoltBase64Ctx *base64Ctx = (VoltBase64Ctx *)(encodeCtx->localEncodeCtx);
VOLT_DECLARE_FNCT_LINE (fnctLine)
status = 0;
switch (callFlag)
{
default:
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_CALL_ORDER;
break;
case VOLT_CALLER_ENCODE_UPDATE:
/* For every binary block of input, there will be one base64
* block.
*/
totalLen = inputLen + encodeCtx->unprocessedDataLen;
blockCount = totalLen / encodeCtx->plainBlockSize;
*outputSize = blockCount * encodeCtx->codedBlockSize;
break;
case VOLT_CALLER_ENCODE_FINAL:
/* For every binary block of input, there will be one base64
* block.
*/
totalLen = inputLen + encodeCtx->unprocessedDataLen;
blockCount = totalLen / encodeCtx->plainBlockSize;
*outputSize = blockCount * encodeCtx->codedBlockSize;
/* For any extra left over, we'll "pad" to a multiple of three
* and the final output will be 4 bytes for every three.
* Then we'll add the required number of "=" characters.
* We'll also need the line feed at the end.
*/
extra = totalLen - (blockCount * encodeCtx->plainBlockSize);
if (extra == 0)
break;
padLen = extra % 3;
if (padLen != 0)
padLen = 3 - padLen;
extra += padLen;
extra = (extra / 3) * 4;
(*outputSize) += (extra + base64Ctx->newLineLen);
break;
case VOLT_CALLER_DECODE_UPDATE:
/* For every 4 bytes of input, there are 3 bytes of output.
* Actually, there are new line characters that should not be
* considered part of the total length, however, we're not going
* to search for them, so we'll use 3/4 * inputLen. This will
* produce a number that may be too large.
*/
totalLen = inputLen + base64Ctx->converterLen;
*outputSize = (totalLen / 4) * 3;
break;
case VOLT_CALLER_DECODE_FINAL:
/* For every 4 bytes of input, there are 3 bytes of output.
* Actually, there are new line characters that should not be
* considered part of the total length, however, we're not going
* to search for them, so we'll use 3/4 * inputLen. This will
* produce a number that may be too large.
* For Final, the total length of valid characters must be a
* multiple of 4. If not, there will be an error (if checking).
* But we don't know yet how many of the characters are invalid,
* so we'll use the same formula.
* If there are any leftovers, we may want to deal with them, so
* find a "padded" length (the + 3).
*/
totalLen = inputLen + base64Ctx->converterLen;
*outputSize = ((totalLen + 3) / 4) * 3;
}
VOLT_LOG_ERROR_COMPARE (
status, obj->voltObject.libraryCtx, status, VT_ERROR_TYPE_PRIMARY,
fnctLine, "Base64GetOutputSize", (char *)0)
return (status);
}
int Base64EncodeInit (
VoltAlgorithmObject *obj
)
{
VoltEncodeClassCtx *encodeCtx = (VoltEncodeClassCtx *)(obj->classCtx);
VoltBase64Ctx *base64Ctx = (VoltBase64Ctx *)(encodeCtx->localEncodeCtx);
/* "Empty" the unprocessedData buffer.
*/
encodeCtx->unprocessedDataLen = 0;
base64Ctx->converterLen = 0;
/* Because we're encoding, the block sizes are based on the size
* specified in the base64Info.
*/
encodeCtx->plainBlockSize = (base64Ctx->info.base64BlockSize / 4) * 3;
encodeCtx->codedBlockSize =
base64Ctx->info.base64BlockSize + base64Ctx->newLineLen;
return (0);
}
int Base64EncodeUpdate (
VoltAlgorithmObject *obj,
VtRandomObject random,
unsigned char *dataToEncode,
unsigned int dataToEncodeLen,
unsigned char *encoding,
unsigned int *encodingLen
)
{
unsigned int outputLen;
VoltEncodeClassCtx *encodeCtx = (VoltEncodeClassCtx *)(obj->classCtx);
VoltBase64Ctx *base64Ctx = (VoltBase64Ctx *)(encodeCtx->localEncodeCtx);
*encodingLen = 0;
/* As long as there are blocks of input, encode.
*/
while (dataToEncodeLen > 0)
{
/* This encodes one block.
*/
DoEncodeUpdate (
dataToEncode, (int)(encodeCtx->plainBlockSize),
base64Ctx->info.newLineCharacter, encoding, &outputLen);
dataToEncode += encodeCtx->plainBlockSize;
dataToEncodeLen -= encodeCtx->plainBlockSize;
encoding += outputLen;
(*encodingLen) += outputLen;
}
return (0);
}
int Base64EncodeFinal (
VoltAlgorithmObject *obj,
VtRandomObject random,
unsigned char *encoding,
unsigned int *encodingLen
)
{
unsigned int padLen, index;
VoltEncodeClassCtx *encodeCtx = (VoltEncodeClassCtx *)(obj->classCtx);
VoltBase64Ctx *base64Ctx = (VoltBase64Ctx *)(encodeCtx->localEncodeCtx);
/* If there's no data in the unprocessedData buffer, there's nothing
* to do.
*/
*encodingLen = 0;
if (encodeCtx->unprocessedDataLen == 0)
return (0);
/* Any pad?
*/
padLen = encodeCtx->unprocessedDataLen % 3;
if (padLen != 0)
{
padLen = 3 - padLen;
index = encodeCtx->unprocessedDataLen;
encodeCtx->unprocessedData[index] = 0;
/* Even if padLen is 1, go ahead and set the next byte to 0, it's
* cheaper to set it to 0 than to check to see if it needs to be
* set. We know there's enough space in the buffer, it was set to
* the size of a binary block + 1.
*/
encodeCtx->unprocessedData[index + 1] = 0;
encodeCtx->unprocessedDataLen += padLen;
}
DoEncodeUpdate (
encodeCtx->unprocessedData, (int)(encodeCtx->unprocessedDataLen),
base64Ctx->info.newLineCharacter, encoding, encodingLen);
/* If there's pad, replace the last one or two chars (in front of the
* new line chars) with "=" chars.
*/
if (padLen == 1)
{
encoding += ((*encodingLen) - (base64Ctx->newLineLen + 1));
*encoding = 0x3d;
}
else if (padLen == 2)
{
encoding += ((*encodingLen) - (base64Ctx->newLineLen + 2));
*encoding = 0x3d;
*(encoding + 1) = 0x3d;
}
return (0);
}
int Base64DecodeInit (
VoltAlgorithmObject *obj
)
{
VoltEncodeClassCtx *encodeCtx = (VoltEncodeClassCtx *)(obj->classCtx);
VoltBase64Ctx *base64Ctx = (VoltBase64Ctx *)(encodeCtx->localEncodeCtx);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -