【问题标题】:Are java.lang.Long or java.util.UUID safe shared secrets?java.lang.Long 或 java.util.UUID 是安全的共享机密吗?
【发布时间】:2013-02-03 19:25:57
【问题描述】:

为了访问我的 Web 服务应用程序中的资源,客户端应用程序需要为每个资源提供唯一的共享密钥。

问题是:SecureRandom 生成的多头对于此目的是否合理安全(例如,针对暴力攻击)?还是应该改用 UUID?

Web 服务通过 HTTPS 运行,我可以保证不会发生冲突(使用 Long 或 UUID)。唯一的问题是 Java 中 Long 的域是否足够大,可以防止通过 HTTPS 进行的详尽攻击。

【问题讨论】:

  • 64 位对我来说看起来不是很安全...当然这取决于您要保护的内容。 byte[256] 有什么问题?
  • 这是一个“一段字符串有多长”之类的问题...
  • 我同意 64 位看起来有点短。例如,如果您可以创建 32 位的目标并可以进行 32 位的尝试,您可能会遇到冲突(根据您的喜好在两者之间移动位)。 / 为什么是java.lang.Long?大概是为了避免写一个合适的类,但应该写那个类。
  • 嗯,我想“这取决于”是我一直都知道但不想听到的答案。我更改了我的模型以使用字符串 ID,如果我发现发生碰撞或泄漏,它们会呈现出可扩展的状态。目前,由 30 个字符组成的字母数字序列,有效期为两周,应该为我要保护的数据类型提供可接受的安全性。

标签: java long-integer uuid shared-secret


【解决方案1】:

简单的答案是,您永远无法保证随机生成的数字对/序列不会发生任何冲突。您所能做的就是设计一些东西,使应用程序的碰撞概率可以接受。该概率需要多低取决于应用程序的详细信息。

让我感到困惑的是,为什么冲突会成为共享机密的问题。您真的是在询问有人猜到共享秘密的概率吗?


好的,这是一道简单的数学题。以long 为例。

  • 2^64 可能有 long 的值。
  • 其中大约V 是“有效机密”。
  • 一些坏人可能会合理地尝试每秒N猜测的秘密。
  • 您可以推导出一个概率公式P 有人可以在给定的时间间隔T 内猜出您的秘密之一。

推导公式,插入变量VNT,判断P是否可以接受。

请注意,我们无法就“实际相关的机会”向您提供建议。相反,应该根据对某人成功破坏您的计划的成本/后果的分析来决定可接受的风险。

【讨论】:

  • “你真的是在询问某人猜测共享秘密的概率吗?” - 是的。冲突的概率为零,因为我有一个所有已发布秘密的列表,并且可以验证生成的秘密是否已经存在(并相应地重新生成)。我唯一担心的是,在纯 Long 域中,在我的网络服务器上通过 HTTPS 进行的详尽搜索是否有实际相关的成功机会,因为系统中任何时候都只有不到 100 个有效秘密处于活动状态。
  • 感谢您的评估——以及这个问题的真正答案,我需要自己判断这个概率是否可以接受。
【解决方案2】:

也许吧,但是为什么JCE supports this很有功能呢?

DHParameterSpec dhSkipParamSpec = new DHParameterSpec(skip1024Modulus, skip1024Base);
KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH", "BC");
aliceKpairGen.initialize(dhSkipParamSpec);
KeyPair aliceKpair = aliceKpairGen.generateKeyPair();
byte[] alicePubKeyEnc = aliceKpair.getPublic().getEncoded();

aliceKeyAgree = KeyAgreement.getInstance("DH", "BC");
aliceKeyAgree.init(aliceKpair.getPrivate());


//... obtaining Bob's Public Key
aliceKeyFac = KeyFactory.getInstance("DH", "BC");
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(bobPubKeyEnc);
bobPubKey = aliceKeyFac.generatePublic(x509KeySpec);

aliceKeyAgree.doPhase(bobPubKey, true);
SecretKey aliceAesKey = aliceKeyAgree.generateSecret("AES");

Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding", "BC");
cipher.init(Cipher.ENCRYPT_MODE, aliceAesKey);
byte[] cipherText = cipher.doFinal(plaintext.getBytes());

您的 AES 加密文本现在是密文。希望对您有所帮助...

【讨论】:

  • 人们为什么要使用它们?可能是因为它们比您刚刚发布的更短更简单。
猜你喜欢
  • 1970-01-01
  • 2016-09-10
  • 1970-01-01
  • 2013-07-08
  • 2020-12-19
  • 2013-01-08
相关资源
最近更新 更多