导入和导出密钥

Importing and exporting keys

您好,我正在尝试为 RSAECCAES GCMChaChaPoly1305 导入和导出(到和从字符串)public/private 键.

我正在使用充气城堡 1.59 来完成大部分工作。 RSA 我可以使用 java 原生支持的 KeyFactory,所以这可能没问题。

但是,其他的好像不行。有谁知道这方面以前的工作?我正在寻找类似 wolfcrypt 的导入和导出功能的东西。

基本上我需要能够存储密钥然后重新创建它。

这是我的代码(我知道它很多,但它是我得到的)。

重要片段

    public static void packRsaKey(Key key, KeyPair keyPair) {
        key.toBuilder()
                .addPrimaryKey(ByteString.copyFrom(keyPair.getPrivate().getEncoded()))
                .addPublicKey(ByteString.copyFrom(keyPair.getPublic().getEncoded()))
                .build();
    }

    public static void packECCKey(Key key, KeyPair keyPair) {
        key.toBuilder()
                .addPrimaryKey(ByteString.copyFrom(keyPair.getPrivate().getEncoded()))
                .addPublicKey(ByteString.copyFrom(keyPair.getPublic().getEncoded()))
                .build();
    }

    public static void packAESGCMKey(Key key, SecretKey secretKey, byte[] IV) {
        key.toBuilder().setIv(ByteString.copyFrom(IV)).addPrimaryKey(ByteString.copyFrom(secretKey.getEncoded())).build();
    }

    public static void packChaChaPoly1305Key(Key key, SecretKey secretKey) {
        key.toBuilder().addPrimaryKey(ByteString.copyFrom(secretKey.getEncoded()));
    }

    public static PrivateKey unpackRsaPrivateKey(Key key) throws InvalidKeySpecException, NoSuchAlgorithmException {
        KeyFactory kf = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(key.getPublicKey(0).toByteArray());
        return kf.generatePrivate(pkSpec);
    }

    public static PublicKey unpackRsaPublicKey(Key key) throws InvalidKeySpecException, NoSuchAlgorithmException {
        KeyFactory kf = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(key.getPrimaryKey(0).toByteArray());
        return kf.generatePublic(pkSpec);
    }

    public static SecretKey unpackAESGCMKey(Key key) {
        return new SecretKeySpec(key.getPrimaryKey(0).toByteArray(), 0, key.getPrimaryKey(0).toByteArray().length, "AES");
    }

    public static SecretKey unpackChaChaPoly1305Key(Key key) {
        return new SecretKeySpec(key.getPrimaryKey(0).toByteArray(), 0, key.getPrimaryKey(0).toByteArray().length, "ChaCha20");
    }

    public static PrivateKey unpackECCPrivateKey(Key key) throws NoSuchAlgorithmException, InvalidKeySpecException {
        KeyFactory kf = KeyFactory.getInstance("EC");
        X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(key.getPublicKey(0).toByteArray());
        return kf.generatePrivate(pkSpec);
    }

    public static PublicKey unpackECCPublicKey(Key key) throws NoSuchAlgorithmException, InvalidKeySpecException {
        KeyFactory kf = KeyFactory.getInstance("EC");
        X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(key.getPrimaryKey(0).toByteArray());
        return kf.generatePublic(pkSpec);
    }

完整代码

package com.keiros.security.encryption;

import java.security.*;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import javax.crypto.*;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import com.google.protobuf.ByteString;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.jce.provider.BouncyCastleProvider;


import com.keiros.security.AsymmetricEncryptionClass.AsymmetricEncryption;
import com.keiros.security.KeyClass.Key;
import com.keiros.security.SymmetricEncryptionClass.SymmetricEncryption;

/**
 * Helper class for encrypting strings.
 */
public class EncryptionHelper {

    public static final int AES_KEY_SIZE = 32;
    public static final int GCM_IV_LENGTH = 16;
    public static final int GCM_TAG_LENGTH = 16;


    public static boolean generateKey(Key key) {

        if (key.hasSymmetricKeyType()) {
            return generateSymmetricKey(key);
        } else if (key.hasAsymmetricKeyType()) {
            return generateAsymmetricKey(key);
        }
        return false;
    }

    public static boolean generateSymmetricKey(Key key) {
        if (key.getSymmetricKeyType().getType() == SymmetricEncryption.Types.AES_GCM) {
            try {
                generateAESGCMKey(key);
                return true;
            } catch (Exception e) {
                return false;
            }
        } else if (key.getSymmetricKeyType().getType() == SymmetricEncryption.Types.CHA_CHA_20_POLY_1305) {
            try {
                packChaChaPoly1305Key(key, generateChaChaPoly1305Key());
                return true;
            } catch (Exception e) {
                return false;
            }
        }
        return false;
    }

    public static SecretKey generateChaChaPoly1305Key() throws NoSuchAlgorithmException {
        KeyGenerator keyGenerator = KeyGenerator.getInstance("ChaCha20");
        keyGenerator.init(32);
        return keyGenerator.generateKey();
    }

    public static void generateAESGCMKey(Key key) throws NoSuchAlgorithmException {
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(AES_KEY_SIZE);
        // Generate Key
        byte[] IV = new byte[GCM_IV_LENGTH];
        SecureRandom random = new SecureRandom();
        random.nextBytes(IV);

        SecretKey secretKey = keyGenerator.generateKey();
        packAESGCMKey(key, secretKey, IV);
    }

    public static boolean generateAsymmetricKey(Key key) {
        if (key.getAsymmetricKeyType().getType() == AsymmetricEncryption.Types.ECC) {
            try {
                KeyPair keyPair = generateECCKeys();
                packECCKey(key, keyPair);
            } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException | NoSuchProviderException e) {
                return false;
            }
        } else if (key.getAsymmetricKeyType().getType() == AsymmetricEncryption.Types.SSH_2_RSA) {
            try {
                KeyPair keyPair = generateRsaKeys();
                packRsaKey(key, keyPair);
                return true;
            } catch (NoSuchAlgorithmException e) {
                return false;
            }
        }
        return false;
    }

    public static KeyPair generateRsaKeys() throws NoSuchAlgorithmException {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(2048);
        return kpg.generateKeyPair();
    }

    public static KeyPair generateECCKeys() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, NoSuchProviderException {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME);
        kpg.initialize(new ECGenParameterSpec("secp256r1"));
        return kpg.generateKeyPair();
    }

    public static void packRsaKey(Key key, KeyPair keyPair) {
        key.toBuilder()
                .addPrimaryKey(ByteString.copyFrom(keyPair.getPrivate().getEncoded()))
                .addPublicKey(ByteString.copyFrom(keyPair.getPublic().getEncoded()))
                .build();
    }

    public static void packECCKey(Key key, KeyPair keyPair) {
        key.toBuilder()
                .addPrimaryKey(ByteString.copyFrom(keyPair.getPrivate().getEncoded()))
                .addPublicKey(ByteString.copyFrom(keyPair.getPublic().getEncoded()))
                .build();
    }

    public static void packAESGCMKey(Key key, SecretKey secretKey, byte[] IV) {
        key.toBuilder().setIv(ByteString.copyFrom(IV)).addPrimaryKey(ByteString.copyFrom(secretKey.getEncoded())).build();
    }

    public static void packChaChaPoly1305Key(Key key, SecretKey secretKey) {
        key.toBuilder().addPrimaryKey(ByteString.copyFrom(secretKey.getEncoded()));
    }

    public static PrivateKey unpackRsaPrivateKey(Key key) throws InvalidKeySpecException, NoSuchAlgorithmException {
        KeyFactory kf = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(key.getPublicKey(0).toByteArray());
        return kf.generatePrivate(pkSpec);
    }

    public static PublicKey unpackRsaPublicKey(Key key) throws InvalidKeySpecException, NoSuchAlgorithmException {
        KeyFactory kf = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(key.getPrimaryKey(0).toByteArray());
        return kf.generatePublic(pkSpec);
    }

    public static SecretKey unpackAESGCMKey(Key key) {
        return new SecretKeySpec(key.getPrimaryKey(0).toByteArray(), 0, key.getPrimaryKey(0).toByteArray().length, "AES");
    }

    public static SecretKey unpackChaChaPoly1305Key(Key key) {
        return new SecretKeySpec(key.getPrimaryKey(0).toByteArray(), 0, key.getPrimaryKey(0).toByteArray().length, "ChaCha20");
    }

    public static PrivateKey unpackECCPrivateKey(Key key) throws NoSuchAlgorithmException, InvalidKeySpecException {
        KeyFactory kf = KeyFactory.getInstance("EC");
        X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(key.getPublicKey(0).toByteArray());
        return kf.generatePrivate(pkSpec);
    }

    public static PublicKey unpackECCPublicKey(Key key) throws NoSuchAlgorithmException, InvalidKeySpecException {
        KeyFactory kf = KeyFactory.getInstance("EC");
        X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(key.getPrimaryKey(0).toByteArray());
        return kf.generatePublic(pkSpec);
    }

    public boolean encryptData(String in, StringBuilder out, Key key) {
        if (key.hasAsymmetricKeyType()) {
            if (key.getAsymmetricKeyType().getType() == AsymmetricEncryption.Types.SSH_2_RSA) {
                try {
                    out.append(encryptRsa(in.getBytes(), unpackRsaPublicKey(key)));
                    return true;
                } catch (Exception e) {
                    return false;
                }
            }
        } else if (key.hasSymmetricKeyType()) {
            if (key.getSymmetricKeyType().getType() == SymmetricEncryption.Types.AES_GCM) {
                try {
                    out.append(encryptAESGCM(in, key));
                    return true;
                } catch (Exception e) {
                    return false;
                }
            } else if (key.getSymmetricKeyType().getType() == SymmetricEncryption.Types.CHA_CHA_20_POLY_1305) {
                try {
                    out.append(encryptChaChaPoly1305(in, key));
                    return true;
                } catch (Exception e) {
                    return false;
                }
            }
        }
        return false;
    }

    public boolean encryptData(String in, StringBuilder out, Key firstKey, Key secondKey) {

        if (firstKey.hasAsymmetricKeyType() && firstKey.getAsymmetricKeyType().getType() == AsymmetricEncryption.Types.ECC) {
            if (secondKey.hasAsymmetricKeyType() && secondKey.getAsymmetricKeyType().getType() == AsymmetricEncryption.Types.ECC) {
                try {
                    out.append(encryptECC(in.getBytes(), (ECPrivateKey) unpackECCPrivateKey(firstKey),
                            (ECPublicKey) unpackECCPublicKey(secondKey)));
                    return true;
                } catch (Exception e) {
                    return false;
                }
            }
        }
        return false;
    }

    public static String encryptRsa(byte[] data, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return new String(cipher.doFinal(data));
    }

    // Source https://zhishenyong.com/ecc-asymmetric-encryption
    public static String encryptECC(byte[] data, ECPrivateKey keyOnePrivateKey, ECPublicKey keyTwoPublicKey)
            throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException,
            InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
        // 1. Generate the pre-master shared secret
        KeyAgreement ka = KeyAgreement.getInstance("ECDH", "BC");
        ka.init(keyOnePrivateKey);
        ka.doPhase(keyTwoPublicKey, true);
        byte[] sharedSecret = ka.generateSecret();

        // 2. (Optional) Hash the shared secret.
        //      Alternatively, you don't need to hash it.
        MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
        messageDigest.update(sharedSecret);
        byte[] digest = messageDigest.digest();

        // 3. (Optional) Split up hashed shared secret into an initialization vector and a session key
        //      Alternatively, you can just use the shared secret as the session key and not use an iv.
        int digestLength = digest.length;
        byte[] iv = Arrays.copyOfRange(digest, 0, (digestLength + 1) / 2);
        byte[] sessionKey = Arrays.copyOfRange(digest, (digestLength + 1) / 2, digestLength);

        // 4. Create a secret key from the session key and initialize a cipher with the secret key
        SecretKey secretKey = new SecretKeySpec(sessionKey, 0, sessionKey.length, "AES");
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
        IvParameterSpec ivSpec = new IvParameterSpec(iv);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);

        // 5. Encrypt whatever message you want to send
        return new String(cipher.doFinal(data));
    }

    public String encryptAESGCM(String in, Key key) throws NoSuchPaddingException, NoSuchAlgorithmException,
            InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        // Get Cipher Instance
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

        // Create GCMParameterSpec
        GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, key.getIv().toByteArray());

        // Initialize Cipher for ENCRYPT_MODE
        cipher.init(Cipher.ENCRYPT_MODE, unpackAESGCMKey(key), gcmParameterSpec);

        // Perform Encryption
        byte[] cipherText = cipher.doFinal(in.getBytes());

        return new String(cipherText);
    }

    public String encryptChaChaPoly1305(String in, Key key) throws NoSuchPaddingException, NoSuchAlgorithmException,
            BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidKeyException {
        byte[] nonceBytes = new byte[12];

        // Get Cipher Instance
        Cipher cipher = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding");

        // Create IvParamterSpec
        AlgorithmParameterSpec ivParameterSpec = new IvParameterSpec(nonceBytes);

        // Initialize Cipher for ENCRYPT_MODE
        cipher.init(Cipher.ENCRYPT_MODE, unpackChaChaPoly1305Key(key), ivParameterSpec);

        // Perform Encryption
        byte[] cipherText = cipher.doFinal(in.getBytes());

        return new String(cipherText);
    }

    public boolean decryptData(String in, StringBuilder out, Key key) {
        if (key.hasAsymmetricKeyType()) {
            if (key.getAsymmetricKeyType().getType() == AsymmetricEncryption.Types.SSH_2_RSA) {
                try {
                    out.append(decryptRsa(in, unpackRsaPrivateKey(key)));
                    return true;
                } catch (Exception e) {
                    return false;
                }
            }
        } else if (key.hasSymmetricKeyType()) {
            if (key.getSymmetricKeyType().getType() == SymmetricEncryption.Types.AES_GCM) {
                try {
                    out.append(decryptAESGCM(in, key));
                    return true;
                } catch (Exception e) {
                    return false;
                }
            } else if (key.getSymmetricKeyType().getType() == SymmetricEncryption.Types.CHA_CHA_20_POLY_1305) {
                try {
                    out.append(decryptChaChaPoly1305(in, key));
                    return true;
                } catch (Exception e) {
                    return false;
                }
            }
        }
        return false;
    }

    public boolean decryptData(String in, StringBuilder out, Key firstKey, Key secondKey) {
        if (firstKey.hasAsymmetricKeyType() && firstKey.getAsymmetricKeyType().getType() == AsymmetricEncryption.Types.ECC) {
            if (secondKey.hasAsymmetricKeyType() && secondKey.getAsymmetricKeyType().getType() == AsymmetricEncryption.Types.ECC) {
                try {
                    out.append(decryptECC(in.getBytes(), (ECPrivateKey) unpackECCPrivateKey(firstKey),
                            (ECPublicKey) unpackECCPublicKey(secondKey)));
                    return true;
                } catch (Exception e) {
                    return false;
                }
            }
        }
        return false;
    }

    public static String decryptRsa(String encrypted, PrivateKey privateKey) throws InvalidCipherTextException,
            NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException,
            IllegalBlockSizeException {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return new String(cipher.doFinal(encrypted.getBytes()));
    }

    // Source https://zhishenyong.com/ecc-asymmetric-encryption
    public static String decryptECC(byte[] data, ECPrivateKey keyOnePrivateKey, ECPublicKey keyTwoPublicKey)
            throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException,
            InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
        // 1. Generate the pre-master shared secret
        KeyAgreement ka = KeyAgreement.getInstance("ECDH", "BC");
        ka.init(keyOnePrivateKey);
        ka.doPhase(keyTwoPublicKey, true);
        byte[] sharedSecret = ka.generateSecret();

        // 2. (Optional) Hash the shared secret.
        //      Alternatively, you don't need to hash it.
        MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
        messageDigest.update(sharedSecret);
        byte[] digest = messageDigest.digest();

        // 3. (Optional) Split up hashed shared secret into an initialization vector and a session key
        //      Alternatively, you can just use the shared secret as the session key and not use an iv.
        int digestLength = digest.length;
        byte[] iv = Arrays.copyOfRange(digest, 0, (digestLength + 1) / 2);
        byte[] sessionKey = Arrays.copyOfRange(digest, (digestLength + 1) / 2, digestLength);

        // 4. Create a secret key from the session key and initialize a cipher with the secret key
        SecretKey secretKey = new SecretKeySpec(sessionKey, 0, sessionKey.length, "AES");
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
        IvParameterSpec ivSpec = new IvParameterSpec(iv);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);

        // 5. Encrypt whatever message you want to send
        return new String(cipher.doFinal(data));
    }

    public static String decryptAESGCM(String in, Key key) throws NoSuchPaddingException, NoSuchAlgorithmException,
            InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        // Get Cipher Instance
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

        // Create GCMParameterSpec
        GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, key.getIv().toByteArray());

        // Initialize Cipher for DECRYPT_MODE
        cipher.init(Cipher.DECRYPT_MODE, unpackAESGCMKey(key), gcmParameterSpec);

        // Perform Decryption
        byte[] decryptedText = cipher.doFinal(in.getBytes());

        return new String(decryptedText);
    }

    public static String decryptChaChaPoly1305(String in, Key key) throws NoSuchPaddingException,
            NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException,
            IllegalBlockSizeException {
        byte[] nonceBytes = new byte[12];

        // Get Cipher Instance
        Cipher cipher = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding");

        // Create IvParamterSpec
        AlgorithmParameterSpec ivParameterSpec = new IvParameterSpec(nonceBytes);

        // Initialize Cipher for DECRYPT_MODE
        cipher.init(Cipher.DECRYPT_MODE, unpackChaChaPoly1305Key(key), ivParameterSpec);

        // Perform Decryption
        byte[] decryptedText = cipher.doFinal(in.getBytes());

        return new String(decryptedText);
    }

    public static boolean signData(String in, StringBuilder out, Key key) {
        if (key.hasAsymmetricKeyType()) {

            if (key.getAsymmetricKeyType().getType() == AsymmetricEncryption.Types.ECC) {

            } else if (key.getAsymmetricKeyType().getType() == AsymmetricEncryption.Types.SSH_2_RSA) {
                try {
                    out.append(signRsa(in, unpackRsaPrivateKey(key)));
                } catch (Exception e) {
                    return false;
                }
            }
        }
        return false;
    }

    public static String signRsa(String in, PrivateKey privateKey)
            throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
        Signature sig = Signature.getInstance("SHA1WithRSA");
        sig.initSign(privateKey);
        sig.update(in.getBytes());
        return new String(sig.sign());
    }

    public static String signECC(String in, PrivateKey privateKey)
            throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
        Signature sig = Signature.getInstance("SHA256withECDSA");
        sig.initSign(privateKey);
        sig.update(in.getBytes());
        return new String(sig.sign());
    }


    public static boolean verifyData(String signature, String message, Key key) {
        if (key.hasAsymmetricKeyType()) {
            if (key.getAsymmetricKeyType().getType() == AsymmetricEncryption.Types.ECC) {
                try {
                    verifyECC(signature, message, unpackECCPublicKey(key));
                } catch (Exception e) {
                    return false;
                }
            } else if (key.getAsymmetricKeyType().getType() == AsymmetricEncryption.Types.SSH_2_RSA) {
                try {
                    verifyRsa(signature, message, unpackRsaPublicKey(key));
                } catch (Exception e) {
                    return false;
                }
            }
        }
        return false;
    }

    public static boolean verifyRsa(String signature, String message, PublicKey publicKey)
            throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
        Signature sig = Signature.getInstance("SHA1WithRSA");
        sig.initVerify(publicKey);
        sig.update(message.getBytes());
        return sig.verify(signature.getBytes());
    }

    public static boolean verifyECC(String signature, String message, PublicKey publicKey)
            throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
        Signature sig = Signature.getInstance("SHA256withECDSA");
        sig.initVerify(publicKey);
        sig.update(message.getBytes());
        return sig.verify(signature.getBytes());
    }
}


这是原型参考。

密钥

message Key {

  // Private key or the sole key.
  // For ChaCha-Poly1305 the first key is the ChaCha the second is the Poly.
  repeated bytes primary_key = 1;

  // Public key (if this is asymmetric). Will almost always be one (no cases with multiple rn).
  repeated bytes public_key = 2;

  // What kind of key this is.
  oneof key_type {
    AsymmetricEncryption asymmetric_key_type = 3;
    SymmetricEncryption symmetric_key_type = 4;
  }

  // The initialization vector if one is needed along with the key.
  bytes iv = 5;

  // An authentication tag if one is needed along with the key.
  bytes auth_tag = 6;

  // An authentication vector if one is needed along with the key.
  bytes auth_vector = 7;

  // Arbitrary additional data.
  bytes arbitrary_additional_data = 8;
}

非对称加密

message AsymmetricEncryption {
    // All the types of asymmetric encryption supported. 
    enum Types {
        // The primary type within Keiros. Will be used for encrypting connections.
        ECC = 0;
        // A supported type that can be used only for signing.
        ED25519 = 1;
        // Useful for dealing with the keys that are generated by AWS. 
        SSH_2_RSA = 2;
    }
    Types type = 1;


    // If there is a number of bits to go along with an encryption type. For example,
    // SSH_2_RSA can be with 1024, 2048 etc... 
    // See https://security.stackexchange.com/questions/62247/should-i-use-more-than-2048-bits-in-my-ssh-2-rsa-key. 
    int64 bits_for_encryption_method = 2;
}

对称加密

message SymmetricEncryption {
    // All the types of symmetric encryption supported. 
    enum Types {
        // The primary type within Keiros. Useful for storage and for maintaining an encrypted
        // connection. 
        AES_GCM = 0;
        // A secondary type to allow stream decrypting -- just additional felxibility.
        CHA_CHA_20_POLY_1305 = 1;
    }
    Types type = 1;


    // If there is a number of bits to go along with an encryption type. For example,
    // AES_GCM can use a "tag" of size 128, 120, 112, 104, or 96.
    // See: https://en.wikipedia.org/wiki/Galois/Counter_Mode.
    int64 bits_for_encryption_method = 2;
}

所以让我感到困惑的是,我在 C++ 中有相同的代码,但 wolfcrypt 将密钥编码为 RSADER 和 [=16= 的 X.963 格式].然后 AESGCMChaChaPoly1305 它们都是原始字节数组,而在这里它们不是。我只是想知道如果我在 java 中编码然后在 c++ 中解码是否有任何方法可以让它工作。我想一定有,因为 TLS 在 java 和 c++ 中工作。

描述 'DER' 含糊不清,但与您引用的对比相比,它可能意味着 RSA 密钥采用 PKCS1 aka RFC8017 et pred Appendix A.1 which like all ASN.1 data can be and for crypto often is encoded in DER. 'X.963' is clearly a mistake; the relevant standards for ECC crypto are X9.62 and X9.63, but the publickey format which indeed is not ASN.1/DER was defined by X9.62 and copied by X9.63, while the privatekey format was not standardized at all, but is often a raw octet string and not ASN.1/DER. (X.(number) standards are from the international treaty organization formerly called International Consultative Committee on Telephony and Telegraphy CCITT and now International Telecommunication Union Telecommunication Standardization Sector ITU-T; X9.(number) are from the USA private-sector financial-industry organization ANSI accredited standards committee (ASC) X9.) OTOH Java crypto encoding for private key is PKCS8 aka RFC5208 (unencrypted) 定义的 ASN.1 格式,其中添加了元数据。要将 Java 密钥转换为您的 'wolfcrypt' 显然想要的格式相当容易,只需提取与算法相关的元素,而相反,使用 [=61= 中的 'wolfcrypt' 密钥], 仅 Java 会非常困难,但添加 BouncyCastle 有很大帮助;关于这两个(或所有三个)的现有问题很多,我稍后会为您挖掘。

一些其他的,部分的,评论:

generateChaChaPoly1305Key, generateAESGCMKey: KeyGenerator.init(int)bits 的数量,ChaCha20 应为 256,AES 应为 128、192 或 256。 (KeyPairGenerator 也是如此,您获得了 RSA 的权利。)不应使用 AES-GCM 的密钥生成 IV;在下面查看更多内容。

unpackRsaPrivateKey、unpackRsaPublicKey、unpackECCPrivateKey、unpackECCPublicKey:'PrivateKey' 方法使用 key.getPublicKey(),'PublicKey' 方法使用 key.getPrivateKey(),这似乎是倒退的。假设您更改 PrivateKey 方法以使用私钥,如上所述,私钥的 Java 编码是 PKCS8EncodedKeySpec -- 而不是 X509EncodedKeySpec ,后者仅适用于 publickey.

unpackAESGCMKey,unpackChaChaPoly1305Key:使用整个byte[]作为key,不需要指定, 0, array.length,可以使用更简单的ctorSecretKeySpec(byte[], String algorithm).

encrypt*:您对密文执行 new String(byte[]),在 decrypt* 方法中执行 (String_var).getBytes()这不安全。 Java String 旨在保存 个字符 ,尽管加密仍然使用传统术语明文和密文,自从大约 1950 年以来,明文不再是必需的,密文实际上从来不是字符,而是任意位模式。尝试将这些位放入 Java String 然后取回它们通常会失败,尤其是在跨多个系统时(例如,在 A 上加密,在 B 上传输和解密,这是一种常见的用法)案件)。最好的办法是始终如一地处理它们 byte[];如果您必须 运行 通过无法处理任意位的方式发送它们,例如 SMS 或 Web (HTML),则需要以保留所有位的文本形式进行编码;常用的方法是十六进制(或十六进制)和 base64。

encryptAESGCM:尚不清楚key.getIV() does/uses,但如果使用同一密钥重复多次加密的 IV 值,即 CATASTROPHIC ;即使是一次重复使用也会破坏所有真实性(攻击者可以伪造任何数据),并且根据您的数据从一次到少量重复使用(例如两次或十次)会破坏机密性(攻击者可以公开所谓的秘密数据)。

encryptChaChaPoly1305:这显然对每次加密都使用相同的随机数,全零;如果您完全重复使用密钥(这似乎是您的设计重点),这将以与 AES-GCM 相同的方式破坏所有安全性。

此时我放弃了。你应该扔掉这个设计,换成懂密码学的人的设计。