diff --git a/src/main/java/org/pgpainless/pgpainless/util/KeyRingSubKeyFix.java b/src/main/java/org/pgpainless/pgpainless/util/KeyRingSubKeyFix.java
new file mode 100644
index 00000000..0230ccfe
--- /dev/null
+++ b/src/main/java/org/pgpainless/pgpainless/util/KeyRingSubKeyFix.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2018 Paul Schaub.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pgpainless.pgpainless.util;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.bouncycastle.bcpg.HashAlgorithmTags;
+import org.bouncycastle.bcpg.PublicKeyPacket;
+import org.bouncycastle.bcpg.PublicSubkeyPacket;
+import org.bouncycastle.openpgp.PGPException;
+import org.bouncycastle.openpgp.PGPPrivateKey;
+import org.bouncycastle.openpgp.PGPPublicKey;
+import org.bouncycastle.openpgp.PGPSecretKey;
+import org.bouncycastle.openpgp.PGPSecretKeyRing;
+import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor;
+import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor;
+import org.bouncycastle.openpgp.operator.PGPDigestCalculator;
+import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider;
+
+public class KeyRingSubKeyFix {
+
+ private static final Logger LOGGER = Logger.getLogger(KeyRingSubKeyFix.class.getName());
+
+ /**
+ * This method makes sure, that sub keys do consist of sub key packets.
+ * Bouncycastle versions up to and including 1.60 created {@link PGPSecretKeyRing}s which sub keys consisted of
+ * normal public key packets, which would result in lost keys when converting PGPSecretKeyRings to PGPPublicKeyRings.
+ *
+ * This method throws a {@link RuntimeException} of a {@link NoSuchFieldException} or {@link IllegalAccessException}.
+ *
+ * @see Bouncycastle Java bug report #381
+ *
+ * @param secretKeys possibly faulty PGPSecretKeyRing
+ * @param decryptor decryptor in case the keys are encrypted (can be null)
+ * @param encryptor encryptor to re-encrypt the keys in case they are encrypted (can be null)
+ *
+ * @return fixed PGPSecretKeyRing
+ *
+ * @throws PGPException in case we cannot dismantle or reassemble the key.
+ */
+ public static PGPSecretKeyRing repairSubkeyPackets(PGPSecretKeyRing secretKeys,
+ PBESecretKeyDecryptor decryptor,
+ PBESecretKeyEncryptor encryptor)
+ throws PGPException {
+ List _secretKeys = new ArrayList<>();
+ Iterator secretKeyIterator = secretKeys.iterator();
+ _secretKeys.add(secretKeyIterator.next());
+
+ PGPDigestCalculator calculator = new BcPGPDigestCalculatorProvider().get(HashAlgorithmTags.SHA1);
+
+ try {
+
+ while (secretKeyIterator.hasNext()) {
+ PGPSecretKey subKey = secretKeyIterator.next();
+ PGPPublicKey pubSubKey = subKey.getPublicKey();
+
+ // check for public key packet type
+
+ Field publicPk = pubSubKey.getClass().getDeclaredField("publicPk");
+ publicPk.setAccessible(true);
+ PublicKeyPacket keyPacket = (PublicKeyPacket) publicPk.get(pubSubKey);
+
+ if (keyPacket instanceof PublicSubkeyPacket) {
+ // Sub key is already sub key
+ continue;
+ }
+
+ // Sub key is normal key -> fix
+ LOGGER.log(Level.INFO, "Subkey " + Long.toHexString(subKey.getKeyID()) + " does not have a subkey key packet. Convert it...");
+ keyPacket = new PublicSubkeyPacket(pubSubKey.getAlgorithm(), pubSubKey.getCreationTime(), keyPacket.getKey());
+ publicPk.set(pubSubKey, keyPacket);
+
+ PGPPrivateKey privateKey = subKey.extractPrivateKey(decryptor);
+
+ PGPSecretKey secretKey = new PGPSecretKey(privateKey, pubSubKey, calculator, false, encryptor);
+ _secretKeys.add(secretKey);
+ }
+
+ return new PGPSecretKeyRing(_secretKeys);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new RuntimeException("Cannot apply fix due to an error while using reflections.", e);
+ }
+ }
+}
diff --git a/src/test/java/org/pgpainless/pgpainless/KeyRingSubKeyFixTest.java b/src/test/java/org/pgpainless/pgpainless/KeyRingSubKeyFixTest.java
new file mode 100644
index 00000000..beb1688a
--- /dev/null
+++ b/src/test/java/org/pgpainless/pgpainless/KeyRingSubKeyFixTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2018 Paul Schaub.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pgpainless.pgpainless;
+
+import static junit.framework.TestCase.assertTrue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Security;
+import java.util.Arrays;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.openpgp.PGPException;
+import org.bouncycastle.openpgp.PGPPublicKey;
+import org.bouncycastle.openpgp.PGPPublicKeyRing;
+import org.bouncycastle.openpgp.PGPSecretKey;
+import org.bouncycastle.openpgp.PGPSecretKeyRing;
+import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator;
+import org.junit.Test;
+import org.pgpainless.pgpainless.key.collection.PGPKeyRing;
+import org.pgpainless.pgpainless.util.KeyRingSubKeyFix;
+
+public class KeyRingSubKeyFixTest {
+
+ static {
+ Security.addProvider(new BouncyCastleProvider());
+ }
+
+ @Test
+ public void test()
+ throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException,
+ IOException {
+ PGPKeyRing ring = PGPainless.generateKeyRing().simpleEcKeyRing("hallo@welt.de");
+ PGPSecretKeyRing secretKeys = ring.getSecretKeys();
+ PGPPublicKeyRing publicKeys = ring.getPublicKeys();
+
+ PGPSecretKeyRing fixed = KeyRingSubKeyFix.repairSubkeyPackets(secretKeys, null, null);
+ PGPPublicKeyRing fixedPub = publicKeyRing(fixed);
+
+ assertTrue(Arrays.equals(publicKeys.getEncoded(), fixedPub.getEncoded()));
+ }
+
+ private PGPPublicKeyRing publicKeyRing(PGPSecretKeyRing secretKeys) throws IOException {
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream(2048);
+ for (PGPSecretKey s : secretKeys) {
+ PGPPublicKey p = s.getPublicKey();
+ if (p != null) {
+ p.encode(buffer);
+ }
+ }
+
+ return new PGPPublicKeyRing(buffer.toByteArray(), new BcKeyFingerprintCalculator());
+ }
+}