有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么每次调用ECIES加密时都会给出不同的值?

我编写了一个函数来加密字符串,因为它是一个敏感信息。我正在运行一些测试,并且我已经确定在每次运行中生成的输出是不同的

我不确定是否与盐或类似的东西有关

每次调用时,输出是否不同是正常行为?这是一个好的做法还是一个坏的做法

import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.jce.interfaces.ECPublicKey;
import javax.crypto.Cipher;
import java.io.BufferedReader;
import java.io.FileReader;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;


public class App {

    private static String PUBLIC_PEM = "/opt/public.pem";

    static String TO_ENCODE = "not going well";

    public static void main(String[] args) throws Exception {
        Security.addProvider(new BouncyCastleProvider());
        App app = new App();

        PublicKey publicKey = app.getECPublicKeyFromPEM(PUBLIC_PEM);

        byte[] message = TO_ENCODE.getBytes();

        byte[] out1;

        Cipher c1 = Cipher.getInstance("ECIES");

        c1.init(Cipher.ENCRYPT_MODE, publicKey, new SecureRandom());

        out1 = c1.doFinal(message, 0, message.length);

        System.out.println(Base64.toBase64String(out1));
    }

    public ECPublicKey getECPublicKeyFromPEM(String publicPem) throws  Exception {
        PEMParser pemParser = getPemFile(publicPem);
        SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(pemParser.readObject());

        return (ECPublicKey) new JcaPEMKeyConverter().getPublicKey(subjectPublicKeyInfo);
    }

    private PEMParser getPemFile(String path) throws Exception {
        BufferedReader reader = new BufferedReader(new FileReader(path));
        return new PEMParser(reader);
    }
}

共 (1) 个答案

  1. # 1 楼答案

    如果每次调用函数时加密的数据都是相同的,则加密将是不安全的

    考虑:

    1. 您想发送一条消息,要么是“攻击”,要么是“不攻击”
    2. 攻击者拦截该消息
    3. 攻击者随后发现收件人没有进行攻击
    4. 攻击者拦截下一条消息
    5. 攻击者将该消息与上一条消息进行比较。如果它们完全相同,攻击者就知道消息上写着“请勿攻击”。如果它们不完全相同,攻击者就知道消息上写着“攻击”

    在任何情况下,当您使用ECIES加密某些内容时,您要做的第一件事就是创建一个随机的临时密钥。所以每次钥匙都不一样

        c1.init(Cipher.ENCRYPT_MODE, publicKey, new SecureRandom());
    

    理论上,您可以通过使用哈希函数和一些秘密信息(如私钥)从消息和收件人公钥中确定地生成“随机”密钥,从而使每次的结果相同

    更新

    攻击者不能预测或确定加密过程中使用的临时私钥,这一点至关重要。通常的方法是使用安全的随机数生成器,就像您在代码中所做的那样

    如果希望相同的输入产生相同的输出,则需要生成临时私钥,以确保相同输入的结果相同,但也确保攻击者无法预测或猜测临时私钥

    满足这两个要求的一种方法是使用接收方公钥、发送方私钥和消息的散列作为临时私钥。攻击者无法猜测或预测这一点,因为他们不知道发件人的私钥。只要密钥和消息都相同,它就会相同,因此它将确保由同一发送者发送给同一接收者的同一消息产生相同的临时私钥,从而产生相同的结果

    请注意,ECIES不要求发送方拥有私钥。您可以只使用一些保密的发送方标识符(它必须足够长才能安全,所以请将其视为私钥!)。只要发送者标识符保持不变,发送给同一接收者的同一封邮件将产生相同的加密输出