非对称使用公钥进行加密,使用私钥进行解密。由于应用程序必须能够解密应用程序需要知道私钥的数据,这就是常用算法的问题,因为对于 RSA 或 ECIES,公钥可以从私钥派生。因此,在使用公钥加密后派生公钥并存储更改/附加的数据并不是真正的问题。
第二件事是 - 你没有指定你的文本会有多“大” - 一些 KB、MB、GB?
几个月前,我测试了一些“后量子安全”的“新”算法,作为示例,我使用了 Bouncy Castle Crypto 提供程序提供的 McEliece Fujisaki 算法(我使用了 1.65 版,bcprov-jdk15to18-165 .jar)。
程序创建一个 50 MB 大字节数组,该数组使用公钥加密并使用私钥解密。
目前我没有找到任何公钥派生方法,所以你肯定需要知道私钥和公钥。
我没有测试更大的字节数组,因为这个参数取决于目标系统的内存(你需要双倍内存
因为完整的数据是在 ciphertextByte 中捕获的,然后在 decryptedtextByte 中再次捕获)。
2020 年 6 月 16 日编辑: 詹姆斯·K·波尔克总统编写了一种方法,可以轻松地从给定的私钥中检索公钥。源代码可在他的 GitHub-Repo (https://github.com/james-k-polk/McEliece/blob/master/McElieceRecoverPublicFromPrivate.java) 中找到,为了以后方便,请在此答案末尾显示。 因此,可以访问私有 McEliece 密钥的每个人都能够使用检索到的公钥加密数据!感谢詹姆斯总统的帮助。
以下是控制台上的输出:
McEliece Fujisaki Pqc Encryption
key generation
PrivateKey length: 4268 algorithm: McEliece-CCA2 format: PKCS#8
PublicKey length: 103429 algorithm: McEliece-CCA2 format: X.509
initialize cipher for encryption
pt length: 52428800 (50 mb)
ct length: 52429056 (50 mb)
initialize cipher for decryption
dt length: 52428800 (50 mb)
compare plaintext <-> decryptedtext: true
类 McElieceFujisakiPqcEncryptionLargeData.java
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.pqc.crypto.mceliece.*;
import org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider;
import org.bouncycastle.pqc.jcajce.provider.mceliece.BCMcElieceCCA2PrivateKey;
import org.bouncycastle.pqc.jcajce.provider.mceliece.BCMcElieceCCA2PublicKey;
import java.security.*;
import java.util.Arrays;
import java.util.Random;
public class McElieceFujisakiPqcEncryptionLargeData {
public static void main(String[] args) throws InvalidCipherTextException {
System.out.println("McEliece Fujisaki Pqc Encryption");
if (Security.getProvider("BCPQC") == null) {
Security.addProvider(new BouncyCastlePQCProvider());
// used Bouncy Castle: bcprov-jdk15to18-165.jar
}
System.out.println("key generation");
SecureRandom keyRandom = new SecureRandom();
McElieceCCA2Parameters params = new McElieceCCA2Parameters();
McElieceCCA2KeyPairGenerator mcElieceCCA2KeyGen = new McElieceCCA2KeyPairGenerator();
McElieceCCA2KeyGenerationParameters genParam = new McElieceCCA2KeyGenerationParameters(keyRandom, params);
mcElieceCCA2KeyGen.init(genParam);
AsymmetricCipherKeyPair pair = mcElieceCCA2KeyGen.generateKeyPair();
AsymmetricKeyParameter mcEliecePrivateKey = pair.getPrivate();
AsymmetricKeyParameter mcEliecePublicKey = pair.getPublic();
PrivateKey privateKey = new BCMcElieceCCA2PrivateKey((McElieceCCA2PrivateKeyParameters) pair.getPrivate()); // conversion neccessary only for key data
PublicKey publicKey = new BCMcElieceCCA2PublicKey((McElieceCCA2PublicKeyParameters) pair.getPublic()); // conversion neccessary only for key data
System.out.println("PrivateKey length: " + privateKey.getEncoded().length + " algorithm: " + privateKey.getAlgorithm() + " format: " + privateKey.getFormat());
System.out.println("PublicKey length: " + publicKey.getEncoded().length + " algorithm: " + publicKey.getAlgorithm() + " format: " + publicKey.getFormat());
// generate cipher for encryption
System.out.println("\ninitialize cipher for encryption");
ParametersWithRandom param = new ParametersWithRandom(mcEliecePublicKey, keyRandom);
McElieceFujisakiCipher mcElieceFujisakiDigestCipher = new McElieceFujisakiCipher();
mcElieceFujisakiDigestCipher.init(true, param);
// random plaintext
byte[] plaintext = new byte[52428800]; // 50 mb, 50 * 1024 * 1024
new Random().nextBytes(plaintext);
System.out.println("pt length: " + plaintext.length + " (" + (plaintext.length / (1024 * 1024)) + " mb)");
byte[] ciphertext = mcElieceFujisakiDigestCipher.messageEncrypt(plaintext);
System.out.println("ct length: " + ciphertext.length + " (" + (ciphertext.length / (1024 * 1024)) + " mb)");
System.out.println("\ninitialize cipher for decryption");
mcElieceFujisakiDigestCipher.init(false, mcEliecePrivateKey);
byte[] decryptedtext = mcElieceFujisakiDigestCipher.messageDecrypt(ciphertext);
System.out.println("dt length: " + decryptedtext.length + " (" + (decryptedtext.length / (1024 * 1024)) + " mb)");
System.out.println("\ncompare plaintext<-> decryptedtext: " + Arrays.equals(plaintext, decryptedtext));
}
}
James K. Polk 总统的公钥检索课程,可在 MIT-Licence 下获得:
package com.github.jameskpolk;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.pqc.crypto.mceliece.*;
import org.bouncycastle.pqc.jcajce.provider.mceliece.BCMcElieceCCA2PrivateKey;
import org.bouncycastle.pqc.jcajce.provider.mceliece.BCMcElieceCCA2PublicKey;
import org.bouncycastle.pqc.math.linearalgebra.*;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
public class McElieceRecoverPublicFromPrivate {
private static final SecureRandom RAND = new SecureRandom();
public static AsymmetricCipherKeyPair generateKeyPair() {
McElieceCCA2KeyPairGenerator kpg = new McElieceCCA2KeyPairGenerator();
McElieceCCA2Parameters params = new McElieceCCA2Parameters();
McElieceCCA2KeyGenerationParameters genParam = new McElieceCCA2KeyGenerationParameters(RAND, params);
kpg.init(genParam);
return kpg.generateKeyPair();
}
public static McElieceCCA2PublicKeyParameters recoverPubFromPriv(McElieceCCA2PrivateKeyParameters priv) {
GF2mField field = priv.getField();
PolynomialGF2mSmallM gp = priv.getGoppaPoly();
GF2Matrix h = GoppaCode.createCanonicalCheckMatrix(field, gp);
Permutation p = priv.getP();
GF2Matrix hp = (GF2Matrix) h.rightMultiply(p);
GF2Matrix sInv = hp.getLeftSubMatrix();
GF2Matrix s = (GF2Matrix) sInv.computeInverse();
GF2Matrix shp = (GF2Matrix)s.rightMultiply(hp);
GF2Matrix m = shp.getRightSubMatrix();
GoppaCode.MaMaPe mmp = new GoppaCode.MaMaPe(sInv, m, p);
GF2Matrix shortH = mmp.getSecondMatrix();
GF2Matrix shortG = (GF2Matrix) shortH.computeTranspose();
// generate public key
return new McElieceCCA2PublicKeyParameters(
priv.getN(), gp.getDegree(), shortG,
priv.getDigest());
}
public static void main(String[] args) throws Exception{
// generate a McEliece key pair
AsymmetricCipherKeyPair bcKeyPair = generateKeyPair();
McElieceCCA2PrivateKeyParameters bcPriv = (McElieceCCA2PrivateKeyParameters) bcKeyPair.getPrivate();
BCMcElieceCCA2PrivateKey priv = new BCMcElieceCCA2PrivateKey(bcPriv);
// get the first public key
McElieceCCA2PublicKeyParameters bcPub1 = (McElieceCCA2PublicKeyParameters) bcKeyPair.getPublic();
BCMcElieceCCA2PublicKey pub1 = new BCMcElieceCCA2PublicKey(bcPub1);
// Now generate a second public key for the private key
McElieceCCA2PublicKeyParameters bcPub2 = recoverPubFromPriv(bcPriv);
BCMcElieceCCA2PublicKey pub2 = new BCMcElieceCCA2PublicKey(bcPub2);
// print some info about sizes
System.out.printf("Size of encrypted messages in bits(bytes): %d(%d)\n",
priv.getEncoded().length, priv.getEncoded().length / 8);
System.out.printf("private key length: %d\n", bcPriv.getK());
System.out.printf("public key1 length: %d\n", pub1.getEncoded().length);
System.out.printf("public key2 length: %d\n", pub2.getEncoded().length);
// now encrypt different messages with each public key.
String message1 = "Deposits should be made to account # 3.1415929";
String message2 = "Deposits should be made to account # 2.71828";
ParametersWithRandom params1 = new ParametersWithRandom(bcPub1, RAND);
ParametersWithRandom params2 = new ParametersWithRandom(bcPub2, RAND);
McElieceFujisakiCipher mcElieceFujisakiDigestCipher1 = new McElieceFujisakiCipher();
McElieceFujisakiCipher mcElieceFujisakiDigestCipher2 = new McElieceFujisakiCipher();
mcElieceFujisakiDigestCipher1.init(true, params1);
mcElieceFujisakiDigestCipher2.init(true, params2);
byte[] ciphertext1 = mcElieceFujisakiDigestCipher1.messageEncrypt(message1.getBytes(StandardCharsets.UTF_8));
byte[] ciphertext2 = mcElieceFujisakiDigestCipher2.messageEncrypt(message2.getBytes(StandardCharsets.UTF_8));
System.out.println("ct1 length: " + ciphertext1.length + " (" + (ciphertext1.length / (1024 * 1024)) + " mb)");
System.out.println("ct2 length: " + ciphertext2.length + " (" + (ciphertext2.length / (1024 * 1024)) + " mb)");
mcElieceFujisakiDigestCipher1.init(false, bcPriv);
mcElieceFujisakiDigestCipher2.init(false, bcPriv);
byte[] decryptedtext1 = mcElieceFujisakiDigestCipher1.messageDecrypt(ciphertext1);
byte[] decryptedtext2 = mcElieceFujisakiDigestCipher2.messageDecrypt(ciphertext2);
System.out.printf("Decrypted message 1: %s\n", new String(decryptedtext1, StandardCharsets.UTF_8));
System.out.printf("Decrypted message 2: %s\n", new String(decryptedtext2, StandardCharsets.UTF_8));
}
}