【问题标题】:Poor man serial number generation scheme穷人序列号生成方案
【发布时间】:2016-02-25 11:34:28
【问题描述】:

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

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

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

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

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

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

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

另外我认为可以为下一个版本的应用程序更改序列号生成算法,或者使用多轮传递来显着降低暴力破解速度。

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

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

【问题讨论】:

    标签: c encryption rsa-key-fingerprint


    【解决方案1】:

    您可能想查看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 位,这通常不足以进行适当的加密,但在您的情况下,攻击者可能仍然更容易对程序进行逆向工程以删除您的许可证密钥检查,而不是尝试生成伪造的密钥。

    【讨论】:

    【解决方案2】:

    您正在寻找加密哈希函数。 md5 是一个很好的例子,它适合您想要的 32 个字符。

    【讨论】:

    • Hardware id => (md5 hash algorithm) => 序列号 这个方案也可以被客户端用来生成相同的序列号?
    【解决方案3】:

    我决定发布我自己的解决方案,该解决方案现在在这个论坛 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 的跳转短,无操作),但这是总是可以执行的。

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

    【讨论】:

      猜你喜欢
      • 2010-12-29
      • 1970-01-01
      • 2020-05-11
      • 2012-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-25
      • 1970-01-01
      相关资源
      最近更新 更多