001// SPDX-FileCopyrightText: 2020 Paul Schaub <vanitasvitae@fsfe.org> 002// 003// SPDX-License-Identifier: Apache-2.0 004 005package org.pgpainless.implementation; 006 007import java.io.InputStream; 008import java.security.KeyPair; 009import java.util.Date; 010 011import org.bouncycastle.crypto.AsymmetricCipherKeyPair; 012import org.bouncycastle.crypto.params.AsymmetricKeyParameter; 013import org.bouncycastle.openpgp.PGPException; 014import org.bouncycastle.openpgp.PGPKeyPair; 015import org.bouncycastle.openpgp.PGPObjectFactory; 016import org.bouncycastle.openpgp.PGPPrivateKey; 017import org.bouncycastle.openpgp.PGPPublicKey; 018import org.bouncycastle.openpgp.PGPSecretKey; 019import org.bouncycastle.openpgp.PGPSessionKey; 020import org.bouncycastle.openpgp.bc.BcPGPObjectFactory; 021import org.bouncycastle.openpgp.operator.KeyFingerPrintCalculator; 022import org.bouncycastle.openpgp.operator.PBEDataDecryptorFactory; 023import org.bouncycastle.openpgp.operator.PBEKeyEncryptionMethodGenerator; 024import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor; 025import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor; 026import org.bouncycastle.openpgp.operator.PGPContentSignerBuilder; 027import org.bouncycastle.openpgp.operator.PGPContentVerifierBuilderProvider; 028import org.bouncycastle.openpgp.operator.PGPDataEncryptorBuilder; 029import org.bouncycastle.openpgp.operator.PGPDigestCalculator; 030import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory; 031import org.bouncycastle.openpgp.operator.PublicKeyKeyEncryptionMethodGenerator; 032import org.bouncycastle.openpgp.operator.SessionKeyDataDecryptorFactory; 033import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator; 034import org.bouncycastle.openpgp.operator.bc.BcPBEDataDecryptorFactory; 035import org.bouncycastle.openpgp.operator.bc.BcPBEKeyEncryptionMethodGenerator; 036import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyDecryptorBuilder; 037import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyEncryptorBuilder; 038import org.bouncycastle.openpgp.operator.bc.BcPGPContentSignerBuilder; 039import org.bouncycastle.openpgp.operator.bc.BcPGPContentVerifierBuilderProvider; 040import org.bouncycastle.openpgp.operator.bc.BcPGPDataEncryptorBuilder; 041import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider; 042import org.bouncycastle.openpgp.operator.bc.BcPGPKeyConverter; 043import org.bouncycastle.openpgp.operator.bc.BcPGPKeyPair; 044import org.bouncycastle.openpgp.operator.bc.BcPublicKeyDataDecryptorFactory; 045import org.bouncycastle.openpgp.operator.bc.BcPublicKeyKeyEncryptionMethodGenerator; 046import org.bouncycastle.openpgp.operator.bc.BcSessionKeyDataDecryptorFactory; 047import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyPair; 048import org.pgpainless.algorithm.HashAlgorithm; 049import org.pgpainless.algorithm.PublicKeyAlgorithm; 050import org.pgpainless.algorithm.SymmetricKeyAlgorithm; 051import org.pgpainless.util.Passphrase; 052 053public class BcImplementationFactory extends ImplementationFactory { 054 055 @Override 056 public PBESecretKeyEncryptor getPBESecretKeyEncryptor(PGPSecretKey secretKey, Passphrase passphrase) 057 throws PGPException { 058 int keyEncryptionAlgorithm = secretKey.getKeyEncryptionAlgorithm(); 059 060 if (secretKey.getS2K() == null) { 061 return getPBESecretKeyEncryptor(SymmetricKeyAlgorithm.fromId(keyEncryptionAlgorithm), passphrase); 062 } 063 064 int hashAlgorithm = secretKey.getS2K().getHashAlgorithm(); 065 PGPDigestCalculator digestCalculator = getPGPDigestCalculator(hashAlgorithm); 066 long iterationCount = secretKey.getS2K().getIterationCount(); 067 068 return new BcPBESecretKeyEncryptorBuilder(keyEncryptionAlgorithm, digestCalculator, (int) iterationCount) 069 .build(passphrase.getChars()); 070 } 071 072 @Override 073 public PBESecretKeyEncryptor getPBESecretKeyEncryptor(SymmetricKeyAlgorithm symmetricKeyAlgorithm, 074 PGPDigestCalculator digestCalculator, 075 Passphrase passphrase) { 076 return new BcPBESecretKeyEncryptorBuilder(symmetricKeyAlgorithm.getAlgorithmId(), digestCalculator) 077 .build(passphrase.getChars()); 078 } 079 080 @Override 081 public PBESecretKeyDecryptor getPBESecretKeyDecryptor(Passphrase passphrase) { 082 return new BcPBESecretKeyDecryptorBuilder(getPGPDigestCalculatorProvider()) 083 .build(passphrase.getChars()); 084 } 085 086 @Override 087 public BcPGPDigestCalculatorProvider getPGPDigestCalculatorProvider() { 088 return new BcPGPDigestCalculatorProvider(); 089 } 090 091 @Override 092 public PGPContentVerifierBuilderProvider getPGPContentVerifierBuilderProvider() { 093 return new BcPGPContentVerifierBuilderProvider(); 094 } 095 096 @Override 097 public PGPContentSignerBuilder getPGPContentSignerBuilder(int keyAlgorithm, int hashAlgorithm) { 098 return new BcPGPContentSignerBuilder(keyAlgorithm, hashAlgorithm); 099 } 100 101 @Override 102 public KeyFingerPrintCalculator getKeyFingerprintCalculator() { 103 return new BcKeyFingerprintCalculator(); 104 } 105 106 @Override 107 public PBEDataDecryptorFactory getPBEDataDecryptorFactory(Passphrase passphrase) { 108 return new BcPBEDataDecryptorFactory(passphrase.getChars(), getPGPDigestCalculatorProvider()); 109 } 110 111 @Override 112 public PublicKeyDataDecryptorFactory getPublicKeyDataDecryptorFactory(PGPPrivateKey privateKey) { 113 return new BcPublicKeyDataDecryptorFactory(privateKey); 114 } 115 116 @Override 117 public PublicKeyKeyEncryptionMethodGenerator getPublicKeyKeyEncryptionMethodGenerator(PGPPublicKey key) { 118 return new BcPublicKeyKeyEncryptionMethodGenerator(key); 119 } 120 121 @Override 122 public PBEKeyEncryptionMethodGenerator getPBEKeyEncryptionMethodGenerator(Passphrase passphrase) { 123 return new BcPBEKeyEncryptionMethodGenerator(passphrase.getChars()); 124 } 125 126 @Override 127 public PGPDataEncryptorBuilder getPGPDataEncryptorBuilder(int symmetricKeyAlgorithm) { 128 return new BcPGPDataEncryptorBuilder(symmetricKeyAlgorithm); 129 } 130 131 @Override 132 public PGPKeyPair getPGPKeyPair(PublicKeyAlgorithm algorithm, KeyPair keyPair, Date creationDate) 133 throws PGPException { 134 return new BcPGPKeyPair(algorithm.getAlgorithmId(), jceToBcKeyPair(algorithm, keyPair, creationDate), creationDate); 135 } 136 137 @Override 138 public PBESecretKeyEncryptor getPBESecretKeyEncryptor(SymmetricKeyAlgorithm encryptionAlgorithm, HashAlgorithm hashAlgorithm, int s2kCount, Passphrase passphrase) throws PGPException { 139 return new BcPBESecretKeyEncryptorBuilder( 140 encryptionAlgorithm.getAlgorithmId(), 141 getPGPDigestCalculator(hashAlgorithm), 142 s2kCount) 143 .build(passphrase.getChars()); 144 } 145 146 @Override 147 public SessionKeyDataDecryptorFactory provideSessionKeyDataDecryptorFactory(PGPSessionKey sessionKey) { 148 return new BcSessionKeyDataDecryptorFactory(sessionKey); 149 } 150 151 @Override 152 public PGPObjectFactory getPGPObjectFactory(byte[] bytes) { 153 return new BcPGPObjectFactory(bytes); 154 } 155 156 @Override 157 public PGPObjectFactory getPGPObjectFactory(InputStream inputStream) { 158 return new BcPGPObjectFactory(inputStream); 159 } 160 161 private AsymmetricCipherKeyPair jceToBcKeyPair(PublicKeyAlgorithm algorithm, 162 KeyPair keyPair, 163 Date creationDate) throws PGPException { 164 BcPGPKeyConverter converter = new BcPGPKeyConverter(); 165 166 PGPKeyPair pair = new JcaPGPKeyPair(algorithm.getAlgorithmId(), keyPair, creationDate); 167 AsymmetricKeyParameter publicKey = converter.getPublicKey(pair.getPublicKey()); 168 AsymmetricKeyParameter privateKey = converter.getPrivateKey(pair.getPrivateKey()); 169 170 return new AsymmetricCipherKeyPair(publicKey, privateKey); 171 } 172}