bc-java
bc-java copied to clipboard
GNUPG 2.2.X file format support
I'm trying to load GNUPG 2.2.23 secret keys from D:\Users\xxxxx\AppData\Roaming\gnupg\private-keys-v1.d using bouncy castle bcpg-jdk15on-1.66.jar.
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.bouncycastle.gpg.SExprParser;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.operator.PBEProtectionRemoverFactory;
import org.bouncycastle.openpgp.operator.PGPDigestCalculatorProvider;
import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
import org.bouncycastle.openpgp.operator.jcajce.JcePBEProtectionRemoverFactory;
import org.bouncycastle.util.encoders.Hex;
public class LoadKey {
public static void main(String[] args) throws IOException, PGPException {
String filePath = "D:\\Users\\XXXX\\AppData\\Roaming\\gnupg\\private-keys-v1.d\\4B8379C14DED7818D546E3C4AF7F1D0DF5716BCD.key";
String pass = "siv_test";
PGPDigestCalculatorProvider calculatorProvider = new JcaPGPDigestCalculatorProviderBuilder()
.build();
PBEProtectionRemoverFactory passphraseProvider = new JcePBEProtectionRemoverFactory(
pass.toCharArray());
InputStream in = new FileInputStream(filePath);
PGPSecretKey key =
new SExprParser(calculatorProvider).parseSecretKey(
new BufferedInputStream(in), passphraseProvider,
new JcaKeyFingerprintCalculator());
System.out.println("Found key "
+ Hex.toHexString(key.getPublicKey().getFingerprint()));
}
}
But I'm getting
Exception in thread "main" java.io.IOException: unknown character encountered: K at org.bouncycastle.gpg.SXprUtils.skipOpenParenthesis(Unknown Source) at org.bouncycastle.gpg.SExprParser.parseSecretKey(Unknown Source)
**gpg (GnuPG) 2.2.23
libgcrypt 1.8.6**
It seems to secret key file format has been changed between GNUPG 2.1.X et GNUPG 2.2.X
https://lists.gnupg.org/pipermail/gnupg-devel/2017-December/033295.html
Yes, this would be useful.
- The file format is different. See keyformat.txt The "Extended Private Key Format" is the default since gpg-agent 2.2.20.
- Keys are encrypted using AES/OCB/NoPadding. The
JcePBEProtectionRemoverFactoryis hard-coded to AES/CBC/NoPadding. The AAD is the full key binary s-expression (starting with the key type) minus the protected sub-list. - AES/OCB/NoPadding encrypted secret keys have no hash in the protected material. (Not needed thanks to the OCB MAC check.)
Sample code for this is in JGit. If anyone's interested in doing this properly in BC itself, feel free to take that code as inspiration.
Bump