【问题标题】:Elliptic Curve implementation for product keys产品密钥的椭圆曲线实现
【发布时间】:2022-01-02 16:53:08
【问题描述】:

Here我读到了关于如何使用非对称椭圆曲线加密来创建产品密钥的基本思想,这里引用:

我的问题是如何通过 128 位椭圆曲线创建产品密钥,因为如果您加密 X 长度的文本,您会得到比 X 长得多的加密?

下面是我写的测试代码,8个字符的消息加密成28个字节的数组,我哪里错了,还是根本不可能使用椭圆曲线来创建25个字符的产品密钥?

using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using System.Text;
using System.Linq;
using Org.BouncyCastle.Crypto.Engines;
using System.Diagnostics;
using Org.BouncyCastle.Crypto.Agreement;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Macs;

class Program
{
    public static void Main(string[] args)
    {
        var keyPairGenerator = new ECKeyPairGenerator("ECDH");
        var x9 = ECNamedCurveTable.GetByName("secp128r1");
        keyPairGenerator.Init(new ECKeyGenerationParameters(new ECDomainParameters(x9), new SecureRandom()));
        var keyPair = keyPairGenerator.GenerateKeyPair();

        byte[] d = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
        byte[] e = new byte[] { 8, 7, 6, 5, 4, 3, 2, 1 };
        var p = new IesWithCipherParameters(d, e, 64, 128);

        var cipher = new IesEngine(
                       new ECDHBasicAgreement(),
                       new Kdf2BytesGenerator(new Sha1Digest()),
                       new HMac(new Sha1Digest()));

        var message = Encoding.UTF8.GetBytes("12345678");

        cipher.Init(true, keyPair.Private, keyPair.Public, p);
        var encryption = cipher.ProcessBlock(message, 0, message.Length); // encryption length is 28 <==

        cipher.Init(false, keyPair.Private, keyPair.Public, p);
        var decryption = cipher.ProcessBlock(encryption, 0, encryption.Length);

        Debug.Assert(decryption.SequenceEqual(message));
    }
}

【问题讨论】:

  • 鉴于该示例使用 MD5 并指定直接 EC 加密(ElGamal?,如果不是,如何?)我会说这是一个非常糟糕的协议。 128 位 EC 也不安全。
  • @MaartenBodewes 忘了说要使用 ECIES 而不是 ECC 加密。 That has an encoding issue
  • 是的,但是 ECIES 需要额外的数据,而示例表明用户必须输入 25 个字符,而不是更多。
  • 尚不完全清楚,但似乎链接的答案实际上是提出签名而不是加密,但答案作者没有意识到这一点。作者讲的是在服务端用私钥“加密”,在客户端用公钥“解密”。
  • 您没有定义要加密的密码。因此它使用streaming mode,并且有MAC要考虑大小。

标签: c# algorithm security encryption cryptography


【解决方案1】:

“如果你加密 X 长度的文本,你会得到比 X 长得多的加密”这不是真的,但是加密是在 中进行的。

128位EC加密的基本操作是对一个128位的明文块进行加密,产生一个128位的密文块——大小完全相同。

如果您想加密较小的内容,则需要将其四舍五入到整数个块,这就是为什么您的 非常短 消息变得更长的原因。

还有很多额外的东西经常添加到消息中:

  • CBC 等加密模式在开始时需要一个随机数据块。
  • 通常会添加消息验证码 (HMAC) 以防止篡改。
  • 添加了填充以将消息扩展到整数块,这必须包括额外信息以指示原始消息大小。如果您的消息正好是一个块长,那么这个带有额外信息的填充将消耗整个额外的块。

对于您的应用程序,您不需要任何这些额外的东西。你从 MD5 得到 128 位,你应该只加密那个 128 位明文位块来生成一个 128 位密文位块。

我不确定您如何以正确的方式构建您的 bouncycastle IesEngine 实例之一。但就分组密码的常用参数而言:

  • 通常您必须指定一个模式。欧洲央行是正确的选择。它代表“电子密码本”,因为该语言很古老,意思是“只需加密块”。
  • 通常您必须指定要使用的填充类型。您应该指定 NO PADDING。
  • 通常你必须配置使用什么样的验证码。您似乎已指定 HMAC。正确的值是 NO AUTHENTICATION CODE。

如果设置正确,则可以加密 16 字节(128 位)的消息以产生 16 字节的输出。

【讨论】:

  • 您能否添加适用于您的答案并获得赏金的代码?
【解决方案2】:

与其说“加密”,不如说是使用签名。

在某些输入上使用哈希函数,客户端和服务器都可以计算而无需传输任何内容。然后服务器可以对该哈希进行签名,客户端可以验证签名。

128 位 ECC 签名在这里很有用,因为它们只有 128 位长。因此,将整个值编码为用户可以键入的文本字符串是合理的。另外,在不知道密钥的情况下,攻击者应该“不可能”(或至少在不使海洋沸腾的情况下......)生成假密钥。

但是,在互联网连接始终在线的时代,您想这样惹恼您的潜在客户吗?他们必须在您的在线订单页面中输入与产品激活屏幕完全相同的输入。使用和支持可能会相当令人沮丧。

此外,没有机制可以防止使用同一个密钥进行多次安装。因此,任何软件盗版者要么破解软件以删除您的激活页面,要么购买一个产品密钥并分发它。

恕我直言,任何简单的混淆都应该足以作为产品密钥。由于任何具有破坏它的技能的攻击者都可能无论如何都会将其删除。为了提高安全性,您应该执行一些在线检查。或者只是相信您的合法用户会做正确的事。

【讨论】:

  • 问题是关于如何执行非对称加密,对称算法是有限的,因为任何具有反汇编程序的新手破解者都可以找到您的密钥(或用于生成密钥的算法)并制作“keygen” .
  • 是的,签名是一个非对称系统。您不需要客户端“解密”任何东西,您只需要他们验证一个值是否有效。我不明白你怎么认为我在提倡对称系统。虽然我说一旦你假设攻击者可以修改你的代码,你的产品密钥的复杂性就无关紧要了。即使他们不能,如果没有执行在线测试,只需复制一个有效的密钥就足够了。
  • 您能否添加适用于您的答案并获得赏金的代码?
猜你喜欢
  • 2010-10-15
  • 1970-01-01
  • 1970-01-01
  • 2012-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-20
相关资源
最近更新 更多