3

我想获得一些简单的方案/算法,用于根据一些唯一的硬件 id(cpu id 或以太网 MAC 地址或硬盘序列号)生成序列号。

我希望方案仅在一个方向上工作-因此客户端计算机上的应用程序可以验证序列号但不能生成序列号。(所以破解起来并不简单)。

现在很可能你们中的大多数人会推荐某种 RSA 公钥/私钥对加密,它可以足够可靠地工作——客户端没有私钥 RSA 密钥,所以他不能“生成”序列号。

但是 RSA 签名的主要问题是它太大了 - 它的签名大小是 128 或 256 字节,具体取决于 RSA 密钥大小(RSA 签名大小?

  • 我希望序列号是简单的从邮件复制粘贴到注册表单 - 所以最多 64 个字符,最好是 32 个字节。

好的,现在您可能会说这种保护不足以抵御暴力破解 - 您只需尝试所有组合以确定正确的序列号。

但我想说的是,通常你需要聘请“昂贵”的黑客或黑客团队来创建这样的暴力破解应用程序。

此外,我认为可以为下一个版本的应用程序更改序列号生成算法,或者使用多轮传递来显着减慢蛮力。

作为基础,我更喜欢使用纯 C 或 C++(不是 C#),最好是 Windows / wincrypt.h 或任何现有的纯 C 源代码(最好不要使用庞大的 3-rd 方库)。

是否可以创建 RSA 公钥/私钥对,以便签名大小为 32 个字符?

4

3 回答 3

4

您可能想查看ECDSA

ECDSA 是类似于 RSA 的公钥算法,但其密钥和签名大小比 RSA 更短,以提供相同级别的有效安全性。ECDSA 基于椭圆曲线密码学。RSA中使用的整数分解问题和ECDSA中使用的椭圆曲线都归结为离散对数问题,这被认为是难以解决的。

例如,对于与 1024 位 RSA 相同的安全级别(估计具有大约 80 位的安全性),您可以使用 160 位 ECDSA 密钥,它会生成 320 位签名。您可以将 320 位签名 base64 编码为 54 个字符的字符串,也可以将 ascii85 编码为 50 个字符的字符串。

或者,如果您想使用 base64 编码保留 32 个字符,它最多可以保存 192 位数据,您可以使用具有 96 位密钥大小的 ECDSA。96 位 ECDSA 的有效强度是 48 位,这通常不足以进行适当的加密,但在您的情况下,攻击者可能仍然更容易对程序进行逆向工程以删除您的许可证密钥检查,而不是尝试生成伪造的密钥。

于 2016-02-25T12:05:54.210 回答
1

我决定发布我自己的解决方案,该解决方案现在正在这个论坛 ECDSA 私钥/公钥对上提出,并包括我在这里询问过的双向加密算法的使用: Poor man serial number generation scheme,part 2

代码可能仍然包含一些错误,但我已尽力做到最好并测试我所能做的一切。

它还使用托管代码部分和 C# 代码来测试 C++ 代码,但根据您的实现,您可能希望完全删除托管部分。

因为这里答案的大小是有限的,所以我不得不把我的代码放在外部 url 上——所以答案的大小会足够小。

这是我的代码片段:

第三个代码不完整 - 它只是如何编码的演示代码。如果你不使用 C#,那么上层可能是别的东西。

对于 EDSCA 签名算法,我使用了https://github.com/esxgx/easy-ecc并进行了很少的修复 - 以缩短签名的大小:

/* Curve selection options. */
#define secp128r1 16

#ifndef ECC_CURVE
    #define ECC_CURVE secp128r1
#endif
  • 所以最小的签名大小。

现在,当您开始检查代码时 - 您会注意到公钥和私钥对未初始化 - 因为它们与我的产品紧密绑定。但是让我在这里发布一些演示密钥(我已经使用当前代码来初始化它们)

unsigned char publicKey[] = {
    0x03, 0x7A, 0x0E, 0xE4, 0x2C, 0xC1, 0x29, 0x1D, 0x22, 0xCF, 0x6F, 0xCE, 0x03, 0x5F, 0xBF, 0x31, 0xDD, 
};
unsigned char encryptedPrivateKey[] = {
    0x9E, 0x8C, 0x4C, 0x8F, 0x02, 0x1D, 0x7E, 0x34, 0xA0, 0xDB, 0xBC, 0x45, 0xD8, 0x1A, 0x57, 0x7A, 
};

因此,对于当前的公钥/私钥对 - 对于硬件 id 000000000000(从网卡 MAC 地址派生) - 以下序列密钥是有效的:

pc000000000000-NnE84PSfl8nFxmhpHn+gvNFwZNkwuEFKAzu/yEmDohc=

这现在包含签名部分 ("pc000000000000") 和签名本身 ("NnE84PSfl8nFxmhpHn+gvNFwZNkwuEFKAzu/yEmDohc=")。

现在最好的部分是您现在拥有我的解决方案的完整源代码,包括公钥和私钥。缺少的是我用来加密管理员私钥的密码 - 但没有它,您将无法生成序列号。我现在挑战黑客破解这个解决方案 - 为我的软件创建串行密钥生成器。相当有趣的困境——你有完整的源代码,但它对你没用。:-)

我认为破解软件还是有可能的(Asm 的跳转短,无操作),但这是总是可以执行的。

目标是通过引入简单、小巧且漂亮的串行密钥生成解决方案来让黑客的生活变得更加艰难——该解决方案可以简单地从一种产品复制粘贴到另一种产品。

于 2016-03-05T22:00:37.417 回答
1

您正在寻找加密哈希函数。一个适合您所需的 32 个字符的好例子是md5

于 2016-02-25T11:47:01.547 回答