mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-12-09 05:41:07 +01:00
Transparent decryption
This commit is contained in:
parent
de47a683d9
commit
a1af39a4f7
18 changed files with 461 additions and 357 deletions
|
|
@ -57,11 +57,10 @@ class GnuPGDummyKeyUtil private constructor() {
|
|||
*/
|
||||
@JvmStatic fun modify(secretKeys: PGPSecretKeyRing) = Builder(secretKeys)
|
||||
|
||||
@JvmStatic fun serialToBytes(sn: Int) = byteArrayOf(
|
||||
(sn shr 24).toByte(),
|
||||
(sn shr(16)).toByte(),
|
||||
(sn shr(8)).toByte(),
|
||||
sn.toByte())
|
||||
@JvmStatic
|
||||
fun serialToBytes(sn: Int) =
|
||||
byteArrayOf(
|
||||
(sn shr 24).toByte(), (sn shr (16)).toByte(), (sn shr (8)).toByte(), sn.toByte())
|
||||
}
|
||||
|
||||
class Builder(private val keys: PGPSecretKeyRing) {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ import org.bouncycastle.openpgp.api.OpenPGPKey.OpenPGPSecretKey
|
|||
import org.bouncycastle.openpgp.api.OpenPGPSignature.OpenPGPDocumentSignature
|
||||
import org.bouncycastle.openpgp.api.exception.MalformedOpenPGPSignatureException
|
||||
import org.bouncycastle.openpgp.operator.PBEDataDecryptorFactory
|
||||
import org.bouncycastle.openpgp.operator.PGPDataDecryptorFactory
|
||||
import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory
|
||||
import org.bouncycastle.util.io.TeeInputStream
|
||||
import org.pgpainless.PGPainless
|
||||
|
|
@ -448,16 +447,19 @@ class OpenPgpMessageInputStream(
|
|||
}
|
||||
|
||||
if (secretKey.hasExternalSecretKey()) {
|
||||
LOGGER.debug("Decryption key ${secretKey.keyIdentifier} is located on an external device, e.g. a smartcard.")
|
||||
LOGGER.debug(
|
||||
"Decryption key ${secretKey.keyIdentifier} is located on an external device, e.g. a smartcard.")
|
||||
for (hardwareTokenBackend in options.hardwareTokenBackends) {
|
||||
LOGGER.debug("Attempt decryption with ${hardwareTokenBackend.getBackendName()} backend.")
|
||||
LOGGER.debug(
|
||||
"Attempt decryption with ${hardwareTokenBackend.getBackendName()} backend.")
|
||||
if (decryptWithHardwareKey(
|
||||
hardwareTokenBackend,
|
||||
esks,
|
||||
secretKey,
|
||||
protector,
|
||||
SubkeyIdentifier(secretKey.openPGPKey.pgpSecretKeyRing, secretKey.keyIdentifier),
|
||||
pkesk)) {
|
||||
hardwareTokenBackend,
|
||||
esks,
|
||||
secretKey,
|
||||
protector,
|
||||
SubkeyIdentifier(
|
||||
secretKey.openPGPKey.pgpSecretKeyRing, secretKey.keyIdentifier),
|
||||
pkesk)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -624,16 +626,22 @@ class OpenPgpMessageInputStream(
|
|||
pkesk: PGPPublicKeyEncryptedData
|
||||
): Boolean {
|
||||
try {
|
||||
val decrypted = pkesk.getDataStream(decryptorFactory)
|
||||
val sessionKey = SessionKey(pkesk.getSessionKey(decryptorFactory))
|
||||
throwIfUnacceptable(sessionKey.algorithm)
|
||||
|
||||
val pgpSessionKey = PGPSessionKey(sessionKey.algorithm.algorithmId, sessionKey.key)
|
||||
val sessionKeyEncData = esks.esks.extractSessionKeyEncryptedData()
|
||||
val decrypted =
|
||||
sessionKeyEncData.getDataStream(
|
||||
api.implementation.sessionKeyDataDecryptorFactory(pgpSessionKey))
|
||||
|
||||
val encryptedData = esks.toEncryptedData(sessionKey, layerMetadata.depth)
|
||||
encryptedData.decryptionKey = decryptionKeyId
|
||||
encryptedData.sessionKey = sessionKey
|
||||
encryptedData.addRecipients(esks.pkesks.plus(esks.anonPkesks).map { it.keyIdentifier })
|
||||
LOGGER.debug("Successfully decrypted data with key $decryptionKeyId")
|
||||
val integrityProtected = IntegrityProtectedInputStream(decrypted, pkesk, options)
|
||||
val integrityProtected =
|
||||
IntegrityProtectedInputStream(decrypted, sessionKeyEncData, options)
|
||||
nestedInputStream =
|
||||
OpenPgpMessageInputStream(integrityProtected, options, encryptedData, api)
|
||||
return true
|
||||
|
|
@ -790,7 +798,7 @@ class OpenPgpMessageInputStream(
|
|||
}
|
||||
}
|
||||
|
||||
private class ESKsAndData(private val esks: PGPEncryptedDataList) {
|
||||
private class ESKsAndData(val esks: PGPEncryptedDataList) {
|
||||
fun toEncryptedData(sk: SessionKey, depth: Int): EncryptedData {
|
||||
return when (EncryptedDataPacketType.of(esks)!!) {
|
||||
EncryptedDataPacketType.SED ->
|
||||
|
|
|
|||
|
|
@ -313,18 +313,20 @@ class SigningOptions(private val api: PGPainless) {
|
|||
subpacketsCallback)
|
||||
}
|
||||
|
||||
fun addInlineSignature(hardwareBackedKey: OpenPGPComponentKey,
|
||||
hardwareContentSignerBuilderProviderFactory: PGPContentSignerBuilderProviderFactory,
|
||||
hashAlgorithm: HashAlgorithm,
|
||||
signatureType: DocumentSignatureType = DocumentSignatureType.BINARY_DOCUMENT,
|
||||
subpacketsCallback: Callback? = null
|
||||
) = addHardwareSigningMethod(
|
||||
hardwareBackedKey,
|
||||
hardwareContentSignerBuilderProviderFactory,
|
||||
hashAlgorithm,
|
||||
signatureType,
|
||||
false,
|
||||
subpacketsCallback)
|
||||
fun addInlineSignature(
|
||||
hardwareBackedKey: OpenPGPComponentKey,
|
||||
hardwareContentSignerBuilderProviderFactory: PGPContentSignerBuilderProviderFactory,
|
||||
hashAlgorithm: HashAlgorithm,
|
||||
signatureType: DocumentSignatureType = DocumentSignatureType.BINARY_DOCUMENT,
|
||||
subpacketsCallback: Callback? = null
|
||||
) =
|
||||
addHardwareSigningMethod(
|
||||
hardwareBackedKey,
|
||||
hardwareContentSignerBuilderProviderFactory,
|
||||
hashAlgorithm,
|
||||
signatureType,
|
||||
false,
|
||||
subpacketsCallback)
|
||||
|
||||
/**
|
||||
* Add detached signatures with all key rings from the provided secret key ring collection.
|
||||
|
|
@ -532,7 +534,14 @@ class SigningOptions(private val api: PGPainless) {
|
|||
hashAlgorithm: HashAlgorithm,
|
||||
signatureType: DocumentSignatureType = DocumentSignatureType.BINARY_DOCUMENT,
|
||||
subpacketsCallback: Callback? = null
|
||||
) = addHardwareSigningMethod(hardwareBackedKey, hardwareContentSignerBuilderProviderFactory, hashAlgorithm, signatureType, true, subpacketsCallback)
|
||||
) =
|
||||
addHardwareSigningMethod(
|
||||
hardwareBackedKey,
|
||||
hardwareContentSignerBuilderProviderFactory,
|
||||
hashAlgorithm,
|
||||
signatureType,
|
||||
true,
|
||||
subpacketsCallback)
|
||||
|
||||
private fun addHardwareSigningMethod(
|
||||
hardwareBackedKey: OpenPGPComponentKey,
|
||||
|
|
@ -540,15 +549,15 @@ class SigningOptions(private val api: PGPainless) {
|
|||
hashAlgorithm: HashAlgorithm,
|
||||
signatureType: DocumentSignatureType = DocumentSignatureType.BINARY_DOCUMENT,
|
||||
detached: Boolean,
|
||||
subpacketsCallback: Callback? = null) = apply {
|
||||
subpacketsCallback: Callback? = null
|
||||
) = apply {
|
||||
rejectWeakKeys(hardwareBackedKey)
|
||||
val pubkey = hardwareBackedKey.pgpPublicKey
|
||||
val pgpContentSignerBuilder = hardwareContentSignerBuilderProviderFactory.create(hashAlgorithm)
|
||||
.get(pubkey)
|
||||
val pgpContentSignerBuilder =
|
||||
hardwareContentSignerBuilderProviderFactory.create(hashAlgorithm).get(pubkey)
|
||||
|
||||
val generator = PGPSignatureGenerator(
|
||||
pgpContentSignerBuilder, pubkey)
|
||||
.apply {
|
||||
val generator =
|
||||
PGPSignatureGenerator(pgpContentSignerBuilder, pubkey).apply {
|
||||
init(signatureType.signatureType.code, pubkey)
|
||||
}
|
||||
|
||||
|
|
@ -582,17 +591,19 @@ class SigningOptions(private val api: PGPainless) {
|
|||
val publicKeyAlgorithm = requireFromId(signingKey.pgpPublicKey.algorithm)
|
||||
val bitStrength = signingKey.pgpPublicKey.bitStrength
|
||||
if (!api.algorithmPolicy.publicKeyAlgorithmPolicy.isAcceptable(
|
||||
publicKeyAlgorithm, bitStrength)) {
|
||||
publicKeyAlgorithm, bitStrength)) {
|
||||
throw UnacceptableSigningKeyException(
|
||||
PublicKeyAlgorithmPolicyException(
|
||||
signingKey, publicKeyAlgorithm, bitStrength))
|
||||
PublicKeyAlgorithmPolicyException(signingKey, publicKeyAlgorithm, bitStrength))
|
||||
}
|
||||
}
|
||||
|
||||
private fun prepareSignatureGenerator(generator: PGPSignatureGenerator, signingKey: PGPPublicKey, subpacketCallback: Callback?) {
|
||||
private fun prepareSignatureGenerator(
|
||||
generator: PGPSignatureGenerator,
|
||||
signingKey: PGPPublicKey,
|
||||
subpacketCallback: Callback?
|
||||
) {
|
||||
// Subpackets
|
||||
val hashedSubpackets =
|
||||
SignatureSubpackets.createHashedSubpackets(signingKey)
|
||||
val hashedSubpackets = SignatureSubpackets.createHashedSubpackets(signingKey)
|
||||
val unhashedSubpackets = SignatureSubpackets.createEmptySubpackets()
|
||||
if (subpacketCallback != null) {
|
||||
subpacketCallback.modifyHashedSubpackets(hashedSubpackets)
|
||||
|
|
|
|||
|
|
@ -210,7 +210,6 @@ $algorithm of size $bitSize is not acceptable.""",
|
|||
}
|
||||
}
|
||||
|
||||
class GeneralKeyException(message: String,
|
||||
fingerprint: OpenPgpFingerprint
|
||||
) : KeyException(message, fingerprint)
|
||||
class GeneralKeyException(message: String, fingerprint: OpenPgpFingerprint) :
|
||||
KeyException(message, fingerprint)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
// SPDX-FileCopyrightText: 2025 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.pgpainless.hardware
|
||||
|
||||
import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
// SPDX-FileCopyrightText: 2025 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.pgpainless.signature
|
||||
|
||||
import org.bouncycastle.openpgp.operator.PGPContentSignerBuilderProvider
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue