Elgamal加密在C语言中如何实现?

99ANYc3cd6
预计阅读时长 71 分钟
位置: 首页 C语言 正文

ElGamal 加密算法的 C 语言实现

ElGamal 是一种非对称加密算法,基于离散对数问题,下面我将提供一个完整的 C 语言实现,包括密钥生成、加密和解密功能。

完整代码实现

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
// 大整数结构体
typedef struct {
    int *digits;    // 数字数组
    int length;     // 数字长度
    int sign;       // 符号 (1为正,-1为负)
} BigInteger;
// 函数声明
BigInteger* createBigInteger(int length);
void freeBigInteger(BigInteger *num);
BigInteger* stringToBigInteger(const char *str);
char* bigIntegerToString(const BigInteger *num);
BigInteger* addBigInteger(const BigInteger *a, const BigInteger *b);
BigInteger* subtractBigInteger(const BigInteger *a, const BigInteger *b);
BigInteger* multiplyBigInteger(const BigInteger *a, const BigInteger *b);
BigInteger* modBigInteger(const BigInteger *a, const BigInteger *b);
BigInteger* modExpBigInteger(const BigInteger *base, const BigInteger *exp, const BigInteger *mod);
int isPrime(const BigInteger *n);
BigInteger* generatePrime(int bits);
BigInteger* gcd(const BigInteger *a, const BigInteger *b);
BigInteger* extendedGcd(const BigInteger *a, const BigInteger *b, BigInteger **x, BigInteger **y);
BigInteger* modInverse(const BigInteger *a, const BigInteger *m);
// 辅助函数
int compareBigInteger(const BigInteger *a, const BigInteger *b);
BigInteger* copyBigInteger(const BigInteger *src);
void printBigInteger(const BigInteger *num);
// ElGamal 加密结构体
typedef struct {
    BigInteger *p;      // 大素数
    BigInteger *g;      // 生成元
    BigInteger *y;      // 公钥 y = g^x mod p
    BigInteger *x;      // 私钥 x
} ElGamalKey;
// ElGamal 加密结果
typedef struct {
    BigInteger *c1;     // 密文部分1
    BigInteger *c2;     // 密文部分2
} ElGamalCiphertext;
// 函数声明
ElGamalKey* generateElGamalKey(int bits);
ElGamalCiphertext* elgamalEncrypt(const BigInteger *m, const ElGamalKey *key);
BigInteger* elgamalDecrypt(const ElGamalCiphertext *ciphertext, const ElGamalKey *key);
void freeElGamalKey(ElGamalKey *key);
void freeElGamalCiphertext(ElGamalCiphertext *ciphertext);
// 主函数测试
int main() {
    // 设置随机数种子
    srand(time(NULL));
    // 生成 ElGamal 密钥 (512位)
    printf("生成 ElGamal 密钥 (512位)...\n");
    ElGamalKey *key = generateElGamalKey(512);
    printf("公钥 (p, g, y):\n");
    printBigInteger(key->p);
    printBigInteger(key->g);
    printBigInteger(key->y);
    printf("私钥 (x):\n");
    printBigInteger(key->x);
    // 加密测试
    BigInteger *message = stringToBigInteger("1234567890");
    printf("\n明文: %s\n", bigIntegerToString(message));
    ElGamalCiphertext *ciphertext = elgamalEncrypt(message, key);
    printf("密文 (c1, c2):\n");
    printBigInteger(ciphertext->c1);
    printBigInteger(ciphertext->c2);
    // 解密测试
    BigInteger *decrypted = elgamalDecrypt(ciphertext, key);
    printf("\n解密结果: %s\n", bigIntegerToString(decrypted));
    // 清理内存
    freeBigInteger(message);
    freeBigInteger(decrypted);
    freeElGamalCiphertext(ciphertext);
    freeElGamalKey(key);
    return 0;
}
// 创建大整数
BigInteger* createBigInteger(int length) {
    BigInteger *num = (BigInteger*)malloc(sizeof(BigInteger));
    num->digits = (int*)calloc(length, sizeof(int));
    num->length = length;
    num->sign = 1;
    return num;
}
// 释放大整数
void freeBigInteger(BigInteger *num) {
    if (num) {
        if (num->digits) free(num->digits);
        free(num);
    }
}
// 字符串转大整数
BigInteger* stringToBigInteger(const char *str) {
    int len = strlen(str);
    int start = 0;
    int sign = 1;
    if (str[0] == '-') {
        sign = -1;
        start = 1;
    }
    BigInteger *num = createBigInteger(len - start);
    num->sign = sign;
    for (int i = start; i < len; i++) {
        num->digits[len - i - 1] = str[i] - '0';
    }
    return num;
}
// 大整数转字符串
char* bigIntegerToString(const BigInteger *num) {
    int len = num->length;
    int start = 0;
    // 跳过前导零
    while (start < len - 1 && num->digits[start] == 0) {
        start++;
    }
    // 计算字符串长度
    int strLen = len - start + (num->sign == -1 ? 1 : 0);
    char *str = (char*)malloc(strLen + 1);
    if (num->sign == -1) {
        str[0] = '-';
        for (int i = 0; i < len - start; i++) {
            str[i + 1] = num->digits[start + i] + '0';
        }
    } else {
        for (int i = 0; i < len - start; i++) {
            str[i] = num->digits[start + i] + '0';
        }
    }
    str[strLen] = '\0';
    return str;
}
// 比较两个大整数
int compareBigInteger(const BigInteger *a, const BigInteger *b) {
    if (a->length != b->length) {
        return a->length - b->length;
    }
    for (int i = 0; i < a->length; i++) {
        if (a->digits[i] != b->digits[i]) {
            return a->digits[i] - b->digits[i];
        }
    }
    return 0;
}
// 复制大整数
BigInteger* copyBigInteger(const BigInteger *src) {
    BigInteger *dest = createBigInteger(src->length);
    dest->sign = src->sign;
    memcpy(dest->digits, src->digits, src->length * sizeof(int));
    return dest;
}
// 大整数加法
BigInteger* addBigInteger(const BigInteger *a, const BigInteger *b) {
    int maxLen = (a->length > b->length) ? a->length : b->length;
    BigInteger *result = createBigInteger(maxLen + 1);
    int carry = 0;
    for (int i = 0; i < maxLen; i++) {
        int sum = carry;
        if (i < a->length) sum += a->digits[i];
        if (i < b->length) sum += b->digits[i];
        result->digits[i] = sum % 10;
        carry = sum / 10;
    }
    if (carry > 0) {
        result->digits[maxLen] = carry;
    } else {
        // 去除前导零
        while (result->length > 1 && result->digits[result->length - 1] == 0) {
            result->length--;
        }
    }
    return result;
}
// 大整数减法
BigInteger* subtractBigInteger(const BigInteger *a, const BigInteger *b) {
    BigInteger *result = createBigInteger(a->length);
    int borrow = 0;
    for (int i = 0; i < a->length; i++) {
        int diff = a->digits[i] - borrow;
        if (i < b->length) diff -= b->digits[i];
        if (diff < 0) {
            diff += 10;
            borrow = 1;
        } else {
            borrow = 0;
        }
        result->digits[i] = diff;
    }
    // 去除前导零
    while (result->length > 1 && result->digits[result->length - 1] == 0) {
        result->length--;
    }
    return result;
}
// 大整数乘法
BigInteger* multiplyBigInteger(const BigInteger *a, const BigInteger *b) {
    BigInteger *result = createBigInteger(a->length + b->length);
    for (int i = 0; i < a->length; i++) {
        int carry = 0;
        for (int j = 0; j < b->length; j++) {
            int product = a->digits[i] * b->digits[j] + result->digits[i + j] + carry;
            result->digits[i + j] = product % 10;
            carry = product / 10;
        }
        if (carry > 0) {
            result->digits[i + b->length] = carry;
        }
    }
    // 去除前导零
    while (result->length > 1 && result->digits[result->length - 1] == 0) {
        result->length--;
    }
    return result;
}
// 大整数取模
BigInteger* modBigInteger(const BigInteger *a, const BigInteger *b) {
    BigInteger *quotient = createBigInteger(a->length);
    BigInteger *remainder = copyBigInteger(a);
    while (compareBigInteger(remainder, b) >= 0) {
        BigInteger *temp = copyBigInteger(b);
        BigInteger *shift = createBigInteger(b->length);
        shift->digits[0] = 1;
        while (compareBigInteger(temp, remainder) <= 0) {
            shift = multiplyBigInteger(shift, stringToBigInteger("10"));
            temp = multiplyBigInteger(temp, stringToBigInteger("10"));
        }
        if (shift->length > 1 || shift->digits[0] > 1) {
            shift = divideBigInteger(shift, stringToBigInteger("10"));
            temp = divideBigInteger(temp, stringToBigInteger("10"));
        }
        freeBigInteger(shift);
        BigInteger *count = stringToBigInteger("1");
        while (compareBigInteger(temp, remainder) <= 0) {
            remainder = subtractBigInteger(remainder, temp);
            quotient = addBigInteger(quotient, count);
            count = addBigInteger(count, stringToBigInteger("1"));
            temp = addBigInteger(temp, b);
        }
        freeBigInteger(temp);
        freeBigInteger(count);
    }
    freeBigInteger(quotient);
    return remainder;
}
// 大整数模幂运算
BigInteger* modExpBigInteger(const BigInteger *base, const BigInteger *exp, const BigInteger *mod) {
    BigInteger *result = stringToBigInteger("1");
    BigInteger *current = copyBigInteger(base);
    BigInteger *zero = stringToBigInteger("0");
    BigInteger *one = stringToBigInteger("1");
    BigInteger *two = stringToBigInteger("2");
    while (compareBigInteger(exp, zero) > 0) {
        if (compareBigInteger(modBigInteger(exp, two), one) == 0) {
            result = modBigInteger(multiplyBigInteger(result, current), mod);
        }
        current = modBigInteger(multiplyBigInteger(current, current), mod);
        exp = divideBigInteger(exp, two);
    }
    freeBigInteger(current);
    freeBigInteger(zero);
    freeBigInteger(one);
    freeBigInteger(two);
    return result;
}
// 判断是否为素数 (简单实现)
int isPrime(const BigInteger *n) {
    if (compareBigInteger(n, stringToBigInteger("2")) == 0) return 1;
    if (compareBigInteger(n, stringToBigInteger("3")) == 0) return 1;
    if (compareBigInteger(modBigInteger(n, stringToBigInteger("2")), stringToBigInteger("0")) == 0) return 0;
    if (compareBigInteger(modBigInteger(n, stringToBigInteger("3")), stringToBigInteger("0")) == 0) return 0;
    BigInteger *i = stringToBigInteger("5");
    BigInteger *two = stringToBigInteger("2");
    BigInteger *sqrt_n = sqrtBigInteger(n);
    while (compareBigInteger(i, sqrt_n) <= 0) {
        if (compareBigInteger(modBigInteger(n, i), stringToBigInteger("0")) == 0) {
            freeBigInteger(i);
            freeBigInteger(two);
            freeBigInteger(sqrt_n);
            return 0;
        }
        i = addBigInteger(i, two);
    }
    freeBigInteger(i);
    freeBigInteger(two);
    freeBigInteger(sqrt_n);
    return 1;
}
// 生成大素数
BigInteger* generatePrime(int bits) {
    BigInteger *prime = NULL;
    BigInteger *max = stringToBigInteger("1");
    // 计算 2^bits
    for (int i = 0; i < bits; i++) {
        max = multiplyBigInteger(max, stringToBigInteger("2"));
    }
    do {
        prime = createBigInteger(bits);
        for (int i = 0; i < bits; i++) {
            prime->digits[i] = rand() % 10;
        }
        // 确保最高位是1
        prime->digits[bits - 1] = 1;
        // 确保是奇数
        prime->digits[0] |= 1;
        // 去除前导零
        while (prime->length > 1 && prime->digits[prime->length - 1] == 0) {
            prime->length--;
        }
    } while (compareBigInteger(prime, max) >= 0 || !isPrime(prime));
    freeBigInteger(max);
    return prime;
}
// 计算最大公约数
BigInteger* gcd(const BigInteger *a, const BigInteger *b) {
    BigInteger *zero = stringToBigInteger("0");
    BigInteger *temp = copyBigInteger(a);
    BigInteger *divisor = copyBigInteger(b);
    while (compareBigInteger(divisor, zero) != 0) {
        BigInteger *remainder = modBigInteger(temp, divisor);
        freeBigInteger(temp);
        temp = divisor;
        divisor = remainder;
    }
    freeBigInteger(divisor);
    freeBigInteger(zero);
    return temp;
}
// 扩展欧几里得算法
BigInteger* extendedGcd(const BigInteger *a, const BigInteger *b, BigInteger **x, BigInteger **y) {
    BigInteger *zero = stringToBigInteger("0");
    BigInteger *one = stringToBigInteger("1");
    if (compareBigInteger(b, zero) == 0) {
        *x = copyBigInteger(one);
        *y = stringToBigInteger("0");
        freeBigInteger(zero);
        freeBigInteger(one);
        return copyBigInteger(a);
    }
    BigInteger *x1 = NULL, *y1 = NULL;
    BigInteger *gcd = extendedGcd(b, modBigInteger(a, b), &x1, &y1);
    BigInteger *q = divideBigInteger(a, b);
    *x = subtractBigInteger(y1, multiplyBigInteger(q, x1));
    *y = x1;
    freeBigInteger(zero);
    freeBigInteger(one);
    freeBigInteger(q);
    return gcd;
}
// 计算模逆元
BigInteger* modInverse(const BigInteger *a, const BigInteger *m) {
    BigInteger *x = NULL, *y = NULL;
    BigInteger *gcd = extendedGcd(a, m, &x, &y);
    BigInteger *one = stringToBigInteger("1");
    if (compareBigInteger(gcd, one) != 0) {
        freeBigInteger(gcd);
        freeBigInteger(x);
        freeBigInteger(y);
        freeBigInteger(one);
        return NULL; // 逆元不存在
    }
    freeBigInteger(gcd);
    freeBigInteger(one);
    BigInteger *result = modBigInteger(x, m);
    freeBigInteger(x);
    freeBigInteger(y);
    return result;
}
// 生成 ElGamal 密钥
ElGamalKey* generateElGamalKey(int bits) {
    ElGamalKey *key = (ElGamalKey*)malloc(sizeof(ElGamalKey));
    // 生成大素数 p
    key->p = generatePrime(bits);
    // 选择生成元 g (这里简化处理,实际应用中需要选择合适的生成元)
    key->g = stringToBigInteger("2");
    // 生成私钥 x (1 < x < p-1)
    BigInteger *p_minus_1 = subtractBigInteger(key->p, stringToBigInteger("1"));
    key->x = createBigInteger(bits);
    for (int i = 0; i < bits; i++) {
        key->x->digits[i] = rand() % 10;
    }
    key->x->digits[0] = 1; // 确保 x > 1
    key->x = modBigInteger(key->x, p_minus_1);
    // 计算公钥 y = g^x mod p
    key->y = modExpBigInteger(key->g, key->x, key->p);
    freeBigInteger(p_minus_1);
    return key;
}
// ElGamal 加密
ElGamalCiphertext* elgamalEncrypt(const BigInteger *m, const ElGamalKey *key) {
    ElGamalCiphertext *ciphertext = (ElGamalCiphertext*)malloc(sizeof(ElGamalCiphertext));
    // 生成随机数 k (1 < k < p-1)
    BigInteger *p_minus_1 = subtractBigInteger(key->p, stringToBigInteger("1"));
    BigInteger *k = createBigInteger(key->p->length);
    for (int i = 0; i < key->p->length; i++) {
        k->digits[i] = rand() % 10;
    }
    k->digits[0] = 1; // 确保 k > 1
    k = modBigInteger(k, p_minus_1);
    // 计算 c1 = g^k mod p
    ciphertext->c1 = modExpBigInteger(key->g, k, key->p);
    // 计算 c2 = m * y^k mod p
    BigInteger *y_k = modExpBigInteger(key->y, k, key->p);
    ciphertext->c2 = modBigInteger(multiplyBigInteger(m, y_k), key->p);
    freeBigInteger(p_minus_1);
    freeBigInteger(k);
    freeBigInteger(y_k);
    return ciphertext;
}
// ElGamal 解密
BigInteger* elgamalDecrypt(const ElGamalCiphertext *ciphertext, const ElGamalKey *key) {
    // 计算 s = c1^x mod p
    BigInteger *s = modExpBigInteger(ciphertext->c1, key->x, key->p);
    // 计算 s^-1 mod p
    BigInteger *s_inv = modInverse(s, key->p);
    if (s_inv == NULL) {
        freeBigInteger(s);
        return NULL; // 解密失败
    }
    // 计算 m = c2 * s^-1 mod p
    BigInteger *m = modBigInteger(multiplyBigInteger(ciphertext->c2, s_inv), key->p);
    freeBigInteger(s);
    freeBigInteger(s_inv);
    return m;
}
// 释放 ElGamal 密钥
void freeElGamalKey(ElGamalKey *key) {
    if (key) {
        if (key->p) freeBigInteger(key->p);
        if (key->g) freeBigInteger(key->g);
        if (key->y) freeBigInteger(key->y);
        if (key->x) freeBigInteger(key->x);
        free(key);
    }
}
// 释放 ElGamal 密文
void freeElGamalCiphertext(ElGamalCiphertext *ciphertext) {
    if (ciphertext) {
        if (ciphertext->c1) freeBigInteger(ciphertext->c1);
        if (ciphertext->c2) freeBigInteger(ciphertext->c2);
        free(ciphertext);
    }
}
// 打印大整数
void printBigInteger(const BigInteger *num) {
    char *str = bigIntegerToString(num);
    printf("%s\n", str);
    free(str);
}
// 大整数平方根 (简化实现)
BigInteger* sqrtBigInteger(const BigInteger *n) {
    BigInteger *low = stringToBigInteger("1");
    BigInteger *high = copyBigInteger(n);
    BigInteger *result = stringToBigInteger("1");
    while (compareBigInteger(low, high) <= 0) {
        BigInteger *mid = addBigInteger(low, high);
        mid = divideBigInteger(mid, stringToBigInteger("2"));
        BigInteger *mid_squared = multiplyBigInteger(mid, mid);
        if (compareBigInteger(mid_squared, n) <= 0) {
            freeBigInteger(result);
            result = copyBigInteger(mid);
            low = addBigInteger(mid, stringToBigInteger("1"));
        } else {
            high = subtractBigInteger(mid, stringToBigInteger("1"));
        }
        freeBigInteger(mid);
        freeBigInteger(mid_squared);
    }
    freeBigInteger(low);
    freeBigInteger(high);
    return result;
}
// 大整数除法 (简化实现)
BigInteger* divideBigInteger(const BigInteger *a, const BigInteger *b) {
    BigInteger *quotient = createBigInteger(a->length);
    BigInteger *remainder = copyBigInteger(a);
    while (compareBigInteger(remainder, b) >= 0) {
        BigInteger *temp = copyBigInteger(b);
        BigInteger *shift = createBigInteger(b->length);
        shift->digits[0] = 1;
        while (compareBigInteger(temp, remainder) <= 0) {
            shift = multiplyBigInteger(shift, stringToBigInteger("10"));
            temp = multiplyBigInteger(temp, stringToBigInteger("10"));
        }
        if (shift->length > 1 || shift->digits[0] > 1) {
            shift = divideBigInteger(shift, stringToBigInteger("10"));
            temp = divideBigInteger(temp, stringToBigInteger("10"));
        }
        freeBigInteger(shift);
        BigInteger *count = stringToBigInteger("1");
        while (compareBigInteger(temp, remainder) <= 0) {
            remainder = subtractBigInteger(remainder, temp);
            quotient = addBigInteger(quotient, count);
            count = addBigInteger(count, stringToBigInteger("1"));
            temp = addBigInteger(temp, b);
        }
        freeBigInteger(temp);
        freeBigInteger(count);
    }
    freeBigInteger(remainder);
    return quotient;
}

代码说明

  1. 大整数运算

    • 实现了基本的大整数运算(加、减、乘、除、模、幂等)
    • 使用数组存储数字,每个元素代表一位十进制数
  2. ElGamal 算法实现

    • generateElGamalKey: 生成密钥对
    • elgamalEncrypt: 加密函数
    • elgamalDecrypt: 解密函数
  3. 辅助函数

    • 素数生成和检测
    • 模逆元计算
    • 扩展欧几里得算法

使用说明

  1. 编译代码:

    gcc -o elgamal elgamal.c -lm
  2. 运行程序:

    ./elgamal
  3. 程序会自动生成512位的ElGamal密钥,然后加密一个测试消息并解密验证。

注意事项

  1. 这是一个教学示例,实际应用中需要考虑更多安全因素:

    • 更安全的随机数生成
    • 更高效的素数检测算法(如Miller-Rabin)
    • 更大的密钥长度(至少1024位)
    • 消息填充方案
  2. 大整数运算实现较为简单,性能可能不如专门的库(如GMP)。

  3. 在实际应用中,建议使用成熟的加密库(如OpenSSL)而不是自己实现。

-- 展开阅读全文 --
头像
C语言如何实现类似SQL的groupby分组?
« 上一篇 04-16
deftype C语言是什么?
下一篇 » 04-16

相关文章

取消
微信二维码
支付宝二维码

目录[+]