001// SPDX-FileCopyrightText: 2018 Paul Schaub <vanitasvitae@fsfe.org> 002// 003// SPDX-License-Identifier: Apache-2.0 004 005package org.pgpainless.key.protection; 006 007import javax.annotation.Nonnull; 008import javax.annotation.Nullable; 009 010import org.bouncycastle.openpgp.PGPKeyRing; 011import org.bouncycastle.openpgp.PGPSecretKey; 012import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor; 013import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor; 014import org.pgpainless.key.protection.passphrase_provider.SecretKeyPassphraseProvider; 015import org.pgpainless.util.Passphrase; 016 017/** 018 * Provides {@link PBESecretKeyDecryptor} and {@link PBESecretKeyEncryptor} objects while getting the passphrases 019 * from a {@link SecretKeyPassphraseProvider} and using settings from an {@link KeyRingProtectionSettings}. 020 */ 021public class PasswordBasedSecretKeyRingProtector extends BaseSecretKeyRingProtector { 022 023 public PasswordBasedSecretKeyRingProtector(@Nonnull SecretKeyPassphraseProvider passphraseProvider) { 024 super(passphraseProvider); 025 } 026 027 /** 028 * Constructor. 029 * Passphrases for keys are sourced from the {@code passphraseProvider} and decryptors/encryptors are constructed 030 * following the settings given in {@code settings}. 031 * 032 * @param settings S2K settings etc. 033 * @param passphraseProvider provider which provides passphrases. 034 */ 035 public PasswordBasedSecretKeyRingProtector(@Nonnull KeyRingProtectionSettings settings, @Nonnull SecretKeyPassphraseProvider passphraseProvider) { 036 super(passphraseProvider, settings); 037 } 038 039 public static PasswordBasedSecretKeyRingProtector forKey(PGPKeyRing keyRing, Passphrase passphrase) { 040 SecretKeyPassphraseProvider passphraseProvider = new SecretKeyPassphraseProvider() { 041 @Override 042 @Nullable 043 public Passphrase getPassphraseFor(Long keyId) { 044 return hasPassphrase(keyId) ? passphrase : null; 045 } 046 047 @Override 048 public boolean hasPassphrase(Long keyId) { 049 return keyRing.getPublicKey(keyId) != null; 050 } 051 }; 052 return new PasswordBasedSecretKeyRingProtector(passphraseProvider); 053 } 054 055 public static PasswordBasedSecretKeyRingProtector forKey(PGPSecretKey key, Passphrase passphrase) { 056 return forKeyId(key.getPublicKey().getKeyID(), passphrase); 057 } 058 059 public static PasswordBasedSecretKeyRingProtector forKeyId(long singleKeyId, Passphrase passphrase) { 060 SecretKeyPassphraseProvider passphraseProvider = new SecretKeyPassphraseProvider() { 061 @Nullable 062 @Override 063 public Passphrase getPassphraseFor(Long keyId) { 064 if (keyId == singleKeyId) { 065 return passphrase; 066 } 067 return null; 068 } 069 070 @Override 071 public boolean hasPassphrase(Long keyId) { 072 return keyId == singleKeyId; 073 } 074 }; 075 return new PasswordBasedSecretKeyRingProtector(passphraseProvider); 076 } 077 078}