“Hasty Pudding”的示例源代码密码?

发布于 2025-01-07 22:30:34 字数 410 浏览 0 评论 0原文

我需要使用“Hasty Pudding”密码,因为它能够使用 n 位的块大小。 SO 中的一些问题提到了它,但它们仅指向维基百科文章。

AFAIK 密码属于公共领域,但我还没有找到任何实现源代码。

有人见过吗?

(我最终会编码它是 C# 语言,但欢迎任何语言的源代码)

I need to use the "Hasty Pudding" cipher because its ability to use a block size of n bits. Some questions in SO mention it but they only point to the Wikipedia article.

AFAIK the cipher is in public domain, but I haven't found any implemmentation source code.

Anyone has seen it?

(I'll finally code it in C#, but source code in any language is welcome)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情绪操控生活 2025-01-14 22:30:34

您是正确的,该密码属于公共领域。事实上,我想知道还没有人向您指出源代码,因为它是 Bruce Schneier 的“应用密码学,第二版”随附源代码的一部分。

保持简短......在 https://www.schneier.com/book-applied- source.html,你会发现

HPC.ZIP
作者:布赖恩·格拉德曼博士
日期:99年1月14日
描述:HPC 分组密码,AES 的候选密码。

可通过 https://www.schneier.com/sccd/HPC.ZIP 免费下载 包含以下源代码,这应该正是您正在寻找的内容...

std_defs.h

/* 1. Standard types for AES cryptography source code               */

typedef unsigned char   u1byte; /* an 8 bit unsigned character type */
typedef unsigned short  u2byte; /* a 16 bit unsigned integer type   */
typedef unsigned long   u4byte; /* a 32 bit unsigned integer type   */

typedef signed char     s1byte; /* an 8 bit signed character type   */
typedef signed short    s2byte; /* a 16 bit signed integer type     */
typedef signed long     s4byte; /* a 32 bit signed integer type     */

/* 2. Standard interface for AES cryptographic routines             */

/* These are all based on 32 bit unsigned values and will therefore */
/* require endian conversions for big-endian architectures          */

#ifdef  __cplusplus
    extern "C"
    {
#endif

    char **cipher_name(void);
    u4byte *set_key(const u4byte in_key[], const u4byte key_len);
    void encrypt(const u4byte in_blk[4], u4byte out_blk[4]);
    void decrypt(const u4byte in_blk[4], u4byte out_blk[4]);

#ifdef  __cplusplus
    };
#endif

/* 3. Basic macros for speeding up generic operations               */

/* Circular rotate of 32 bit values                                 */

#ifdef _MSC_VER

#  include <stdlib.h>
#  pragma intrinsic(_lrotr,_lrotl)
#  define rotr(x,n) _lrotr(x,n)
#  define rotl(x,n) _lrotl(x,n)

#else

#define rotr(x,n)   (((x) >> ((int)(n))) | ((x) << (32 - (int)(n))))
#define rotl(x,n)   (((x) << ((int)(n))) | ((x) >> (32 - (int)(n))))

#endif

/* Invert byte order in a 32 bit variable                           */

#define bswap(x)    (rotl(x, 8) & 0x00ff00ff | rotr(x, 8) & 0xff00ff00)

/* Extract byte from a 32 bit quantity (little endian notation)     */

#define byte(x,n)   ((u1byte)((x) >> (8 * n)))

/* For inverting byte order in input/output 32 bit words if needed  */

#ifdef  BLOCK_SWAP
#define BYTE_SWAP
#define WORD_SWAP
#endif

#ifdef  BYTE_SWAP
#define io_swap(x)  bswap(x)
#else
#define io_swap(x)  (x)
#endif

/* For inverting the byte order of input/output blocks if needed    */

#ifdef  WORD_SWAP

#define get_block(x)                            \
    ((u4byte*)(x))[0] = io_swap(in_blk[3]);     \
    ((u4byte*)(x))[1] = io_swap(in_blk[2]);     \
    ((u4byte*)(x))[2] = io_swap(in_blk[1]);     \
    ((u4byte*)(x))[3] = io_swap(in_blk[0])

#define put_block(x)                            \
    out_blk[3] = io_swap(((u4byte*)(x))[0]);    \
    out_blk[2] = io_swap(((u4byte*)(x))[1]);    \
    out_blk[1] = io_swap(((u4byte*)(x))[2]);    \
    out_blk[0] = io_swap(((u4byte*)(x))[3])

#define get_key(x,len)                          \
    ((u4byte*)(x))[4] = ((u4byte*)(x))[5] =     \
    ((u4byte*)(x))[6] = ((u4byte*)(x))[7] = 0;  \
    switch((((len) + 63) / 64)) {               \
    case 2:                                     \
    ((u4byte*)(x))[0] = io_swap(in_key[3]);     \
    ((u4byte*)(x))[1] = io_swap(in_key[2]);     \
    ((u4byte*)(x))[2] = io_swap(in_key[1]);     \
    ((u4byte*)(x))[3] = io_swap(in_key[0]);     \
    break;                                      \
    case 3:                                     \
    ((u4byte*)(x))[0] = io_swap(in_key[5]);     \
    ((u4byte*)(x))[1] = io_swap(in_key[4]);     \
    ((u4byte*)(x))[2] = io_swap(in_key[3]);     \
    ((u4byte*)(x))[3] = io_swap(in_key[2]);     \
    ((u4byte*)(x))[4] = io_swap(in_key[1]);     \
    ((u4byte*)(x))[5] = io_swap(in_key[0]);     \
    break;                                      \
    case 4:                                     \
    ((u4byte*)(x))[0] = io_swap(in_key[7]);     \
    ((u4byte*)(x))[1] = io_swap(in_key[6]);     \
    ((u4byte*)(x))[2] = io_swap(in_key[5]);     \
    ((u4byte*)(x))[3] = io_swap(in_key[4]);     \
    ((u4byte*)(x))[4] = io_swap(in_key[3]);     \
    ((u4byte*)(x))[5] = io_swap(in_key[2]);     \
    ((u4byte*)(x))[6] = io_swap(in_key[1]);     \
    ((u4byte*)(x))[7] = io_swap(in_key[0]);     \
    }

#else

#define get_block(x)                            \
    ((u4byte*)(x))[0] = io_swap(in_blk[0]);     \
    ((u4byte*)(x))[1] = io_swap(in_blk[1]);     \
    ((u4byte*)(x))[2] = io_swap(in_blk[2]);     \
    ((u4byte*)(x))[3] = io_swap(in_blk[3])

#define put_block(x)                            \
    out_blk[0] = io_swap(((u4byte*)(x))[0]);    \
    out_blk[1] = io_swap(((u4byte*)(x))[1]);    \
    out_blk[2] = io_swap(((u4byte*)(x))[2]);    \
    out_blk[3] = io_swap(((u4byte*)(x))[3])

#define get_key(x,len)                          \
    ((u4byte*)(x))[4] = ((u4byte*)(x))[5] =     \
    ((u4byte*)(x))[6] = ((u4byte*)(x))[7] = 0;  \
    switch((((len) + 63) / 64)) {               \
    case 4:                                     \
    ((u4byte*)(x))[6] = io_swap(in_key[6]);     \
    ((u4byte*)(x))[7] = io_swap(in_key[7]);     \
    case 3:                                     \
    ((u4byte*)(x))[4] = io_swap(in_key[4]);     \
    ((u4byte*)(x))[5] = io_swap(in_key[5]);     \
    case 2:                                     \
    ((u4byte*)(x))[0] = io_swap(in_key[0]);     \
    ((u4byte*)(x))[1] = io_swap(in_key[1]);     \
    ((u4byte*)(x))[2] = io_swap(in_key[2]);     \
    ((u4byte*)(x))[3] = io_swap(in_key[3]);     \
    }

#endif

hpc.c

/* This is an independent implementation of the encryption algorithm:   */

/*                                                                      */
/*         HPC-128 by Richard Schroeppel                                */
/*                                                                      */
/* which is a candidate algorithm in the Advanced Encryption Standard   */
/* programme of the US National Institute of Standards and Technology.  */
/*                                                                      */
/* Copyright in this implementation is held by Dr B R Gladman but I     */
/* hereby give permission for its free direct or derivative use subject */
/* to acknowledgment of its origin and compliance with any conditions   */
/* that the originators of the algorithm place on its exploitation.     */
/*                                                                      */
/* Dr Brian Gladman ([email protected]) 14th January 1999     */

/* Timing data for HPC (hpc.c)

Core timing without I/O endian conversion:

128 bit key:
Key Setup:  120749 cycles
Encrypt:      1429 cycles =    17.9 mbits/sec
Decrypt:      1599 cycles =    16.0 mbits/sec
Mean:         1514 cycles =    16.9 mbits/sec

192 bit key:
Key Setup:  120754 cycles
Encrypt:      1477 cycles =    17.3 mbits/sec
Decrypt:      1599 cycles =    16.0 mbits/sec
Mean:         1538 cycles =    16.6 mbits/sec

256 bit key:
Key Setup:  120731 cycles
Encrypt:      1462 cycles =    17.5 mbits/sec
Decrypt:      1590 cycles =    16.1 mbits/sec
Mean:         1526 cycles =    16.8 mbits/sec

Full timing with I/O endian conversion:

128 bit key:
Key Setup:  118606 cycles
Encrypt:      1479 cycles =    17.3 mbits/sec
Decrypt:      1599 cycles =    16.0 mbits/sec
Mean:         1539 cycles =    16.6 mbits/sec

192 bit key:
Key Setup:  118538 cycles
Encrypt:      1480 cycles =    17.3 mbits/sec
Decrypt:      1583 cycles =    16.2 mbits/sec
Mean:         1532 cycles =    16.7 mbits/sec

256 bit key:
Key Setup:  118532 cycles
Encrypt:      1465 cycles =    17.5 mbits/sec
Decrypt:      1599 cycles =    16.0 mbits/sec
Mean:         1532 cycles =    16.7 mbits/sec

*/

#define BYTE_SWAP

#ifdef CORE_TIME
#  undef BYTE_SWAP
#endif

#include "../std_defs.h"

static char *alg_name[] = { "hpc", "hpc.c", "hpc" };

char **cipher_name()
{
return alg_name;
}

typedef u4byte  u8byte[2];

u8byte  l_key[286];
u8byte  spice[8] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

u8byte  p119 = { 0xa23249d6, 0x2b992ddf };
u8byte  e19  = { 0xc0b36173, 0x25b946eb };
u8byte  r220 = { 0xe9e17158, 0xc442f56b };

#define xor_eq(x,y)     (x)[0] ^= (y)[0]; (x)[1] ^= (y)[1]
#define and_eq(x,y)     (x)[0] &= (y)[0]; (x)[1] &= (y)[1]
#define  or_eq(x,y)     (x)[0] |= (y)[0]; (x)[1] |= (y)[1]

#define add_eq(x,y)     (x)[1] += (y)[1] + (((x)[0] += (y)[0]) < (y)[0] ? 1 : 0)
#define sub_eq(x,y)     xs = (x)[0]; (x)[1] -= (y)[1] + (((x)[0] -= (y)[0]) > xs ? 1 : 0)

#define lsh_eq(x,n)                                         \
if((n) > 31)                                            \
{   (x)[1] = (x)[0] << ((n) & 31); (x)[0] = 0;          \
}                                                       \
else if((n) > 0)                                        \
{   (x)[1] = ((x)[1] << (n)) | ((x)[0] >> (-(n) & 31)); \
    (x)[0] = (x)[0] << (n);                             \
}

#define rsh_eq(x,n)                                         \
if((n) > 31)                                            \
{   (x)[0] = (x)[1] >> ((n) & 31); (x)[1] = 0;          \
}                                                       \
else if((n) > 0)                                        \
{   (x)[0] = ((x)[0] >> (n)) | ((x)[1] << (-(n) & 31)); \
    (x)[1] = (x)[1] >> (n);                             \
}

#define lo(x)   ((x) & 0x0000ffff)
#define hi(x)   ((x) >> 16)

void mult_64(u8byte r, const u8byte x, const u8byte y)
{   u4byte  x0, x1, x2, x3, y0, y1, y2, y3, t0, t1, t2, t3, c;

x0 = lo(x[0]); x1 = hi(x[0]); x2 = lo(x[1]); x3 = hi(x[1]);
y0 = lo(y[0]); y1 = hi(y[0]); y2 = lo(y[1]); y3 = hi(y[1]);

t0 = x0 * y0; r[0] = lo(t0); c = hi(t0);

t0 = x0 * y1; t1 = x1 * y0; c += lo(t0) + lo(t1);
r[0] += (c << 16); c = hi(c) + hi(t0) + hi(t1);

t0 = x0 * y2; t1 = x1 * y1; t2 = x2 * y0;
c += lo(t0) + lo(t1) + lo(t2); r[1] = lo(c);
c = hi(c) + hi(t0) + hi(t1) + hi(t2);

t0 = x0 * y3; t1 = x1 * y2; t2 = x2 * y1; t3 = x3 * y0;
c += lo(t0) + lo(t1) + lo(t2) + lo(t3); r[1] += (c << 16);
/*
c = hi(c) + hi(t0) + hi(t1) + hi(t2) + hi(t3);

t0 = x1 * y3; t1 = x2 * y2; t2 = x3 * y1;
c += lo(t0) + lo(t1) + lo(t2); r[1][0] = lo(c);
c = hi(c) + hi(t0) + hi(t1) + hi(t2);

t0 = x2 * y3; t1 = x3 * y2; c += lo(t0) + lo(t1);
r[1][0] += (c << 16); c = hi(c) + hi(t0) + hi(t1);

r[1][1] = c + x3 * y3;
*/
};

u8byte  l_key[286]; /* storage for the key schedule         */

/* initialise the key schedule from the user supplied key   */

u4byte *set_key(const u4byte in_key[], const u4byte key_len)
{   u8byte  s[8], t;
u4byte  i, j, xs;

l_key[0][0] = p119[0] + 3; l_key[0][1] = p119[1];
t[0] = key_len; t[1] = 0; mult_64(l_key[1], e19, t);
l_key[2][0] = (r220[0] << 3) | (r220[1] >> 29);
l_key[2][1] = (r220[1] << 3) | (r220[0] >> 29);

for(i = 3; i < 256; ++i)
{
    t[0] = l_key[i - 3][0]; t[1] = l_key[i - 3][1]; lsh_eq(t, 41);
    l_key[i][0] = l_key[i - 3][0]; l_key[i][1] = l_key[i - 3][1];
    rsh_eq(l_key[i], 23);
    or_eq(l_key[i], t);
    xor_eq(l_key[i], l_key[i - 2]);
    add_eq(l_key[i], l_key[i - 1]);
}

l_key[0][1] ^= io_swap(in_key[0]); l_key[0][0] ^= io_swap(in_key[1]);
l_key[1][1] ^= io_swap(in_key[2]); l_key[1][0] ^= io_swap(in_key[3]);

if(key_len > 128)
{
    l_key[2][1] ^= io_swap(in_key[4]); l_key[2][0] ^= io_swap(in_key[5]);
}

if(key_len > 192)
{
    l_key[3][1] ^= io_swap(in_key[6]); l_key[3][0] ^= io_swap(in_key[7]);
}

for(i = 0; i < 8; ++i)
{
    s[i][0] = l_key[248 + i][0]; s[i][1] = l_key[248 + i][1];
}

for(j = 0; j < 3; ++j)
    for(i = 0; i < 256; ++i)
    {
        t[0] = l_key[i][0]; t[1] = l_key[i][1]; xor_eq(t, l_key[(i + 83) & 255]);
        add_eq(t, l_key[s[0][0] & 255]);
        xor_eq(s[0], t); add_eq(s[1], s[0]); xor_eq(s[3], s[2]);
        sub_eq(s[5], s[4]); xor_eq(s[7], s[6]);
        t[0] = s[0][0]; t[1] = s[0][1]; rsh_eq(t, 13); add_eq(s[3], t);
        t[0] = s[1][0]; t[1] = s[1][1]; lsh_eq(t, 11); xor_eq(s[4], t);
        t[0] = s[3][0]; t[1] = s[3][1];
        lsh_eq(t, s[1][0] & 31);
        xor_eq(s[5], t);
        t[0] = s[2][0]; t[1] = s[2][1]; rsh_eq(t, 17); add_eq(s[6], t);
        t[0] = s[3][0]; t[1] = s[3][1]; add_eq(t, s[4]); or_eq(s[7], t);
        sub_eq(s[2], s[5]);
        t[0] = s[6][0] ^ i; t[1] = s[6][1]; sub_eq(s[0], t);
        t[0] = s[5][0]; t[1] = s[5][1]; add_eq(t, p119); xor_eq(s[1], t);
        t[0] = s[7][0]; t[1] = s[7][1]; rsh_eq(t, j); add_eq(s[2], t);
        xor_eq(s[2], s[1]); sub_eq(s[4], s[3]);
        xor_eq(s[6], s[5]); add_eq(s[0], s[7]);
        l_key[i][0] = s[2][0]; l_key[i][1] = s[2][1]; add_eq(l_key[i], s[6]);
    }

for(i = 0; i < 30; ++i)
{
    l_key[256 + i][0] = l_key[i][0]; l_key[256 + i][1] = l_key[i][1];
}

return (u4byte*)l_key;
};

/* encrypt a block of text  */
void encrypt(const u4byte in_blk[4], u4byte out_blk[4])
{
u8byte  s0, s1, k, kk, t;
u4byte  tt, xs;
s4byte  i;
s0[1] = io_swap(in_blk[0]); s0[0] = io_swap(in_blk[1]);
s1[1] = io_swap(in_blk[2]); s1[0] = io_swap(in_blk[3]);
add_eq(s0, l_key[128]); add_eq(s1, l_key[129]);
for(i = 0; i < 8; ++i)
{
    tt = s0[0] & 255; k[0] = l_key[tt][0]; k[1] = l_key[tt][1];
    add_eq(s1, k);  lsh_eq(k, 8); xor_eq(s0, k); xor_eq(s1, s0);
    t[0] = s1[0]; t[1] = s1[1]; rsh_eq(t, 11); sub_eq(s0, t);
    t[0] = s1[0]; t[1] = s1[1]; lsh_eq(t, 2); xor_eq(s0, t);
    sub_eq(s0, spice[i ^ 4]);
    t[0] = s0[0]; t[1] = s0[1]; lsh_eq(t, 32);
    kk[0] = p119[0] + 128; kk[1] = p119[1]; xor_eq(t, kk); add_eq(s0, t);
    t[0] = s0[0]; t[1] = s0[1]; rsh_eq(t, 17); xor_eq(s0, t);
    t[0] = s0[0]; t[1] = s0[1]; rsh_eq(t, 34); xor_eq(s0, t);
    t[0] = spice[i][0]; t[1] = spice[i][1]; xor_eq(s0, t);
    lsh_eq(t, 5); add_eq(s0, t);
    t[0] = spice[i][0]; t[1] = spice[i][1]; rsh_eq(t, 4);
    add_eq(s1, t); xor_eq(s0, t);
    t[0] = s0[0]; t[1] = s0[1]; lsh_eq(t, 22 + (s0[0] & 31)); add_eq(s0, t);
    t[0] = s0[0]; t[1] = s0[1]; rsh_eq(t, 23); xor_eq(s0, t);
    sub_eq(s0, spice[i ^ 7]);
    tt = s0[0] & 255; k[0] = l_key[tt][0]; k[1] = l_key[tt][1];
    tt += 3 * i + 1; kk[0] = l_key[tt][0]; kk[1] = l_key[tt][1];
    xor_eq(s1, k); t[0] = kk[0]; t[1] = kk[1]; lsh_eq(t, 8);
    xor_eq(s0, t); xor_eq(kk, k);
    t[0] = kk[0]; t[1] = kk[1]; rsh_eq(t, 5); add_eq(s1, t);
    t[0] = kk[0]; t[1] = kk[1]; lsh_eq(t, 12); sub_eq(s0, t);
    kk[0] &= ~255; xor_eq(s0, kk);  add_eq(s1, s0);
    t[0] = s1[0]; t[1] = s1[1]; lsh_eq(t, 3); add_eq(s0, t);
    xor_eq(s0, spice[i ^ 2]); add_eq(s0, l_key[144 + i]);
    t[0] = s0[0]; t[1] = s0[1]; lsh_eq(t, 22); add_eq(s0, t);
    t[0] = s1[0]; t[1] = s1[1]; rsh_eq(t, 4); xor_eq(s0, t);
    add_eq(s0, spice[i ^ 1]);
    t[0] = s0[0]; t[1] = s0[1]; rsh_eq(t, 33 + i); xor_eq(s0, t);
}
add_eq(s0, l_key[136]); add_eq(s1, l_key[137]);
out_blk[0] = io_swap(s0[1]); out_blk[1] = io_swap(s0[0]);
out_blk[2] = io_swap(s1[1]); out_blk[3] = io_swap(s1[0]);
};
/* decrypt a block of text  */
void decrypt(const u4byte in_blk[4], u4byte out_blk[4])
{
u8byte  s0, s1, k, kk, t;
u4byte  tt, xs;
s4byte  i;
s0[1] = io_swap(in_blk[0]); s0[0] = io_swap(in_blk[1]);
s1[1] = io_swap(in_blk[2]); s1[0] = io_swap(in_blk[3]);
sub_eq(s0, l_key[136]); sub_eq(s1, l_key[137]);
for(i = 7; i >= 0; --i)
{
    t[0] = s0[0]; t[1] = s0[1]; rsh_eq(t, 33 + i); xor_eq(s0, t);
    sub_eq(s0, spice[i ^ 1]);
    t[0] = s1[0]; t[1] = s1[1]; rsh_eq(t, 4); xor_eq(s0, t);
    k[0] = s0[0]; k[1] = s0[1]; lsh_eq(k, 22);
    t[0] = s0[0]; t[1] = s0[1]; sub_eq(t, k);
    lsh_eq(t, 22); sub_eq(s0, t); sub_eq(s0, l_key[144 + i]);
    xor_eq(s0, spice[i ^ 2]); t[0] = s1[0]; t[1] = s1[1]; lsh_eq(t, 3);
    sub_eq(s0, t); sub_eq(s1, s0);
    tt = s0[0] & 255; k[0] = l_key[tt][0]; k[1] = l_key[tt][1];
    tt += 3 * i + 1; kk[0] = l_key[tt][0]; kk[1] = l_key[tt][1]; xor_eq(kk, k);
    t[0] = kk[0] & ~255; t[1] = kk[1]; xor_eq(s0, t);
    t[0] = kk[0]; t[1] = kk[1]; lsh_eq(t, 12); add_eq(s0, t);
    t[0] = kk[0]; t[1] = kk[1]; rsh_eq(t, 5); sub_eq(s1, t);
    kk[0] = l_key[tt][0]; kk[1] = l_key[tt][1]; lsh_eq(kk, 8);
    xor_eq(s0, kk); xor_eq(s1, k); add_eq(s0, spice[i ^ 7]);
    t[0] = s0[0]; t[1] = s0[1]; rsh_eq(t, 23); xor_eq(s0, t);
    t[0] = s0[0]; t[1] = s0[1]; rsh_eq(t, 46); xor_eq(s0, t);
    tt = 22 + (s0[0] & 31); t[0] = s0[0]; t[1] = s0[1]; lsh_eq(t, tt);
    kk[0] = s0[0]; kk[1] = s0[1]; sub_eq(kk, t); lsh_eq(kk, tt); sub_eq(s0, kk);
    t[0] = kk[0] = spice[i][0]; t[1] = kk[1] = spice[i][1]; rsh_eq(kk, 4);
    xor_eq(s0, kk); sub_eq(s1, kk); k[0] = t[0]; k[1] = t[1]; lsh_eq(k, 5);
    sub_eq(s0, k); xor_eq(s0, t);
    t[0] = s0[0]; t[1] = s0[1]; rsh_eq(t, 17); xor_eq(s0, t);
    t[0] = p119[0] + 128; t[1] = p119[1]; k[0] = s0[0]; k[1] = s0[1];
    sub_eq(k, t); lsh_eq(k, 32); xor_eq(t, k); sub_eq(s0, t);
    add_eq(s0, spice[i ^ 4]); t[0] = s1[0]; t[1] = s1[1]; lsh_eq(t, 2);
    xor_eq(s0, t); t[0] = s1[0]; t[1] = s1[1]; rsh_eq(t, 11); add_eq(s0, t);
    xor_eq(s1, s0); tt = s0[0] & 255; k[0] = l_key[tt][0]; k[1] = l_key[tt][1];
    t[0] = k[0]; t[1] = k[1]; lsh_eq(t, 8); xor_eq(s0, t); sub_eq(s1, k);
}
sub_eq(s0, l_key[128]); sub_eq(s1, l_key[129]);
out_blk[0] = io_swap(s0[1]); out_blk[1] = io_swap(s0[0]);
out_blk[2] = io_swap(s1[1]); out_blk[3] = io_swap(s1[0]);
};

You are correct that the cipher is in public domain. In fact, I'm wondering that no one pointed you to the source code yet because it's part of the source code that accompanies "Applied Cryptography, Second Edition" by Bruce Schneier.

Keeping it short... at https://www.schneier.com/book-applied-source.html, you will find

HPC.ZIP
Author : Dr. Brian Gladman
Date : 14 Jan 99
Description: HPC block cipher, candidate for AES.

The download which is available for free via https://www.schneier.com/sccd/HPC.ZIP contains the following sourcecode, which should be exactly what you're looking for…

std_defs.h

/* 1. Standard types for AES cryptography source code               */

typedef unsigned char   u1byte; /* an 8 bit unsigned character type */
typedef unsigned short  u2byte; /* a 16 bit unsigned integer type   */
typedef unsigned long   u4byte; /* a 32 bit unsigned integer type   */

typedef signed char     s1byte; /* an 8 bit signed character type   */
typedef signed short    s2byte; /* a 16 bit signed integer type     */
typedef signed long     s4byte; /* a 32 bit signed integer type     */

/* 2. Standard interface for AES cryptographic routines             */

/* These are all based on 32 bit unsigned values and will therefore */
/* require endian conversions for big-endian architectures          */

#ifdef  __cplusplus
    extern "C"
    {
#endif

    char **cipher_name(void);
    u4byte *set_key(const u4byte in_key[], const u4byte key_len);
    void encrypt(const u4byte in_blk[4], u4byte out_blk[4]);
    void decrypt(const u4byte in_blk[4], u4byte out_blk[4]);

#ifdef  __cplusplus
    };
#endif

/* 3. Basic macros for speeding up generic operations               */

/* Circular rotate of 32 bit values                                 */

#ifdef _MSC_VER

#  include <stdlib.h>
#  pragma intrinsic(_lrotr,_lrotl)
#  define rotr(x,n) _lrotr(x,n)
#  define rotl(x,n) _lrotl(x,n)

#else

#define rotr(x,n)   (((x) >> ((int)(n))) | ((x) << (32 - (int)(n))))
#define rotl(x,n)   (((x) << ((int)(n))) | ((x) >> (32 - (int)(n))))

#endif

/* Invert byte order in a 32 bit variable                           */

#define bswap(x)    (rotl(x, 8) & 0x00ff00ff | rotr(x, 8) & 0xff00ff00)

/* Extract byte from a 32 bit quantity (little endian notation)     */

#define byte(x,n)   ((u1byte)((x) >> (8 * n)))

/* For inverting byte order in input/output 32 bit words if needed  */

#ifdef  BLOCK_SWAP
#define BYTE_SWAP
#define WORD_SWAP
#endif

#ifdef  BYTE_SWAP
#define io_swap(x)  bswap(x)
#else
#define io_swap(x)  (x)
#endif

/* For inverting the byte order of input/output blocks if needed    */

#ifdef  WORD_SWAP

#define get_block(x)                            \
    ((u4byte*)(x))[0] = io_swap(in_blk[3]);     \
    ((u4byte*)(x))[1] = io_swap(in_blk[2]);     \
    ((u4byte*)(x))[2] = io_swap(in_blk[1]);     \
    ((u4byte*)(x))[3] = io_swap(in_blk[0])

#define put_block(x)                            \
    out_blk[3] = io_swap(((u4byte*)(x))[0]);    \
    out_blk[2] = io_swap(((u4byte*)(x))[1]);    \
    out_blk[1] = io_swap(((u4byte*)(x))[2]);    \
    out_blk[0] = io_swap(((u4byte*)(x))[3])

#define get_key(x,len)                          \
    ((u4byte*)(x))[4] = ((u4byte*)(x))[5] =     \
    ((u4byte*)(x))[6] = ((u4byte*)(x))[7] = 0;  \
    switch((((len) + 63) / 64)) {               \
    case 2:                                     \
    ((u4byte*)(x))[0] = io_swap(in_key[3]);     \
    ((u4byte*)(x))[1] = io_swap(in_key[2]);     \
    ((u4byte*)(x))[2] = io_swap(in_key[1]);     \
    ((u4byte*)(x))[3] = io_swap(in_key[0]);     \
    break;                                      \
    case 3:                                     \
    ((u4byte*)(x))[0] = io_swap(in_key[5]);     \
    ((u4byte*)(x))[1] = io_swap(in_key[4]);     \
    ((u4byte*)(x))[2] = io_swap(in_key[3]);     \
    ((u4byte*)(x))[3] = io_swap(in_key[2]);     \
    ((u4byte*)(x))[4] = io_swap(in_key[1]);     \
    ((u4byte*)(x))[5] = io_swap(in_key[0]);     \
    break;                                      \
    case 4:                                     \
    ((u4byte*)(x))[0] = io_swap(in_key[7]);     \
    ((u4byte*)(x))[1] = io_swap(in_key[6]);     \
    ((u4byte*)(x))[2] = io_swap(in_key[5]);     \
    ((u4byte*)(x))[3] = io_swap(in_key[4]);     \
    ((u4byte*)(x))[4] = io_swap(in_key[3]);     \
    ((u4byte*)(x))[5] = io_swap(in_key[2]);     \
    ((u4byte*)(x))[6] = io_swap(in_key[1]);     \
    ((u4byte*)(x))[7] = io_swap(in_key[0]);     \
    }

#else

#define get_block(x)                            \
    ((u4byte*)(x))[0] = io_swap(in_blk[0]);     \
    ((u4byte*)(x))[1] = io_swap(in_blk[1]);     \
    ((u4byte*)(x))[2] = io_swap(in_blk[2]);     \
    ((u4byte*)(x))[3] = io_swap(in_blk[3])

#define put_block(x)                            \
    out_blk[0] = io_swap(((u4byte*)(x))[0]);    \
    out_blk[1] = io_swap(((u4byte*)(x))[1]);    \
    out_blk[2] = io_swap(((u4byte*)(x))[2]);    \
    out_blk[3] = io_swap(((u4byte*)(x))[3])

#define get_key(x,len)                          \
    ((u4byte*)(x))[4] = ((u4byte*)(x))[5] =     \
    ((u4byte*)(x))[6] = ((u4byte*)(x))[7] = 0;  \
    switch((((len) + 63) / 64)) {               \
    case 4:                                     \
    ((u4byte*)(x))[6] = io_swap(in_key[6]);     \
    ((u4byte*)(x))[7] = io_swap(in_key[7]);     \
    case 3:                                     \
    ((u4byte*)(x))[4] = io_swap(in_key[4]);     \
    ((u4byte*)(x))[5] = io_swap(in_key[5]);     \
    case 2:                                     \
    ((u4byte*)(x))[0] = io_swap(in_key[0]);     \
    ((u4byte*)(x))[1] = io_swap(in_key[1]);     \
    ((u4byte*)(x))[2] = io_swap(in_key[2]);     \
    ((u4byte*)(x))[3] = io_swap(in_key[3]);     \
    }

#endif

hpc.c

/* This is an independent implementation of the encryption algorithm:   */

/*                                                                      */
/*         HPC-128 by Richard Schroeppel                                */
/*                                                                      */
/* which is a candidate algorithm in the Advanced Encryption Standard   */
/* programme of the US National Institute of Standards and Technology.  */
/*                                                                      */
/* Copyright in this implementation is held by Dr B R Gladman but I     */
/* hereby give permission for its free direct or derivative use subject */
/* to acknowledgment of its origin and compliance with any conditions   */
/* that the originators of the algorithm place on its exploitation.     */
/*                                                                      */
/* Dr Brian Gladman ([email protected]) 14th January 1999     */

/* Timing data for HPC (hpc.c)

Core timing without I/O endian conversion:

128 bit key:
Key Setup:  120749 cycles
Encrypt:      1429 cycles =    17.9 mbits/sec
Decrypt:      1599 cycles =    16.0 mbits/sec
Mean:         1514 cycles =    16.9 mbits/sec

192 bit key:
Key Setup:  120754 cycles
Encrypt:      1477 cycles =    17.3 mbits/sec
Decrypt:      1599 cycles =    16.0 mbits/sec
Mean:         1538 cycles =    16.6 mbits/sec

256 bit key:
Key Setup:  120731 cycles
Encrypt:      1462 cycles =    17.5 mbits/sec
Decrypt:      1590 cycles =    16.1 mbits/sec
Mean:         1526 cycles =    16.8 mbits/sec

Full timing with I/O endian conversion:

128 bit key:
Key Setup:  118606 cycles
Encrypt:      1479 cycles =    17.3 mbits/sec
Decrypt:      1599 cycles =    16.0 mbits/sec
Mean:         1539 cycles =    16.6 mbits/sec

192 bit key:
Key Setup:  118538 cycles
Encrypt:      1480 cycles =    17.3 mbits/sec
Decrypt:      1583 cycles =    16.2 mbits/sec
Mean:         1532 cycles =    16.7 mbits/sec

256 bit key:
Key Setup:  118532 cycles
Encrypt:      1465 cycles =    17.5 mbits/sec
Decrypt:      1599 cycles =    16.0 mbits/sec
Mean:         1532 cycles =    16.7 mbits/sec

*/

#define BYTE_SWAP

#ifdef CORE_TIME
#  undef BYTE_SWAP
#endif

#include "../std_defs.h"

static char *alg_name[] = { "hpc", "hpc.c", "hpc" };

char **cipher_name()
{
return alg_name;
}

typedef u4byte  u8byte[2];

u8byte  l_key[286];
u8byte  spice[8] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

u8byte  p119 = { 0xa23249d6, 0x2b992ddf };
u8byte  e19  = { 0xc0b36173, 0x25b946eb };
u8byte  r220 = { 0xe9e17158, 0xc442f56b };

#define xor_eq(x,y)     (x)[0] ^= (y)[0]; (x)[1] ^= (y)[1]
#define and_eq(x,y)     (x)[0] &= (y)[0]; (x)[1] &= (y)[1]
#define  or_eq(x,y)     (x)[0] |= (y)[0]; (x)[1] |= (y)[1]

#define add_eq(x,y)     (x)[1] += (y)[1] + (((x)[0] += (y)[0]) < (y)[0] ? 1 : 0)
#define sub_eq(x,y)     xs = (x)[0]; (x)[1] -= (y)[1] + (((x)[0] -= (y)[0]) > xs ? 1 : 0)

#define lsh_eq(x,n)                                         \
if((n) > 31)                                            \
{   (x)[1] = (x)[0] << ((n) & 31); (x)[0] = 0;          \
}                                                       \
else if((n) > 0)                                        \
{   (x)[1] = ((x)[1] << (n)) | ((x)[0] >> (-(n) & 31)); \
    (x)[0] = (x)[0] << (n);                             \
}

#define rsh_eq(x,n)                                         \
if((n) > 31)                                            \
{   (x)[0] = (x)[1] >> ((n) & 31); (x)[1] = 0;          \
}                                                       \
else if((n) > 0)                                        \
{   (x)[0] = ((x)[0] >> (n)) | ((x)[1] << (-(n) & 31)); \
    (x)[1] = (x)[1] >> (n);                             \
}

#define lo(x)   ((x) & 0x0000ffff)
#define hi(x)   ((x) >> 16)

void mult_64(u8byte r, const u8byte x, const u8byte y)
{   u4byte  x0, x1, x2, x3, y0, y1, y2, y3, t0, t1, t2, t3, c;

x0 = lo(x[0]); x1 = hi(x[0]); x2 = lo(x[1]); x3 = hi(x[1]);
y0 = lo(y[0]); y1 = hi(y[0]); y2 = lo(y[1]); y3 = hi(y[1]);

t0 = x0 * y0; r[0] = lo(t0); c = hi(t0);

t0 = x0 * y1; t1 = x1 * y0; c += lo(t0) + lo(t1);
r[0] += (c << 16); c = hi(c) + hi(t0) + hi(t1);

t0 = x0 * y2; t1 = x1 * y1; t2 = x2 * y0;
c += lo(t0) + lo(t1) + lo(t2); r[1] = lo(c);
c = hi(c) + hi(t0) + hi(t1) + hi(t2);

t0 = x0 * y3; t1 = x1 * y2; t2 = x2 * y1; t3 = x3 * y0;
c += lo(t0) + lo(t1) + lo(t2) + lo(t3); r[1] += (c << 16);
/*
c = hi(c) + hi(t0) + hi(t1) + hi(t2) + hi(t3);

t0 = x1 * y3; t1 = x2 * y2; t2 = x3 * y1;
c += lo(t0) + lo(t1) + lo(t2); r[1][0] = lo(c);
c = hi(c) + hi(t0) + hi(t1) + hi(t2);

t0 = x2 * y3; t1 = x3 * y2; c += lo(t0) + lo(t1);
r[1][0] += (c << 16); c = hi(c) + hi(t0) + hi(t1);

r[1][1] = c + x3 * y3;
*/
};

u8byte  l_key[286]; /* storage for the key schedule         */

/* initialise the key schedule from the user supplied key   */

u4byte *set_key(const u4byte in_key[], const u4byte key_len)
{   u8byte  s[8], t;
u4byte  i, j, xs;

l_key[0][0] = p119[0] + 3; l_key[0][1] = p119[1];
t[0] = key_len; t[1] = 0; mult_64(l_key[1], e19, t);
l_key[2][0] = (r220[0] << 3) | (r220[1] >> 29);
l_key[2][1] = (r220[1] << 3) | (r220[0] >> 29);

for(i = 3; i < 256; ++i)
{
    t[0] = l_key[i - 3][0]; t[1] = l_key[i - 3][1]; lsh_eq(t, 41);
    l_key[i][0] = l_key[i - 3][0]; l_key[i][1] = l_key[i - 3][1];
    rsh_eq(l_key[i], 23);
    or_eq(l_key[i], t);
    xor_eq(l_key[i], l_key[i - 2]);
    add_eq(l_key[i], l_key[i - 1]);
}

l_key[0][1] ^= io_swap(in_key[0]); l_key[0][0] ^= io_swap(in_key[1]);
l_key[1][1] ^= io_swap(in_key[2]); l_key[1][0] ^= io_swap(in_key[3]);

if(key_len > 128)
{
    l_key[2][1] ^= io_swap(in_key[4]); l_key[2][0] ^= io_swap(in_key[5]);
}

if(key_len > 192)
{
    l_key[3][1] ^= io_swap(in_key[6]); l_key[3][0] ^= io_swap(in_key[7]);
}

for(i = 0; i < 8; ++i)
{
    s[i][0] = l_key[248 + i][0]; s[i][1] = l_key[248 + i][1];
}

for(j = 0; j < 3; ++j)
    for(i = 0; i < 256; ++i)
    {
        t[0] = l_key[i][0]; t[1] = l_key[i][1]; xor_eq(t, l_key[(i + 83) & 255]);
        add_eq(t, l_key[s[0][0] & 255]);
        xor_eq(s[0], t); add_eq(s[1], s[0]); xor_eq(s[3], s[2]);
        sub_eq(s[5], s[4]); xor_eq(s[7], s[6]);
        t[0] = s[0][0]; t[1] = s[0][1]; rsh_eq(t, 13); add_eq(s[3], t);
        t[0] = s[1][0]; t[1] = s[1][1]; lsh_eq(t, 11); xor_eq(s[4], t);
        t[0] = s[3][0]; t[1] = s[3][1];
        lsh_eq(t, s[1][0] & 31);
        xor_eq(s[5], t);
        t[0] = s[2][0]; t[1] = s[2][1]; rsh_eq(t, 17); add_eq(s[6], t);
        t[0] = s[3][0]; t[1] = s[3][1]; add_eq(t, s[4]); or_eq(s[7], t);
        sub_eq(s[2], s[5]);
        t[0] = s[6][0] ^ i; t[1] = s[6][1]; sub_eq(s[0], t);
        t[0] = s[5][0]; t[1] = s[5][1]; add_eq(t, p119); xor_eq(s[1], t);
        t[0] = s[7][0]; t[1] = s[7][1]; rsh_eq(t, j); add_eq(s[2], t);
        xor_eq(s[2], s[1]); sub_eq(s[4], s[3]);
        xor_eq(s[6], s[5]); add_eq(s[0], s[7]);
        l_key[i][0] = s[2][0]; l_key[i][1] = s[2][1]; add_eq(l_key[i], s[6]);
    }

for(i = 0; i < 30; ++i)
{
    l_key[256 + i][0] = l_key[i][0]; l_key[256 + i][1] = l_key[i][1];
}

return (u4byte*)l_key;
};

/* encrypt a block of text  */
void encrypt(const u4byte in_blk[4], u4byte out_blk[4])
{
u8byte  s0, s1, k, kk, t;
u4byte  tt, xs;
s4byte  i;
s0[1] = io_swap(in_blk[0]); s0[0] = io_swap(in_blk[1]);
s1[1] = io_swap(in_blk[2]); s1[0] = io_swap(in_blk[3]);
add_eq(s0, l_key[128]); add_eq(s1, l_key[129]);
for(i = 0; i < 8; ++i)
{
    tt = s0[0] & 255; k[0] = l_key[tt][0]; k[1] = l_key[tt][1];
    add_eq(s1, k);  lsh_eq(k, 8); xor_eq(s0, k); xor_eq(s1, s0);
    t[0] = s1[0]; t[1] = s1[1]; rsh_eq(t, 11); sub_eq(s0, t);
    t[0] = s1[0]; t[1] = s1[1]; lsh_eq(t, 2); xor_eq(s0, t);
    sub_eq(s0, spice[i ^ 4]);
    t[0] = s0[0]; t[1] = s0[1]; lsh_eq(t, 32);
    kk[0] = p119[0] + 128; kk[1] = p119[1]; xor_eq(t, kk); add_eq(s0, t);
    t[0] = s0[0]; t[1] = s0[1]; rsh_eq(t, 17); xor_eq(s0, t);
    t[0] = s0[0]; t[1] = s0[1]; rsh_eq(t, 34); xor_eq(s0, t);
    t[0] = spice[i][0]; t[1] = spice[i][1]; xor_eq(s0, t);
    lsh_eq(t, 5); add_eq(s0, t);
    t[0] = spice[i][0]; t[1] = spice[i][1]; rsh_eq(t, 4);
    add_eq(s1, t); xor_eq(s0, t);
    t[0] = s0[0]; t[1] = s0[1]; lsh_eq(t, 22 + (s0[0] & 31)); add_eq(s0, t);
    t[0] = s0[0]; t[1] = s0[1]; rsh_eq(t, 23); xor_eq(s0, t);
    sub_eq(s0, spice[i ^ 7]);
    tt = s0[0] & 255; k[0] = l_key[tt][0]; k[1] = l_key[tt][1];
    tt += 3 * i + 1; kk[0] = l_key[tt][0]; kk[1] = l_key[tt][1];
    xor_eq(s1, k); t[0] = kk[0]; t[1] = kk[1]; lsh_eq(t, 8);
    xor_eq(s0, t); xor_eq(kk, k);
    t[0] = kk[0]; t[1] = kk[1]; rsh_eq(t, 5); add_eq(s1, t);
    t[0] = kk[0]; t[1] = kk[1]; lsh_eq(t, 12); sub_eq(s0, t);
    kk[0] &= ~255; xor_eq(s0, kk);  add_eq(s1, s0);
    t[0] = s1[0]; t[1] = s1[1]; lsh_eq(t, 3); add_eq(s0, t);
    xor_eq(s0, spice[i ^ 2]); add_eq(s0, l_key[144 + i]);
    t[0] = s0[0]; t[1] = s0[1]; lsh_eq(t, 22); add_eq(s0, t);
    t[0] = s1[0]; t[1] = s1[1]; rsh_eq(t, 4); xor_eq(s0, t);
    add_eq(s0, spice[i ^ 1]);
    t[0] = s0[0]; t[1] = s0[1]; rsh_eq(t, 33 + i); xor_eq(s0, t);
}
add_eq(s0, l_key[136]); add_eq(s1, l_key[137]);
out_blk[0] = io_swap(s0[1]); out_blk[1] = io_swap(s0[0]);
out_blk[2] = io_swap(s1[1]); out_blk[3] = io_swap(s1[0]);
};
/* decrypt a block of text  */
void decrypt(const u4byte in_blk[4], u4byte out_blk[4])
{
u8byte  s0, s1, k, kk, t;
u4byte  tt, xs;
s4byte  i;
s0[1] = io_swap(in_blk[0]); s0[0] = io_swap(in_blk[1]);
s1[1] = io_swap(in_blk[2]); s1[0] = io_swap(in_blk[3]);
sub_eq(s0, l_key[136]); sub_eq(s1, l_key[137]);
for(i = 7; i >= 0; --i)
{
    t[0] = s0[0]; t[1] = s0[1]; rsh_eq(t, 33 + i); xor_eq(s0, t);
    sub_eq(s0, spice[i ^ 1]);
    t[0] = s1[0]; t[1] = s1[1]; rsh_eq(t, 4); xor_eq(s0, t);
    k[0] = s0[0]; k[1] = s0[1]; lsh_eq(k, 22);
    t[0] = s0[0]; t[1] = s0[1]; sub_eq(t, k);
    lsh_eq(t, 22); sub_eq(s0, t); sub_eq(s0, l_key[144 + i]);
    xor_eq(s0, spice[i ^ 2]); t[0] = s1[0]; t[1] = s1[1]; lsh_eq(t, 3);
    sub_eq(s0, t); sub_eq(s1, s0);
    tt = s0[0] & 255; k[0] = l_key[tt][0]; k[1] = l_key[tt][1];
    tt += 3 * i + 1; kk[0] = l_key[tt][0]; kk[1] = l_key[tt][1]; xor_eq(kk, k);
    t[0] = kk[0] & ~255; t[1] = kk[1]; xor_eq(s0, t);
    t[0] = kk[0]; t[1] = kk[1]; lsh_eq(t, 12); add_eq(s0, t);
    t[0] = kk[0]; t[1] = kk[1]; rsh_eq(t, 5); sub_eq(s1, t);
    kk[0] = l_key[tt][0]; kk[1] = l_key[tt][1]; lsh_eq(kk, 8);
    xor_eq(s0, kk); xor_eq(s1, k); add_eq(s0, spice[i ^ 7]);
    t[0] = s0[0]; t[1] = s0[1]; rsh_eq(t, 23); xor_eq(s0, t);
    t[0] = s0[0]; t[1] = s0[1]; rsh_eq(t, 46); xor_eq(s0, t);
    tt = 22 + (s0[0] & 31); t[0] = s0[0]; t[1] = s0[1]; lsh_eq(t, tt);
    kk[0] = s0[0]; kk[1] = s0[1]; sub_eq(kk, t); lsh_eq(kk, tt); sub_eq(s0, kk);
    t[0] = kk[0] = spice[i][0]; t[1] = kk[1] = spice[i][1]; rsh_eq(kk, 4);
    xor_eq(s0, kk); sub_eq(s1, kk); k[0] = t[0]; k[1] = t[1]; lsh_eq(k, 5);
    sub_eq(s0, k); xor_eq(s0, t);
    t[0] = s0[0]; t[1] = s0[1]; rsh_eq(t, 17); xor_eq(s0, t);
    t[0] = p119[0] + 128; t[1] = p119[1]; k[0] = s0[0]; k[1] = s0[1];
    sub_eq(k, t); lsh_eq(k, 32); xor_eq(t, k); sub_eq(s0, t);
    add_eq(s0, spice[i ^ 4]); t[0] = s1[0]; t[1] = s1[1]; lsh_eq(t, 2);
    xor_eq(s0, t); t[0] = s1[0]; t[1] = s1[1]; rsh_eq(t, 11); add_eq(s0, t);
    xor_eq(s1, s0); tt = s0[0] & 255; k[0] = l_key[tt][0]; k[1] = l_key[tt][1];
    t[0] = k[0]; t[1] = k[1]; lsh_eq(t, 8); xor_eq(s0, t); sub_eq(s1, k);
}
sub_eq(s0, l_key[128]); sub_eq(s1, l_key[129]);
out_blk[0] = io_swap(s0[1]); out_blk[1] = io_swap(s0[0]);
out_blk[2] = io_swap(s1[1]); out_blk[3] = io_swap(s1[0]);
};
稚气少女 2025-01-14 22:30:34

认真地,重新考虑这个决定。仓促布丁几乎没有研究支持它,这意味着你真的不知道它是否安全。另外,正如维基百科文章所说:

在 AES 过程的早期,David Wagner 指出,相对较大的 Hasty Pudding 密钥类别是等效的,因为它们生成相同的密钥表。

这是一个非常糟糕的问题——如果密钥冲突,它们可以用来解密彼此的密文。

不用担心可变的密码块大小,而是解决您的输入问题。存在许多选项,包括在块前添加长度字段以及使用随机位填充到密码块大小。

Seriously, reconsider this decision. Hasty Pudding has very little research supporting it, which means you really have no idea if it is secure or not. Plus, as the Wikipedia article says:

Early in the AES process, David Wagner noted that relatively large classes of Hasty Pudding keys were equivalent in that they led to the same key table.

That's a really bad problem - if keys collide, they can be used to decrypt each other's cipher text.

Instead of worrying about variable cipher block size, fix your input problem. Lots of options exist, including prefixing the block with a length field and padding out to the cipher block size with random bits.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文