// SPDX-FileCopyrightText: 2023 Paul Schaub // // SPDX-License-Identifier: Apache-2.0 package org.pgpainless.encryption_signing import java.security.MessageDigest import org.bouncycastle.openpgp.PGPException import org.bouncycastle.openpgp.PGPPrivateKey import org.bouncycastle.openpgp.PGPSecretKeyRing import org.bouncycastle.openpgp.PGPSignature import org.bouncycastle.openpgp.PGPSignatureGenerator import org.pgpainless.PGPainless import org.pgpainless.algorithm.SignatureType import org.pgpainless.bouncycastle.extensions.unlock import org.pgpainless.key.protection.SecretKeyRingProtector class BcHashContextSigner { companion object { @JvmStatic fun signHashContext( hashContext: MessageDigest, signatureType: SignatureType, secretKey: PGPSecretKeyRing, protector: SecretKeyRingProtector ): PGPSignature { val info = PGPainless.inspectKeyRing(secretKey) return info.signingSubkeys .mapNotNull { info.getSecretKey(it.keyID) } .firstOrNull() ?.let { signHashContext(hashContext, signatureType, it.unlock(protector)) } ?: throw PGPException("Key does not contain suitable signing subkey.") } /** * Create an OpenPGP Signature over the given [MessageDigest] hash context. * * @param hashContext hash context * @param privateKey signing-capable key * @return signature * @throws PGPException in case of an OpenPGP error */ @JvmStatic internal fun signHashContext( hashContext: MessageDigest, signatureType: SignatureType, privateKey: PGPPrivateKey ): PGPSignature { return PGPSignatureGenerator(BcPGPHashContextContentSignerBuilder(hashContext)) .apply { init(signatureType.code, privateKey) } .generate() } } }