退后一步,看看你想要实现什么。Tiny 加密算法不适用于 128 位整数,但适用于 128 位密钥;密钥由四个 32 位无符号整数组成。
您真正需要的是一种将十进制(或十六进制或其他基数)128 位无符号整数从字符串解析为四个 32 位无符号整数元素的方法。
我建议编写一个乘加函数,它采用四 32 位值,将其乘以一个 32 位常数,然后加上另一个 32 位常数:
#include <stdint.h>
uint32_t muladd128(uint32_t quad[4], const uint32_t mul, const uint32_t add)
{
uint64_t temp = 0;
temp = (uint64_t)quad[3] * (uint64_t)mul + add;
quad[3] = temp;
temp = (uint64_t)quad[2] * (uint64_t)mul + (temp >> 32);
quad[2] = temp;
temp = (uint64_t)quad[1] * (uint64_t)mul + (temp >> 32);
quad[1] = temp;
temp = (uint64_t)quad[0] * (uint64_t)mul + (temp >> 32);
quad[0] = temp;
return temp >> 32;
}
以上使用最重要的第一个词序。如果结果溢出,则返回非零;事实上,它返回 32 位溢出本身。
这样,就可以很容易地解析描述二进制、八进制、十进制或十六进制的非负 128 位整数的字符串:
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
static void clear128(uint32_t quad[4])
{
quad[0] = quad[1] = quad[2] = quad[3] = 0;
}
/* muladd128() */
static const char *parse128(uint32_t quad[4], const char *from)
{
if (!from) {
errno = EINVAL;
return NULL;
}
while (*from == '\t' || *from == '\n' || *from == '\v' ||
*from == '\f' || *from == '\r' || *from == ' ')
from++;
if (from[0] == '0' && (from[1] == 'x' || from[1] == 'X') &&
((from[2] >= '0' && from[2] <= '9') ||
(from[2] >= 'A' && from[2] <= 'F') ||
(from[2] >= 'a' && from[2] <= 'f'))) {
/* Hexadecimal */
from += 2;
clear128(quad);
while (1)
if (*from >= '0' && *from <= '9') {
if (muladd128(quad, 16, *from - '0')) {
errno = ERANGE;
return NULL;
}
from++;
} else
if (*from >= 'A' && *from <= 'F') {
if (muladd128(quad, 16, *from - 'A' + 10)) {
errno = ERANGE;
return NULL;
}
from++;
} else
if (*from >= 'a' && *from <= 'f') {
if (muladd128(quad, 16, *from - 'a' + 10)) {
errno = ERANGE;
return NULL;
}
from++;
} else
return from;
}
if (from[0] == '0' && (from[1] == 'b' || from[1] == 'B') &&
(from[2] >= '0' && from[2] <= '1')) {
/* Binary */
from += 2;
clear128(quad);
while (1)
if (*from >= '0' && *from <= '1') {
if (muladd128(quad, 2, *from - '0')) {
errno = ERANGE;
return NULL;
}
from++;
} else
return from;
}
if (from[0] == '0' &&
(from[1] >= '0' && from[1] <= '7')) {
/* Octal */
from += 1;
clear128(quad);
while (1)
if (*from >= '0' && *from <= '7') {
if (muladd128(quad, 8, *from - '0')) {
errno = ERANGE;
return NULL;
}
from++;
} else
return from;
}
if (from[0] >= '0' && from[0] <= '9') {
/* Decimal */
clear128(quad);
while (1)
if (*from >= '0' && *from <= '9') {
if (muladd128(quad, 10, *from - '0')) {
errno = ERANGE;
return NULL;
}
from++;
} else
return from;
}
/* Not a recognized number. */
errno = EINVAL;
return NULL;
}
int main(int argc, char *argv[])
{
uint32_t key[4];
int arg;
for (arg = 1; arg < argc; arg++) {
const char *end = parse128(key, argv[arg]);
if (end) {
if (*end != '\0')
printf("%s: 0x%08x%08x%08x%08x (+ \"%s\")\n", argv[arg], key[0], key[1], key[2], key[3], end);
else
printf("%s: 0x%08x%08x%08x%08x\n", argv[arg], key[0], key[1], key[2], key[3]);
fflush(stdout);
} else {
switch (errno) {
case ERANGE:
fprintf(stderr, "%s: Too large.\n", argv[arg]);
break;
case EINVAL:
fprintf(stderr, "%s: Not a nonnegative integer in binary, octal, decimal, or hexadecimal notation.\n", argv[arg]);
break;
default:
fprintf(stderr, "%s: %s.\n", argv[arg], strerror(errno));
break;
}
}
}
return EXIT_SUCCESS;
}
添加对有时使用的 Base64 和 Base85 的支持非常简单;或者实际上对于任何小于 2 32的基数。
而且,如果您考虑上述情况,这完全取决于您需要什么。