winmain @ 16错误

时间:2011-07-04 16:33:44

标签: c++ winmain

我在网上发现了这个代码,我试图编译它,但是gcc不断告诉我有一个undefined reference to WinMain@16。我不知道它来自哪里,所以我要发布整个代码。在网上搜索之后,我只找到了人们写错int main()的答案,并修复它使其有效。这个代码在这段代码中起作用。

/*
 * 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.  (Whitfield.Diffie@eng.sun.com)
 *
 * 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/leo@cs.adfa.oz.au)
 *
 * 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 */

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

4 个答案:

答案 0 :(得分:1)

您没有主要功能。您可能缺少一个原始源文件。你只需添加一个。

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

它应该编译和链接正常。

更新:刚刚注意到..

你已经有一个主要的宏观

 #ifdef TEST

只需添加

#define TEST 1

它将编译和链接正常。见this它有效。

答案 1 :(得分:1)

主要功能是有条件编译的。要使此源代码作为程序运行,您需要输入

#define TEST

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

答案 2 :(得分: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]是第一个参数,而不是应用程序名称,{{1 }}

如果定位Windows不是您想要的,请在gcc命令行中查找NULL并将其删除。根据@Kerrek SB对您的问题的帮助评论,将argv添加到命令行。如果您在执行此操作时遇到问题,请发布有关您的建筑环境的更多信息,我们将能够为您提供帮助。

答案 3 :(得分:0)

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

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

你应该好好去。