首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NTRU BouncyCastle

NTRU BouncyCastle
EN

Stack Overflow用户
提问于 2022-10-25 19:41:04
回答 1查看 49关注 0票数 -2

我正在开发一个Java应用程序,我想添加一种特殊的加密方法- NTRU。在此之前,我使用了赏金提供者提供的对称和不对称方法,但是由于缺乏网络上的任何信息,我现在无法理解赏金城堡中的后量子算法是如何工作的。请帮助我实现NTRU文本加密代码。

我尝试使用轻量级的API,但是它没有工作,我的代码拒绝做任何事情。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-10-25 21:41:29

这是NTRU的一个完整的运行示例,它不是一个通用的加密算法,而是一个密钥交换算法(KEM)。要使这一工作正常进行,您需要一个实际可用的弹跳城堡库(我用BC第1.71和1.72节进行了测试)。

它是从我的安卓应用程序中摘取来测试一些后量子算法(PQC)的完整代码在这里:https://github.com/MichaelsPlayground/PostQuantumCryptographyBc172

代码语言:javascript
复制
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.jcajce.SecretKeyWithEncapsulation;
import org.bouncycastle.jcajce.spec.KEMExtractSpec;
import org.bouncycastle.jcajce.spec.KEMGenerateSpec;
import org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider;
import org.bouncycastle.pqc.legacy.crypto.ntru.NTRUEncryptionKeyGenerationParameters;
import org.bouncycastle.pqc.legacy.crypto.ntru.NTRUEncryptionKeyPairGenerator;
import org.bouncycastle.pqc.legacy.crypto.ntru.NTRUEncryptionParameters;
import org.bouncycastle.pqc.legacy.crypto.ntru.NTRUEncryptionPrivateKeyParameters;
import org.bouncycastle.pqc.legacy.crypto.ntru.NTRUEncryptionPublicKeyParameters;
import org.bouncycastle.pqc.legacy.crypto.ntru.NTRUEngine;
import org.bouncycastle.util.Arrays;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.KeyGenerator;

public class PqcNtruKem {


    public static void main(String[] args) {
        //Security.addProvider(new BouncyCastleProvider());
        // we do need the regular Bouncy Castle file that includes the PQC provider
        // get Bouncy Castle here: https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on
        // tested with BC version 1.71
        if (Security.getProvider("BCPQC") == null) {
            Security.addProvider(new BouncyCastlePQCProvider());
        }
        System.out.println("PQC NTRU kem");

        System.out.println("\n************************************\n" +
                "* # # SERIOUS SECURITY WARNING # # *\n" +
                "* This program is a CONCEPT STUDY  *\n" +
                "* for the algorithm                *\n" +
                "* NTRU [key exchange mechanism]    *\n" +
                "* The program is using an          *\n" +
                "* parameter set that I cannot      *\n" +
                "* check for the correctness of the *\n" +
                "* output and other details         *\n" +
                "*                                  *\n" +
                "*    DO NOT USE THE PROGRAM IN     *\n" +
                "*    ANY PRODUCTION ENVIRONMENT    *\n" +
                "************************************");

        // as there are 7 parameter sets available the program runs all of them
        NTRUEncryptionKeyGenerationParameters[] ntruEncryptionKeyGenerationParameterSets = {
                NTRUEncryptionKeyGenerationParameters.EES1087EP2,
                NTRUEncryptionKeyGenerationParameters.EES1171EP1,
                NTRUEncryptionKeyGenerationParameters.EES1499EP1,
                NTRUEncryptionKeyGenerationParameters.APR2011_439,
                NTRUEncryptionKeyGenerationParameters.APR2011_439_FAST,
                NTRUEncryptionKeyGenerationParameters.APR2011_743,
                NTRUEncryptionKeyGenerationParameters.APR2011_743_FAST,
        };
        // short name of the parameters for the summary print out
        String[] ntruEncryptionKeyGenerationParameterNames = {
                "EES1087EP2",
                "EES1171EP1",
                "EES1499EP1",
                "APR2011_439",
                "APR2011_439_FAST",
                "APR2011_743",
                "APR2011_743_FAST"
        };

        // statistics
        int nrOfSpecs = ntruEncryptionKeyGenerationParameterSets.length;
        String[] parameterSpecName = new String[nrOfSpecs];
        int[] privateKeyLength = new int[nrOfSpecs];
        int[] publicKeyLength = new int[nrOfSpecs];
        int[] encryptedKeyLength = new int[nrOfSpecs];
        boolean[] encryptionKeysEquals = new boolean[nrOfSpecs];

        // data to encrypt is usually a 32 bytes long (randomly generated) AES key
        String keyToEncryptString = "1234567890ABCDEF1122334455667788";
        byte[] keyToEncrypt = keyToEncryptString.getBytes(StandardCharsets.UTF_8);

        for (int i = 0; i < nrOfSpecs; i++) {
            // generation of the NTRU key pair
            NTRUEncryptionKeyGenerationParameters ntruEncryptionKeyGenerationParameters = ntruEncryptionKeyGenerationParameterSets[i];
            String ntruParameterSpecName = ntruEncryptionKeyGenerationParameterNames[i];
            parameterSpecName[i] = ntruParameterSpecName;
            System.out.println("\nNTRU KEM with parameterset " + ntruParameterSpecName);
            AsymmetricCipherKeyPair keyPair = generateNtruKeyPair(ntruEncryptionKeyGenerationParameters);

            // get private and public key
            AsymmetricKeyParameter privateKey = keyPair.getPrivate();
            AsymmetricKeyParameter publicKey = keyPair.getPublic();

            // storing the key as byte array
            byte[] privateKeyByte = ((NTRUEncryptionPrivateKeyParameters) privateKey).getEncoded();
            byte[] publicKeyByte = ((NTRUEncryptionPublicKeyParameters) publicKey).getEncoded();
            System.out.println("\ngenerated private key length: " + privateKeyByte.length);
            System.out.println("generated public key length:  " + publicKeyByte.length);
            privateKeyLength[i] = privateKeyByte.length;
            publicKeyLength[i] = publicKeyByte.length;

            // generate the keys from a byte array
            NTRUEncryptionPrivateKeyParameters privateKeyLoad = getNtruPrivateKeyFromEncoded(privateKeyByte, ntruEncryptionKeyGenerationParameters);
            NTRUEncryptionPublicKeyParameters publicKeyLoad = getNtruPublicKeyFromEncoded(publicKeyByte, ntruEncryptionKeyGenerationParameters);

            // generate the encryption key and the encapsulated key
            System.out.println("\nEncryption side: generate the encryption key");
            byte[] encryptedKey = pqcNtruEncryptKey(publicKeyLoad, keyToEncrypt);
            System.out.println("encrypted key length: " + encryptedKey.length
                    + " key: " + bytesToHex(encryptedKey));
            encryptedKeyLength[i] = encryptedKey.length;

            System.out.println("\nDecryption side: receive the encrypted key and decrypt it to the decryption key");
            byte[] decryptedKey = pqcNtruDecryptKey(privateKeyLoad, encryptedKey);
            System.out.println("decryption key length: " + decryptedKey.length + " key: " + bytesToHex(decryptedKey));
            boolean keysAreEqual = Arrays.areEqual(keyToEncrypt, decryptedKey);
            System.out.println("decrypted key is equal to keyToEncrypt: " + keysAreEqual);
            encryptionKeysEquals[i] = keysAreEqual;
        }

        System.out.println("\nTest results");
        System.out.println("parameter spec name  priKL   pubKL encKL  keyE");
        for (int i = 0; i < nrOfSpecs; i++) {
             System.out.format("%-20s%6d%8d%6d%6b%n", parameterSpecName[i], privateKeyLength[i], publicKeyLength[i], encryptedKeyLength[i], encryptionKeysEquals[i]);
        }
        System.out.println("Legend: priKL privateKey length, pubKL publicKey length, encKL encryption key length, keyE encryption keys are equal\n");
    }

    private static AsymmetricCipherKeyPair generateNtruKeyPair(NTRUEncryptionKeyGenerationParameters ntruEncryptionKeyGenerationParameters) {
        NTRUEncryptionKeyPairGenerator ntruEncryptionKeyPairGenerator = new NTRUEncryptionKeyPairGenerator();
        ntruEncryptionKeyPairGenerator.init(ntruEncryptionKeyGenerationParameters);
        AsymmetricCipherKeyPair kp = ntruEncryptionKeyPairGenerator.generateKeyPair();
        return kp;
    }

    private static byte[] pqcNtruEncryptKey(AsymmetricKeyParameter publicKey, byte[] keyToEncrypt) {
        NTRUEngine ntru = new NTRUEngine();
        ntru.init(true, publicKey);
        try {
            return ntru.processBlock(keyToEncrypt, 0, keyToEncrypt.length);
        } catch (InvalidCipherTextException e) {
            e.printStackTrace();
            return null;
        }
    }

    private static byte[] pqcNtruDecryptKey(AsymmetricKeyParameter privateKey, byte[] encryptedKeyToDecrypt) {
        NTRUEngine ntru = new NTRUEngine();
        ntru.init(false, privateKey);
        try {
            return ntru.processBlock(encryptedKeyToDecrypt, 0, encryptedKeyToDecrypt.length);
        } catch (InvalidCipherTextException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static SecretKeyWithEncapsulation pqcGenerateNtruEncryptionKey(PublicKey publicKey) {
        KeyGenerator keyGen = null;
        try {
            keyGen = KeyGenerator.getInstance("Frodo", "BCPQC");
            keyGen.init(new KEMGenerateSpec((PublicKey) publicKey, "AES"), new SecureRandom());
            SecretKeyWithEncapsulation secEnc1 = (SecretKeyWithEncapsulation) keyGen.generateKey();
            return secEnc1;
        } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static byte[] pqcGenerateFrodoDecryptionKey(PrivateKey privateKey, byte[] encapsulatedKey) {
        KeyGenerator keyGen = null;
        try {
            keyGen = KeyGenerator.getInstance("Frodo", "BCPQC");
            keyGen.init(new KEMExtractSpec((PrivateKey) privateKey, encapsulatedKey, "AES"), new SecureRandom());
            SecretKeyWithEncapsulation secEnc2 = (SecretKeyWithEncapsulation) keyGen.generateKey();
            return secEnc2.getEncoded();
        } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) {
            e.printStackTrace();
            return null;
        }
    }

    private static NTRUEncryptionPrivateKeyParameters getNtruPrivateKeyFromEncoded(byte[] encodedKey, NTRUEncryptionKeyGenerationParameters ntruEncryptionKeyGenerationParameters) {
        NTRUEncryptionParameters ntruEncryptionParameters = ntruEncryptionKeyGenerationParameters.getEncryptionParameters();
        try {
            return new NTRUEncryptionPrivateKeyParameters(encodedKey, ntruEncryptionParameters);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    private static NTRUEncryptionPublicKeyParameters getNtruPublicKeyFromEncoded(byte[] encodedKey, NTRUEncryptionKeyGenerationParameters ntruEncryptionKeyGenerationParameters) {
        NTRUEncryptionParameters ntruEncryptionParameters = ntruEncryptionKeyGenerationParameters.getEncryptionParameters();
        return new NTRUEncryptionPublicKeyParameters(encodedKey, ntruEncryptionParameters);
    }

    private static PublicKey getFrodoPublicKeyFromEncoded(byte[] encodedKey) {
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(encodedKey);
        KeyFactory keyFactory = null;
        try {
            keyFactory = KeyFactory.getInstance("Frodo", "BCPQC");
            return keyFactory.generatePublic(x509EncodedKeySpec);
        } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidKeySpecException e) {
            e.printStackTrace();
            return null;
        }
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuffer result = new StringBuffer();
        for (byte b : bytes) result.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
        return result.toString();
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74199386

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档