【问题标题】:RSA encrypt share data between 2 clientRSA 加密 2 个客户端之间的共享数据
【发布时间】:2015-10-25 11:08:44
【问题描述】:

是否可以使用 2 个 RSA 密钥(来自对 A 的私钥和来自对 B 的公钥)加密文件,以便用户 B 可以使用他的私钥和 A 的公钥打开文件?

我在 Java 中构建了代码,但我仍然尝试手动加密它,所以我知道我的程序是否工作,但是当我第二次尝试加密我的数据时,我的数据被破坏并且根本没有加密。

这是我的代码:

public static void main(String[] args) throws Exception {
    generateKeys();        
    RSA.rsaEncrypt("AES.key","RSA(AES).key");
    RSA.rsaDecrypt("RSA(AES).key","AES(RSA).key");
}

public static void generateKeys() throws Exception {
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
    kpg.initialize(2048);
    KeyPair kp = kpg.genKeyPair();
    PublicKey publicKey = kp.getPublic();
    PrivateKey privateKey = kp.getPrivate();

    System.out.println("keys created");

    KeyFactory fact = KeyFactory.getInstance("RSA");
    RSAPublicKeySpec pub = fact.getKeySpec(publicKey,
            RSAPublicKeySpec.class);
    RSAPrivateKeySpec priv = fact.getKeySpec(privateKey,
            RSAPrivateKeySpec.class);

    saveToFile("publicA.key", pub.getModulus(), pub.getPublicExponent());
    saveToFile("privateA.key", priv.getModulus(), priv.getPrivateExponent());

    System.out.println("keys saved");
}

public static void saveToFile(String fileName, BigInteger mod,
        BigInteger exp) throws IOException {
    ObjectOutputStream fileOut = new ObjectOutputStream(
            new BufferedOutputStream(new FileOutputStream(fileName)));
    try {
        fileOut.writeObject(mod);
        fileOut.writeObject(exp);
    } catch (Exception e) {
        throw new IOException("Unexpected error");
    } finally {
        fileOut.close();
        System.out.println("Closed writing file.");
    }
}

// Return the saved key
static Key readKeyFromFile(String keyFileName) throws IOException {
    InputStream in = new FileInputStream(keyFileName);
    ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(
            in));
    try {
        BigInteger m = (BigInteger) oin.readObject();
        BigInteger e = (BigInteger) oin.readObject();
        KeyFactory fact = KeyFactory.getInstance("RSA");
        if (keyFileName.startsWith("publicB")) {
            return fact.generatePublic(new RSAPublicKeySpec(m, e));
        } else {
            return fact.generatePrivate(new RSAPrivateKeySpec(m, e));
        }
    } catch (Exception e) {
        throw new RuntimeException("Spurious serialisation error", e);
    } finally {
        oin.close();
        System.out.println("Closed reading file.");
    }
}

// Use this PublicKey object to initialize a Cipher and encrypt some data
public static void rsaEncrypt(String file_loc, String file_des)
        throws Exception {
    byte[] data = new byte[32];
    int i;

    System.out.println("start encyption");

    Key pubKey = readKeyFromFile("publicB.key");
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, pubKey);

    FileInputStream fileIn = new FileInputStream(file_loc);
    FileOutputStream fileOut = new FileOutputStream(file_des);
    CipherOutputStream cipherOut = new CipherOutputStream(fileOut, cipher);

    // Read in the data from the file and encrypt it
    while ((i = fileIn.read(data)) != -1) {
        cipherOut.write(data, 0, i);
    }

    // Close the encrypted file
    cipherOut.close();
    fileIn.close();

    System.out.println("encrypted file created");
}

// Use this PublicKey object to initialize a Cipher and decrypt some data
public static void rsaDecrypt(String file_loc, String file_des)
        throws Exception {
    byte[] data = new byte[32];
    int i;

    System.out.println("start decyption");

    Key priKey = readKeyFromFile("privateB.key");
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.DECRYPT_MODE, priKey);

    FileInputStream fileIn = new FileInputStream(file_loc);
    CipherInputStream cipherIn = new CipherInputStream(fileIn, cipher);
    FileOutputStream fileOut = new FileOutputStream(file_des);

    // Write data to new file
    while ((i = cipherIn.read()) != -1) {
        fileOut.write(i);
    }

    // Close the file
    fileIn.close();
    cipherIn.close();
    fileOut.close();

    System.out.println("decrypted file created");
}

【问题讨论】:

  • 是的,这是可能的。使用私钥“加密”称为签名,您应该知道操作顺序的含义:Should we sign-then-encrypt, or encrypt-then-sign?
  • 我添加了我的代码@ArtjomB。我是如何解决这个问题的:(我是加密领域的新手,而且我还在学习 Java 编程。谢谢
  • @ArtjomB。使用私钥加密和签名不是同一个操作 - 签名会加密消息的哈希值,而加密会加密用于加密消息其余部分的会话密钥。

标签: java encryption cryptography rsa


【解决方案1】:

如果你想确保信息真的来自A,你应该用A密钥对签名,而不是加密两次。简而言之:

数据 -> 用 B 公钥加密 -> 加密数据 -> 用 A 私钥签名

然后将其发送给 B,B 将使用 A 公钥验证 A 签名,然后使用自己的私钥打开加密数据。

使用此方法,您将拥有: - 隐私:用B公钥加密,只有B可以打开。 - 不可否认性:使用 A 私钥签名,只有 A 可以做到。 - 数据完整性:当签名并使用良好的哈希函数时,您可以检查接收到的数据是否有更改。

干杯。

【讨论】:

  • 伙计们,我想问你,我在加密时使用的私钥和我用于签名的私钥有什么不同?我应该为我的加密签名使用相同的密钥,或者我只是创建用于签名的公钥和私钥以及用于加密的公钥和私钥?请帮助我仍然对此感到困惑......
  • 您应该为 A 和 B 创建公共和私有密钥。您将根据需要使用公共和私有密钥进行加密。查看这篇文章,了解非对称加密的工作原理。
  • 一个用于加密/解密的公共/私有对。您希望永远保留该私钥,否则您将永远无法再次解密存档的加密数据。您可以向您的公司提供一份副本,以便他们在您离开后解密数据。您用于签名的另一个公共/私有对。不要把它交给公司——它代表你的签名。随时销毁私钥。只要公钥存在,您的签名仍然有效。
猜你喜欢
  • 2013-07-20
  • 1970-01-01
  • 1970-01-01
  • 2021-12-31
  • 2020-05-16
  • 1970-01-01
  • 2020-07-04
  • 1970-01-01
  • 2011-08-26
相关资源
最近更新 更多