001/* 002 * Copyright 2018 Paul Schaub. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.pgpainless.key.protection; 017 018import javax.annotation.Nonnull; 019import javax.annotation.Nullable; 020 021import org.bouncycastle.openpgp.PGPException; 022import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor; 023import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor; 024import org.bouncycastle.openpgp.operator.PGPDigestCalculatorProvider; 025import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyDecryptorBuilder; 026import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyEncryptorBuilder; 027import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider; 028import org.pgpainless.util.Passphrase; 029 030/** 031 * Provides {@link PBESecretKeyDecryptor} and {@link PBESecretKeyEncryptor} objects while getting the passphrases 032 * from a {@link SecretKeyPassphraseProvider} and using settings from an {@link KeyRingProtectionSettings}. 033 */ 034public class PasswordBasedSecretKeyRingProtector implements SecretKeyRingProtector { 035 036 private static final PGPDigestCalculatorProvider calculatorProvider = new BcPGPDigestCalculatorProvider(); 037 038 protected final KeyRingProtectionSettings protectionSettings; 039 protected final SecretKeyPassphraseProvider passphraseProvider; 040 041 /** 042 * Constructor. 043 * Passphrases for keys are sourced from the {@code passphraseProvider} and decryptors/encryptors are constructed 044 * following the settings given in {@code settings}. 045 * 046 * @param settings S2K settings etc. 047 * @param passphraseProvider provider which provides passphrases. 048 */ 049 public PasswordBasedSecretKeyRingProtector(@Nonnull KeyRingProtectionSettings settings, @Nonnull SecretKeyPassphraseProvider passphraseProvider) { 050 this.protectionSettings = settings; 051 this.passphraseProvider = passphraseProvider; 052 } 053 054 @Override 055 @Nullable 056 public PBESecretKeyDecryptor getDecryptor(Long keyId) { 057 Passphrase passphrase = passphraseProvider.getPassphraseFor(keyId); 058 return new BcPBESecretKeyDecryptorBuilder(calculatorProvider) 059 .build(passphrase != null ? passphrase.getChars() : null); 060 } 061 062 @Override 063 @Nullable 064 public PBESecretKeyEncryptor getEncryptor(Long keyId) throws PGPException { 065 Passphrase passphrase = passphraseProvider.getPassphraseFor(keyId); 066 return new BcPBESecretKeyEncryptorBuilder( 067 protectionSettings.getEncryptionAlgorithm().getAlgorithmId(), 068 calculatorProvider.get(protectionSettings.getHashAlgorithm().getAlgorithmId()), 069 protectionSettings.getS2kCount()) 070 .build(passphrase != null ? passphrase.getChars() : null); 071 } 072}