如何检查字符串是否已加密?

5

我正在使用这种加密方法来加密和解密某个字符串:

package encryption;

import java.security.Key;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class AES {

     private static final String ALGO = "AES";
    private static final byte[] keyValue = 
        new byte[] { 'T', 'h', 'e', 'B', 'e', 's', 't',
'S', 'e', 'c', 'r','e', 't', 'K', 'e', 'y' };

public static String encrypt(String Data) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.ENCRYPT_MODE, key);
        byte[] encVal = c.doFinal(Data.getBytes());
        String encryptedValue = new BASE64Encoder().encode(encVal);
        return encryptedValue;
    }

    public static String decrypt(String encryptedData) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.DECRYPT_MODE, key);
        byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData);
        byte[] decValue = c.doFinal(decordedValue);
        String decryptedValue = new String(decValue);
        return decryptedValue;
    }
    private static Key generateKey() throws Exception {
        Key key = new SecretKeySpec(keyValue, ALGO);
        return key;
}

}

一切正常。

问题在于我如何知道要解密的字符串是否已加密?

我的意思是,我可以将一个长的“未加密”字符串传递给解密方法,它仍然可以工作。

有什么建议吗?

6个回答

4

通过尝试解密,您可以确定某个内容是否使用特定的密钥、算法、模式和填充方案进行加密。

如果您正在解密数据,则知道所使用的填充方案,并且在尝试解密时可以验证填充是否正确。如果无法可靠地从原始消息中清除填充,则说明存在问题!

CBC模式的一个好处是其每个块都依赖于前一个块的数据,这在几乎所有包含对称密码(如AES)的广泛使用的加密库中都得到支持。这意味着错误会传播,您更有可能无法解密实际上未被加密或以某种方式意外损坏的数据。

我认为这可能是测试传入数据是否使用特定的密钥、算法、模式和填充方案加密的最佳选择。

编辑

但是,如果您需要高度确信密钥是正确的,则需要在密文或明文末尾添加消息认证码(MAC)。

您可以形成以下消息:

CIPHERTEXT = ENCRYPT(KEY_1, PADDING, MODE, PLAINTEXT)
MESSAGE = CIPHERTEXT || HMAC(KEY_2, CIPHERTEXT)

CIPHERTEXT的定义是在特定的密钥、填充和操作模式下对明文进行加密的结果。

MESSAGE的定义是将CIPHERTEXTHMAC结果进行二进制拼接(||)得到的结果。

KEY_1是一个密码学安全的密钥,独立于另一个密码学安全的密钥KEY_2

计算HMAC校验和CIPHERTEXT的原因是不想实际进行解密以验证消息的真实性。

您需要开始一个加密会话,然后通过该加密通道交换KEY_2,这意味着您增加了密钥管理开销和代码复杂性,但您至少有1/1^256的概率看到一个不正确的消息通过HMAC检查。

一旦验证了HMAC的结果,您可以确定该消息很可能实际上是使用KEY_1加密的,假设自会话开始或消息寿命期间没有发生泄漏。


这很有帮助,但值得注意的是,默认填充方案--PKCS7/PKCS5填充--并不真正设计用于检测错误的密钥。例如,如果长度只使用一个字节的填充,则错误密钥通过填充检查的概率为1/256。对于许多应用程序来说,这可能还不够好。 - President James K. Polk
@GregS 我提出了一个替代方案,涵盖了您的关注点。我同意,试图依赖填充正确是有些奇怪的。这只是实际错误检查中的一步。在我的应用程序中,我肯定会使用更复杂的替代方案。但我假设这个用户只是在试水,并没有实施生产解决方案,因此我的第一个解释更多的是指导而不是推荐。 :) - Michael J. Gray

4

没有明确的方法可以确定;你唯一可以做的就是查看字符串并确定它是否像某种可理解的东西(粗略地说,file 返回比"data"更具体的东西)。除非你有一些特征可以用来识别“纯文本”(也许所有内容都是ASCII或$LANGUAGE的所有Unicode代码点),否则,在密文和任意二进制数据之间没有本质区别。


理论上来说你不能,但实际上你可以做一些事情,比如查看所有字符的分布。在这种情况下,因为他们期望一个base64字符串,所以应该很容易。 - placeybordeaux
非常好的解释。很少有人理解加密数据理想情况下应该与真正的随机数据相同。 - Michael J. Gray
@PeterMichealLacey-Bordeaux 但是如果有人加密了一个Base64字符串呢? - chrylis -cautiouslyoptimistic-
@chrylis 是的,我完全同意,有办法可以破解它,我只是提出了一些可能适用于某些目的的建议。如果他们正在加密均匀分布的base64字符串,那么你必须使用像检查填充或处理这些内容的某种加密方法。 - placeybordeaux

2
这个问题没有完美的答案,因为没有100%确定的方法来判断是否加密。但是它应该随机分布在所有可能的base64字符串中,这意味着它应该看起来与明文非常不同。你可以通过查看字符串中有多少空格来区分英文和base64加密的字符串。
这篇文章中有92个空格,但字符空格在base64中并不存在。如果你处理的不是明文英语,那么会更有趣。

虽然没有100%确定的方法,正如您所述,但有一个机会非常好,以至于如果您确实找到了一种愚弄它的方法,您将破解密文...这使得所有这些都无关紧要。我的答案详细说明了该解决方案。统计分析不是完美的。 - Michael J. Gray
啊,是的,我没有考虑到填充。 - placeybordeaux
如果是ECB,我可能真的想不到一个好的方法来做它,除了添加某种MAC并在独立密钥下进行验证。但那会增加很多复杂性。 - Michael J. Gray

1
当字符串足够长时,假设该字符串足够长,则可以实现。 那些人正在检测内存转储中的加密密钥。当然,没有100%的保证 - 简单的反例是,您可以对编码后的字符串进行编码,因此您的输入看起来已经像一个密钥。
通常,加密,编码或散列的字节序列看起来像随机序列。它们具有更高的熵,比特分布更均匀,无法压缩等。
最好的方法是分析比特的随机分布程度。对于BASE64,您只分析6位等。

这是一个很好的观点。你实际上可以检测到“看起来随机”的序列。但是,一个简单的加密安全的随机数生成器也可以欺骗它。它也没有验证字符串是否是在指定的密钥下加密的,这将导致解密失败,因此检测数据是否被加密变得毫无意义。不过还是要点赞。 - Michael J. Gray

0

您似乎正在使用对称加密/解密方案,双方都可以使用相同的密钥进行消息的加密和解密,该密钥仅为他们所知。

双方可以就正确性验证方法达成一致意见,例如CRC。

与必须保持秘密的密钥不同,此方法可以公开宣布。

只有秘密密钥的所有者才能生成可验证的加密字符串,在解密后可以使用此方法进行验证。

任何其他发送到解密的字符串都将简单地未通过CRC测试。

顺便说一下,身份验证方法通常是哈希算法,如SHA、HMAC等。由于其性质,CRC通常更容易受到选择明文攻击的影响,其中恶意方生成随机字符串,希望其中一些被检测为真实。


CRC不具有密码学安全性,将其附加到密文中会泄漏有关明文的信息。 - Michael J. Gray
好的,我使用CRC作为可能的身份验证方法的示例。并没有说它是安全的,并明确说明了通常用于身份验证的方法。我还在那之后添加了有关CRC的注释(尽管可能是在您的注释期间或之后)。无论如何,在这种情况下,您的负评非常不受欢迎。如果我错了,我不介意承担责任,但在这种情况下,CRC本身并不是答案的重点! - barak manos
没问题!既然你已经澄清并解释了所选密文的漏洞,而我在你更新之前就已经发表了评论,那么我会撤回我的负评。--实际上,我刚刚尝试这样做,但它说已被锁定。如果你编辑它,我可以进行更改。 - Michael J. Gray
被锁定的意思是,你在编辑时我正好给你的最新版本点了踩,所以看起来像是我对你最新的版本进行了踩。几分钟后就无法更改投票了。因此,SO认为你没有更改帖子,它不会让我取消我的踩。如果你编辑了帖子的任何部分,甚至是格式,那么我就可以这样做。我想让我的踩对没有澄清的旧版本的帖子有效。 - Michael J. Gray

-2

大多数加密文本包含“�”。


1
这并不意味着加密。通常这意味着无效的Unicode,有时可能意味着它被加密了 - 但也可能意味着其他许多事情。 - jpillora

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接