RSA加密2个客户端之间的共享数据

时间:2015-10-25 11:08:45

标签: java encryption cryptography rsa

是否可以使用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");
}

1 个答案:

答案 0 :(得分:1)

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

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

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

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

干杯。