001// Copyright 2021 Paul Schaub. 002// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org> 003// 004// SPDX-License-Identifier: Apache-2.0 005 006package org.pgpainless.key.protection; 007 008import org.bouncycastle.openpgp.PGPException; 009import org.bouncycastle.openpgp.PGPPrivateKey; 010import org.bouncycastle.openpgp.PGPSecretKey; 011import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor; 012import org.pgpainless.exception.KeyIntegrityException; 013import org.pgpainless.exception.WrongPassphraseException; 014import org.pgpainless.key.info.KeyInfo; 015import org.pgpainless.key.util.PublicKeyParameterValidationUtil; 016import org.pgpainless.util.Passphrase; 017 018public final class UnlockSecretKey { 019 020 private UnlockSecretKey() { 021 022 } 023 024 public static PGPPrivateKey unlockSecretKey(PGPSecretKey secretKey, SecretKeyRingProtector protector) 025 throws PGPException, KeyIntegrityException { 026 027 PBESecretKeyDecryptor decryptor = null; 028 if (KeyInfo.isEncrypted(secretKey)) { 029 decryptor = protector.getDecryptor(secretKey.getKeyID()); 030 } 031 PGPPrivateKey privateKey = unlockSecretKey(secretKey, decryptor); 032 return privateKey; 033 } 034 035 public static PGPPrivateKey unlockSecretKey(PGPSecretKey secretKey, PBESecretKeyDecryptor decryptor) 036 throws PGPException { 037 PGPPrivateKey privateKey; 038 try { 039 privateKey = secretKey.extractPrivateKey(decryptor); 040 } catch (PGPException e) { 041 throw new WrongPassphraseException(secretKey.getKeyID(), e); 042 } 043 044 if (privateKey == null) { 045 int s2kType = secretKey.getS2K().getType(); 046 if (s2kType >= 100 && s2kType <= 110) { 047 throw new PGPException("Cannot decrypt secret key" + Long.toHexString(secretKey.getKeyID()) + ": " + 048 "Unsupported private S2K usage type " + s2kType); 049 } 050 051 throw new PGPException("Cannot decrypt secret key."); 052 } 053 054 PublicKeyParameterValidationUtil.verifyPublicKeyParameterIntegrity(privateKey, secretKey.getPublicKey()); 055 056 return privateKey; 057 } 058 059 public static PGPPrivateKey unlockSecretKey(PGPSecretKey secretKey, Passphrase passphrase) 060 throws PGPException, KeyIntegrityException { 061 return unlockSecretKey(secretKey, SecretKeyRingProtector.unlockSingleKeyWith(passphrase, secretKey)); 062 } 063}