2011-07-04 70 views
-1

,我发现这个代码在网上和IM试图编译它,但GCC不断告诉我,有一个undefined reference to [email protected]。我不知道它来自哪里,所以即将发布整个代码。在网上搜索后,我只找到答案,在那里人们写错了int main(),并修复它使其工作。这在这个代码中起作用。的WinMain @ 16错误

/* 
* The GOST 28147-89 cipher 
* 
* This is based on the 25 Movember 1993 draft translation 
* by Aleksandr Malchik, with Whitfield Diffie, of the Government 
* Standard of the U.S.S.R. GOST 28149-89, "Cryptographic Transformation 
* Algorithm", effective 1 July 1990. ([email protected]) 
* 
* That is a draft, and may contain errors, which will be faithfully 
* reflected here, along with possible exciting new bugs. 
* 
* Some details have been cleared up by the paper "Soviet Encryption 
* Algorithm" by Josef Pieprzyk and Leonid Tombak of the University 
* of Wollongong, New South Wales. (josef/[email protected]) 
* 
* The standard is written by A. Zabotin (project leader), G.P. Glazkov, 
* and V.B. Isaeva. It was accepted and introduced into use by the 
* action of the State Standards Committee of the USSR on 2 June 89 as 
* No. 1409. It was to be reviewed in 1993, but whether anyone wishes 
* to take on this obligation from the USSR is questionable. 
* 
* This code is placed in the public domain. 
*/ 

/* 
* If you read the standard, it belabors the point of copying corresponding 
* bits from point A to point B quite a bit. It helps to understand that 
* the standard is uniformly little-endian, although it numbers bits from 
* 1 rather than 0, so bit n has value 2^(n-1). The least significant bit 
* of the 32-bit words that are manipulated in the algorithm is the first, 
* lowest-numbered, in the bit string. 
*/ 


/* A 32-bit data type */ 
#ifdef __alpha /* Any other 64-bit machines? */ 
typedef unsigned int word32; 
#else 
typedef unsigned long word32; 
#endif 

/* 
* The standard does not specify the contents of the 8 4 bit->4 bit 
* substitution boxes, saying they're a parameter of the network 
* being set up. For illustration purposes here, I have used 
* the first rows of the 8 S-boxes from the DES. (Note that the 
* DES S-boxes are numbered starting from 1 at the msb. In keeping 
* with the rest of the GOST, I have used little-endian numbering. 
* Thus, k8 is S-box 1. 
* 
* Obviously, a careful look at the cryptographic properties of the cipher 
* must be undertaken before "production" substitution boxes are defined. 
* 
* The standard also does not specify a standard bit-string representation 
* for the contents of these blocks. 
*/ 
static unsigned char const k8[16] = { 
    14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 }; 
static unsigned char const k7[16] = { 
    15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 }; 
static unsigned char const k6[16] = { 
    10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 }; 
static unsigned char const k5[16] = { 
    7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 }; 
static unsigned char const k4[16] = { 
    2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 }; 
static unsigned char const k3[16] = { 
    12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 }; 
static unsigned char const k2[16] = { 
    4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 }; 
static unsigned char const k1[16] = { 
    13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 }; 

/* Byte-at-a-time substitution boxes */ 
static unsigned char k87[256]; 
static unsigned char k65[256]; 
static unsigned char k43[256]; 
static unsigned char k21[256]; 

/* 
* Build byte-at-a-time subtitution tables. 
* This must be called once for global setup. 
*/ 
void 
kboxinit(void) 
{ 
    int i; 
    for (i = 0; i < 256; i++) { 
     k87[i] = k8[i >> 4] << 4 | k7[i & 15]; 
     k65[i] = k6[i >> 4] << 4 | k5[i & 15]; 
     k43[i] = k4[i >> 4] << 4 | k3[i & 15]; 
     k21[i] = k2[i >> 4] << 4 | k1[i & 15]; 
    } 
} 

/* 
* Do the substitution and rotation that are the core of the operation, 
* like the expansion, substitution and permutation of the DES. 
* It would be possible to perform DES-like optimisations and store 
* the table entries as 32-bit words, already rotated, but the 
* efficiency gain is questionable. 
* 
* This should be inlined for maximum speed 
*/ 
#if __GNUC__ 
__inline__ 
#endif 
static word32 
f(word32 x) 
{ 
    /* Do substitutions */ 
#if 0 
    /* This is annoyingly slow */ 
    x = k8[x>>28 & 15] << 28 | k7[x>>24 & 15] << 24 | 
     k6[x>>20 & 15] << 20 | k5[x>>16 & 15] << 16 | 
     k4[x>>12 & 15] << 12 | k3[x>> 8 & 15] << 8 | 
     k2[x>> 4 & 15] << 4 | k1[x  & 15]; 
#else 
    /* This is faster */ 
    x = k87[x>>24 & 255] << 24 | k65[x>>16 & 255] << 16 | 
     k43[x>> 8 & 255] << 8 | k21[x & 255]; 
#endif 

    /* Rotate left 11 bits */ 
    return x<<11 | x>>(32-11); 
} 

/* 
* The GOST standard defines the input in terms of bits 1..64, with 
* bit 1 being the lsb of in[0] and bit 64 being the msb of in[1]. 
* 
* The keys are defined similarly, with bit 256 being the msb of key[7]. 
*/ 
void 
gostcrypt(word32 const in[2], word32 out[2], word32 const key[8]) 
{ 
    register word32 n1, n2; /* As named in the GOST */ 

    n1 = in[0]; 
    n2 = in[1]; 

    /* Instead of swapping halves, swap names each round */ 
    n2 ^= f(n1+key[0]); 
    n1 ^= f(n2+key[1]); 
    n2 ^= f(n1+key[2]); 
    n1 ^= f(n2+key[3]); 
    n2 ^= f(n1+key[4]); 
    n1 ^= f(n2+key[5]); 
    n2 ^= f(n1+key[6]); 
    n1 ^= f(n2+key[7]); 

    n2 ^= f(n1+key[0]); 
    n1 ^= f(n2+key[1]); 
    n2 ^= f(n1+key[2]); 
    n1 ^= f(n2+key[3]); 
    n2 ^= f(n1+key[4]); 
    n1 ^= f(n2+key[5]); 
    n2 ^= f(n1+key[6]); 
    n1 ^= f(n2+key[7]); 

    n2 ^= f(n1+key[0]); 
    n1 ^= f(n2+key[1]); 
    n2 ^= f(n1+key[2]); 
    n1 ^= f(n2+key[3]); 
    n2 ^= f(n1+key[4]); 
    n1 ^= f(n2+key[5]); 
    n2 ^= f(n1+key[6]); 
    n1 ^= f(n2+key[7]); 

    n2 ^= f(n1+key[7]); 
    n1 ^= f(n2+key[6]); 
    n2 ^= f(n1+key[5]); 
    n1 ^= f(n2+key[4]); 
    n2 ^= f(n1+key[3]); 
    n1 ^= f(n2+key[2]); 
    n2 ^= f(n1+key[1]); 
    n1 ^= f(n2+key[0]); 

    /* There is no swap after the last round */ 
    out[0] = n2; 
    out[1] = n1; 
} 


/* 
* The key schedule is somewhat different for decryption. 
* (The key table is used once forward and three times backward.) 
* You could define an expanded key, or just write the code twice, 
* as done here. 
*/ 
void 
gostdecrypt(word32 const in[2], word32 out[2], word32 const key[8]) 
{ 
    register word32 n1, n2; /* As named in the GOST */ 

    n1 = in[0]; 
    n2 = in[1]; 

    n2 ^= f(n1+key[0]); 
    n1 ^= f(n2+key[1]); 
    n2 ^= f(n1+key[2]); 
    n1 ^= f(n2+key[3]); 
    n2 ^= f(n1+key[4]); 
    n1 ^= f(n2+key[5]); 
    n2 ^= f(n1+key[6]); 
    n1 ^= f(n2+key[7]); 

    n2 ^= f(n1+key[7]); 
    n1 ^= f(n2+key[6]); 
    n2 ^= f(n1+key[5]); 
    n1 ^= f(n2+key[4]); 
    n2 ^= f(n1+key[3]); 
    n1 ^= f(n2+key[2]); 
    n2 ^= f(n1+key[1]); 
    n1 ^= f(n2+key[0]); 

    n2 ^= f(n1+key[7]); 
    n1 ^= f(n2+key[6]); 
    n2 ^= f(n1+key[5]); 
    n1 ^= f(n2+key[4]); 
    n2 ^= f(n1+key[3]); 
    n1 ^= f(n2+key[2]); 
    n2 ^= f(n1+key[1]); 
    n1 ^= f(n2+key[0]); 

    n2 ^= f(n1+key[7]); 
    n1 ^= f(n2+key[6]); 
    n2 ^= f(n1+key[5]); 
    n1 ^= f(n2+key[4]); 
    n2 ^= f(n1+key[3]); 
    n1 ^= f(n2+key[2]); 
    n2 ^= f(n1+key[1]); 
    n1 ^= f(n2+key[0]); 

    out[0] = n2; 
    out[1] = n1; 
} 

/* 
* The GOST "Output feedback" standard. It seems closer morally 
* to the counter feedback mode some people have proposed for DES. 
* The avoidance of the short cycles that are possible in OFB seems 
* like a Good Thing. 
* 
* Calling it the stream mode makes more sense. 
* 
* The IV is encrypted with the key to produce the initial counter value. 
* Then, for each output block, a constant is added, modulo 2^32-1 
* (0 is represented as all-ones, not all-zeros), to each half of 
* the counter, and the counter is encrypted to produce the value 
* to XOR with the output. 
* 
* Len is the number of blocks. Sub-block encryption is 
* left as an exercise for the user. Remember that the 
* standard defines everything in a little-endian manner, 
* so you want to use the low bit of gamma[0] first. 
* 
* OFB is, of course, self-inverse, so there is only one function. 
*/ 

/* The constants for addition */ 
#define C1 0x01010104 
#define C2 0x01010101 

void 
gostofb(word32 const *in, word32 *out, int len, 
    word32 const iv[2], word32 const key[8]) 
{ 
    word32 temp[2];   /* Counter */ 
    word32 gamma[2];  /* Output XOR value */ 

    /* Compute starting value for counter */ 
    gostcrypt(iv, temp, key); 

    while (len--) { 
     temp[0] += C2; 
     if (temp[0] < C2)  /* Wrap modulo 2^32? */ 
      temp[0]++;  /* Make it modulo 2^32-1 */ 
     temp[1] += C1; 
     if (temp[1] < C1)  /* Wrap modulo 2^32? */ 
      temp[1]++;  /* Make it modulo 2^32-1 */ 

     gostcrypt(temp, gamma, key); 

     *out++ = *in++^gamma[0]; 
     *out++ = *in++^gamma[1]; 
    } 
} 

/* 
* The CFB mode is just what you'd expect. Each block of ciphertext y[] is 
* derived from the input x[] by the following pseudocode: 
* y[i] = x[i]^gostcrypt(y[i-1]) 
* x[i] = y[i]^gostcrypt(y[i-1]) 
* Where y[-1] is the IV. 
* 
* The IV is modified in place. Again, len is in *blocks*. 
*/ 

void 
gostcfbencrypt(word32 const *in, word32 *out, int len, 
      word32 iv[2], word32 const key[8]) 
{ 
    while (len--) { 
     gostcrypt(iv, iv, key); 
     iv[0] = *out++ ^= iv[0]; 
     iv[1] = *out++ ^= iv[1]; 
    } 
} 

void 
gostcfbdecrypt(word32 const *in, word32 *out, int len, 
      word32 iv[2], word32 const key[8]) 
{ 
    word32 t; 
    while (len--) { 
     gostcrypt(iv, iv, key); 
     t = *out; 
     *out++ ^= iv[0]; 
     iv[0] = t; 
     t = *out; 
     *out++ ^= iv[1]; 
     iv[1] = t; 
    } 
} 


/* 
* The message suthetication code uses only 16 of the 32 rounds. 
* There *is* a swap after the 16th round. 
* The last block should be padded to 64 bits with zeros. 
* len is the number of *blocks* in the input. 
*/ 
void 
gostmac(word32 const *in, int len, word32 out[2], word32 const key[8]) 
{ 
    register word32 n1, n2; /* As named in the GOST */ 

    n1 = 0; 
    n2 = 0; 

    while (len--) { 
     n1 ^= *in++; 
     n2 = *in++; 

     /* Instead of swapping halves, swap names each round */ 
     n2 ^= f(n1+key[0]); 
     n1 ^= f(n2+key[1]); 
     n2 ^= f(n1+key[2]); 
     n1 ^= f(n2+key[3]); 
     n2 ^= f(n1+key[4]); 
     n1 ^= f(n2+key[5]); 
     n2 ^= f(n1+key[6]); 
     n1 ^= f(n2+key[7]); 

     n2 ^= f(n1+key[0]); 
     n1 ^= f(n2+key[1]); 
     n2 ^= f(n1+key[2]); 
     n1 ^= f(n2+key[3]); 
     n2 ^= f(n1+key[4]); 
     n1 ^= f(n2+key[5]); 
     n2 ^= f(n1+key[6]); 
     n1 ^= f(n2+key[7]); 
    } 

    out[0] = n1; 
    out[1] = n2; 
} 

#ifdef TEST 

#include <stdio.h> 
#include <stdlib.h> 

/* Designed to cope with 15-bit rand() implementations */ 
#define RAND32 ((word32)rand() << 17^(word32)rand() << 9^rand()) 

int 
main(void) 
{ 
    word32 key[8]; 
    word32 plain[2]; 
    word32 cipher[2]; 
    int i, j; 

    kboxinit(); 

    printf("GOST 21847-89 test driver.\n"); 

    for (i = 0; i < 1000; i++) { 
     for (j = 0; j < 8; j++) 
      key[j] = RAND32; 
     plain[0] = RAND32; 
     plain[1] = RAND32; 

     printf("%3d\r", i); 
     fflush(stdout); 

     gostcrypt(plain, cipher, key); 
     for (j = 0; j < 99; j++) 
      gostcrypt(cipher, cipher, key); 
     for (j = 0; j < 100; j++) 
      gostdecrypt(cipher, cipher, key); 

     if (plain[0] != cipher[0] || plain[1] != cipher[1]) { 
      fprintf(stderr, "\nError! i = %d\n", i); 
      return 1; 
     } 
    } 
    printf("All tests passed.\n"); 
    return 0; 
} 

#endif /* TEST */ 

我该怎么做才能让这段代码运行?

+2

在mingw32?用'-mno-windows'链接它。 –

+0

@Kerrek的评论给出了不正确和愚蠢的建议。他没有看过代码。 –

+1

我们在1993年有什么Windows版本?自那以后会有什么改变吗? –

回答

1

主要功能是有条件编译的。为了使这个源代码的工作作为一个程序,你需要把

#define TEST 

#ifdef TEST指令之前的地方(在文件的开头好,所以这是可见的)。

+0

虽然我同意main是#ifdefed出这个代码,但这并不能解决他的问题。 –

1

您没有主要功能。您可能会丢失其中一个原始源文件。你只需添加一个。

int main(int argc, char *argv[]) 
{ 
    return 0; 
} 

它应该编译和链接很好。

更新:只是注意到..

你已经有一个主要由宏观

#ifdef TEST 

gaurded只需添加

#define TEST 1 

,它会编译和链接的罚款。见this它的工作原理。

+0

nope :(http://ideone.com/wIU0f – calccrypto

+0

@calccrypto:检查更新后的答案 –

0

您的目标是Windows子系统,因此您需要提供一个WinMain作为入口点,而不是主要的。如果针对Windows子系统,如果真的是你想要的,那么你可以交出一个简单的WinMain调用你的主。像这样:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nCmdShow) 
{ 
    PARAM_UNUSED(hInstance); 
    PARAM_UNUSED(hPrevInstance); 
    PARAM_UNUSED(nCmdShow); 

    int argc; 

    PCHAR* argv = CommandLineToArgvA(pCmdLine, &argc); 

    return main(argc, argv); 
} 

CommandLineToArgvA实现可以找到here

当心这个简单的实现,它的命令行参数,如在STDLIB版本不起作用:argv[0]是第一个参数,而不是应用程序的名称,而且也没有结束NULLargv

如果针对Windows是不是你打算在gcc命令行找了-mwindows并将其删除。基于@Kerrek SB对您的问题的帮助评论,请将-mno-windows添加到命令行中。如果您在这方面遇到困难,请发布有关您的建筑环境的更多信息,我们将能够提供帮助。

+0

-1“你的目标是Windows子系统因此你需要提供一个WinMain作为入口点,而不是主要的“是不正确的。” –

+0

@Alf P. Steinbach如何如此?请赐教。 –

+0

“怎么这样?”好吧,它只是普通的错误,不正确,不正确,你可以也应该为C或C++程序使用标准的C和C++'main',不管是GUI还是控制台子系统。使用g ++你不必做任何特别的事情,但是使用MSVC(愚蠢的工具链)您可能需要指定入口点作为链接器选项'/ entry:mainCRTStartup'。Cheers&hth。, –

0

Windows应用程序的主要功能称为WinMain。只需将main更改为:

int CALLBACK WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { ... } 

您应该很好地去。

+0

-1呃哦。不不不。首先,这是该程序的错误修复(他应该只定义'TEST'),其次,不,Windows应用程序的主要功能不叫“WinMain”。这只是一个古老的C和C++启动功能,C和C++工具必须支持历史原因。例如。它在帕斯卡​​尔没有。 :-) –

相关问题