title: Importing and exporting keys
body: <p>Hello I am trying to import and export (to and from string) public/private keys for <code>RSA</code>, <code>ECC</code>, <code>AES GCM</code>, and <code>ChaChaPoly1305</code>.</p>
  <p>I am using bouncy castle 1.59 to accomplish most of this. RSA I can use a <code>KeyFactory</code> natively supported by java so that is probably fine.</p>
  <p>However, the other ones do not seem possible. Does anyone know of previous work in this area? I am looking for something like wolfcrypt's import and export functionality.</p>
  <p>Essentially I need to be able to store a key and then recreate it.</p>
  <p>Here is my code ( I know its a lot but its what I got).</p>
  <p>Important snippet</p>
  <pre><code>    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(&quot;RSA&quot;);
          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(&quot;RSA&quot;);
          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, &quot;AES&quot;);
      }
  
      public static SecretKey unpackChaChaPoly1305Key(Key key) {
          return new SecretKeySpec(key.getPrimaryKey(0).toByteArray(), 0, key.getPrimaryKey(0).toByteArray().length, &quot;ChaCha20&quot;);
      }
  
      public static PrivateKey unpackECCPrivateKey(Key key) throws NoSuchAlgorithmException, InvalidKeySpecException {
          KeyFactory kf = KeyFactory.getInstance(&quot;EC&quot;);
          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(&quot;EC&quot;);
          X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(key.getPrimaryKey(0).toByteArray());
          return kf.generatePublic(pkSpec);
      }
  
  </code></pre>
  <p>Full code</p>
  <pre><code>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(&quot;ChaCha20&quot;);
          keyGenerator.init(32);
          return keyGenerator.generateKey();
      }
  
      public static void generateAESGCMKey(Key key) throws NoSuchAlgorithmException {
          KeyGenerator keyGenerator = KeyGenerator.getInstance(&quot;AES&quot;);
          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(&quot;RSA&quot;);
          kpg.initialize(2048);
          return kpg.generateKeyPair();
      }
  
      public static KeyPair generateECCKeys() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, NoSuchProviderException {
          KeyPairGenerator kpg = KeyPairGenerator.getInstance(&quot;EC&quot;, BouncyCastleProvider.PROVIDER_NAME);
          kpg.initialize(new ECGenParameterSpec(&quot;secp256r1&quot;));
          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(&quot;RSA&quot;);
          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(&quot;RSA&quot;);
          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, &quot;AES&quot;);
      }
  
      public static SecretKey unpackChaChaPoly1305Key(Key key) {
          return new SecretKeySpec(key.getPrimaryKey(0).toByteArray(), 0, key.getPrimaryKey(0).toByteArray().length, &quot;ChaCha20&quot;);
      }
  
      public static PrivateKey unpackECCPrivateKey(Key key) throws NoSuchAlgorithmException, InvalidKeySpecException {
          KeyFactory kf = KeyFactory.getInstance(&quot;EC&quot;);
          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(&quot;EC&quot;);
          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() &amp;&amp; firstKey.getAsymmetricKeyType().getType() == AsymmetricEncryption.Types.ECC) {
              if (secondKey.hasAsymmetricKeyType() &amp;&amp; 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(&quot;RSA/ECB/PKCS1Padding&quot;);
          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(&quot;ECDH&quot;, &quot;BC&quot;);
          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(&quot;SHA-256&quot;);
          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, &quot;AES&quot;);
          Cipher cipher = Cipher.getInstance(&quot;AES/GCM/NoPadding&quot;, &quot;BC&quot;);
          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(&quot;AES/GCM/NoPadding&quot;);
  
          // 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(&quot;ChaCha20-Poly1305/None/NoPadding&quot;);
  
          // 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() &amp;&amp; firstKey.getAsymmetricKeyType().getType() == AsymmetricEncryption.Types.ECC) {
              if (secondKey.hasAsymmetricKeyType() &amp;&amp; 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(&quot;RSA/ECB/PKCS1Padding&quot;);
          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(&quot;ECDH&quot;, &quot;BC&quot;);
          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(&quot;SHA-256&quot;);
          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, &quot;AES&quot;);
          Cipher cipher = Cipher.getInstance(&quot;AES/GCM/NoPadding&quot;, &quot;BC&quot;);
          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(&quot;AES/GCM/NoPadding&quot;);
  
          // 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(&quot;ChaCha20-Poly1305/None/NoPadding&quot;);
  
          // 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(&quot;SHA1WithRSA&quot;);
          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(&quot;SHA256withECDSA&quot;);
          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(&quot;SHA1WithRSA&quot;);
          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(&quot;SHA256withECDSA&quot;);
          sig.initVerify(publicKey);
          sig.update(message.getBytes());
          return sig.verify(signature.getBytes());
      }
  }
  
  
  </code></pre>
  <p>Here are the protos reference.</p>
  <p>Key</p>
  <pre><code>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;
  }
  
  </code></pre>
  <p>Asymmetric Encryption</p>
  <pre><code>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;
  }
  </code></pre>
  <p>Symmetric Encryption</p>
  <pre><code>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 &quot;tag&quot; of size 128, 120, 112, 104, or 96.
      // See: https://en.wikipedia.org/wiki/Galois/Counter_Mode.
      int64 bits_for_encryption_method = 2;
  }
  </code></pre>
  <p>So what is confusing me here is that I have the same code in C++ but wolfcrypt encodes the keys specifically as <code>DER</code> for <code>RSA</code> and <code>X.963</code> format for <code>ECC</code>. Then with <code>AESGCM</code> and <code>ChaChaPoly1305</code> they are both raw byte arrays while here they are not.  I am just wondering if I encode in java and then decode in c++ is there any way to get that working. I imagine there must be because TLS works in java and c++.</p>