2011-07-04 4 views
-1

이 코드는 온라인에서 발견되었으며 컴파일하는 중이지만 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

주 기능은 조건부로 컴파일됩니다. 프로그램으로이 소스 코드가 작동하려면, 당신은 어딘가에 #ifdef TEST 지시하기 전에

#define TEST 

을 둘 필요 (파일의 시작 부분에서 더 나은, 그래서 그것을 볼 수 있어요).

+0

메인 코드가이 코드에서 #ifdefed인데도 이것만으로는 문제가 해결되지 않습니다. –

1

주 기능이 없습니다. 원래 소스 파일 중 하나가 누락되었을 수 있습니다. 당신은 하나를 추가하기 만하면됩니다.

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

그리고 컴파일과 링크가 잘되어야합니다.

UPDATE : 그냥

당신은 이미 매크로

#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]는 첫 번째 매개 변수가 아닌 응용 프로그램 이름이고 더 NULL 종료는 argv에 없습니다.

Windows를 대상으로하지 않는 것이 gcc 명령 줄에서 -mwindows을 찾아 제거하려는 경우. @ Kerrek SB 귀하의 질문에 대한 호의적 인 의견을 바탕으로 명령 줄에 -mno-windows을 추가하십시오. 그렇게하는 데 어려움이있는 경우 건물 환경에 대한 자세한 정보를 게시하면 도움을 드릴 수 있습니다.

+0

-1 "타겟팅 중입니다. 따라서 Windows 하위 시스템이 메인이 아닌 진입 점으로 WinMain을 제공해야합니다 "라고 잘못 표기했습니다 –

+0

@Alf P. Steinbach 어떻게 그렇게됩니까? 제게 계몽 해주십시오 –

+0

"How so? "잘 그것은 틀린 거짓말이거나 틀린 것이 아닙니다. 내가 쓴 것처럼. 당신은 C 또는 C++ 프로그램을위한 표준 C와 C++'main'을 GUI 나 콘솔 서브 시스템과 상관없이 사용할 수 있어야한다 .g ++을 사용하면 특별한 일을 할 필요가 없지만 MSVC (바보 툴체인) 엔트리 포인트를 링커 옵션'/ entry : mainCRTStartup'으로 지정할 필요가 있습니다. 건배 & nbsp; –

0

Windows 응용 프로그램의 주요 기능은 WinMain입니다. 그냥에 main을 변경

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

하고 갈 수 있어야합니다.

+0

-1 어 오. 아니, 아니. 첫째,이 프로그램에 대한 잘못된 수정입니다 (그는 단지'TEST'를 정의해야합니다). 둘째, Windows 응용 프로그램의 주요 기능을 WinMain이라고 부르지 않습니다. 이것은 역사적인 이유로 C 및 C++ 툴 체인이 지원해야하는 고풍스러운 C 및 C++ 시작 기능입니다. 예 : 파스칼에는 없어요. :-) –

관련 문제