diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/EncryptionResult.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/EncryptionResult.kt index e86b2d90..410deba1 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/EncryptionResult.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/EncryptionResult.kt @@ -17,9 +17,11 @@ import org.pgpainless.algorithm.SymmetricKeyAlgorithm import org.pgpainless.bouncycastle.extensions.matches import org.pgpainless.key.SubkeyIdentifier import org.pgpainless.util.MultiMap +import org.pgpainless.util.SessionKey data class EncryptionResult( val encryptionMechanism: MessageEncryptionMechanism, + val sessionKey: SessionKey?, val compressionAlgorithm: CompressionAlgorithm, val detachedDocumentSignatures: OpenPGPSignatureSet, val recipients: Set, @@ -84,6 +86,7 @@ data class EncryptionResult( private var _fileName = "" private var _modificationDate = Date(0) private var _encoding = StreamEncoding.BINARY + private var _sessionKey: SessionKey? = null fun setEncryptionMechanism(mechanism: MessageEncryptionMechanism): Builder = apply { _encryptionMechanism = mechanism @@ -105,6 +108,8 @@ data class EncryptionResult( (recipients as MutableSet).add(recipient) } + fun setSessionKey(sessionKey: SessionKey) = apply { _sessionKey = sessionKey } + fun addDetachedSignature(signature: OpenPGPDocumentSignature): Builder = apply { detachedSignatures.add(signature) } @@ -114,6 +119,7 @@ data class EncryptionResult( return EncryptionResult( _encryptionMechanism, + _sessionKey, _compressionAlgorithm!!, OpenPGPSignatureSet(detachedSignatures), recipients, diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/EncryptionStream.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/EncryptionStream.kt index 9ccbfc10..12d8a115 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/EncryptionStream.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/EncryptionStream.kt @@ -20,6 +20,7 @@ import org.pgpainless.algorithm.CompressionAlgorithm import org.pgpainless.algorithm.StreamEncoding import org.pgpainless.bouncycastle.extensions.pgpDataEncryptorBuilder import org.pgpainless.util.ArmoredOutputStreamFactory +import org.pgpainless.util.SessionKey // 1 << 8 causes wrong partial body length encoding // 1 << 9 fixes this. @@ -93,6 +94,11 @@ class EncryptionStream( options.encryptionOptions.encryptionKeyIdentifiers.forEach { r -> resultBuilder.addRecipient(r) } + encryptedDataGenerator.setSessionKeyExtractionCallback { pgpSessionKey -> + if (pgpSessionKey != null) { + resultBuilder.setSessionKey(SessionKey(pgpSessionKey)) + } + } publicKeyEncryptedStream = encryptedDataGenerator.open(outermostStream, ByteArray(BUFFER_SIZE)).also { stream -> diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/OpenPGPKeyUpdater.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/OpenPGPKeyUpdater.kt index def452ac..d0c5c524 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/OpenPGPKeyUpdater.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/OpenPGPKeyUpdater.kt @@ -121,7 +121,7 @@ class OpenPGPKeyUpdater( compAlgs != newCompAlgs || aeadAlgs != newAeadAlgs) { keyEditor.addDirectKeySignature( - SignatureParameters.Callback.modifyHashedSubpackets { sigGen -> + SignatureParameters.Callback.Util.modifyHashedSubpackets { sigGen -> sigGen.apply { setKeyFlags(key.primaryKey.keyFlags?.flags ?: 0) setFeature(true, newFeatures) @@ -157,7 +157,7 @@ class OpenPGPKeyUpdater( fun replaceWeakEncryptionSubkeys( revokeWeakKeys: Boolean, keyPairGeneratorCallback: KeyPairGeneratorCallback = - KeyPairGeneratorCallback.encryptionKey() + KeyPairGeneratorCallback.Util.encryptionKey() ) { val weakEncryptionKeys = key.getEncryptionKeys(referenceTime).filterNot { @@ -179,7 +179,8 @@ class OpenPGPKeyUpdater( fun replaceWeakSigningSubkeys( revokeWeakKeys: Boolean, keyPairGenerator: PGPKeyPairGenerator = provideKeyPairGenerator(), - keyPairGeneratorCallback: KeyPairGeneratorCallback = KeyPairGeneratorCallback.signingKey() + keyPairGeneratorCallback: KeyPairGeneratorCallback = + KeyPairGeneratorCallback.Util.signingKey() ) { val weakSigningKeys = key.getSigningKeys(referenceTime).filterNot { diff --git a/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/EncryptImpl.kt b/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/EncryptImpl.kt index 6e371ff0..c8a71c24 100644 --- a/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/EncryptImpl.kt +++ b/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/EncryptImpl.kt @@ -26,6 +26,7 @@ import org.pgpainless.util.Passphrase import sop.EncryptionResult import sop.Profile import sop.ReadyWithResult +import sop.SessionKey import sop.enums.EncryptAs import sop.exception.SOPGPException import sop.operation.Encrypt @@ -98,8 +99,10 @@ class EncryptImpl(private val api: PGPainless) : Encrypt { api.generateMessage().onOutputStream(outputStream).withOptions(options) Streams.pipeAll(plaintext, encryptionStream) encryptionStream.close() - // TODO: Extract and emit session key once BC supports that - return EncryptionResult(null) + return EncryptionResult( + encryptionStream.result.sessionKey?.let { + SessionKey(it.algorithm.algorithmId.toByte(), it.key) + }) } } } catch (e: PGPException) { diff --git a/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/SOPImpl.kt b/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/SOPImpl.kt index d2d3bf35..9a1b1ad5 100644 --- a/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/SOPImpl.kt +++ b/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/SOPImpl.kt @@ -68,7 +68,7 @@ class SOPImpl( override fun updateKey(): UpdateKey = UpdateKeyImpl(api) - override fun validateUserId(): ValidateUserId = ValidateUserIdImpl(api) + override fun validateUserId(): ValidateUserId = sopv.validateUserId()!! override fun version(): Version = sopv.version()!! } diff --git a/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/SOPVImpl.kt b/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/SOPVImpl.kt index d1f729cf..e5a18c97 100644 --- a/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/SOPVImpl.kt +++ b/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/SOPVImpl.kt @@ -9,6 +9,7 @@ import org.pgpainless.util.ArmoredOutputStreamFactory import sop.SOPV import sop.operation.DetachedVerify import sop.operation.InlineVerify +import sop.operation.ValidateUserId import sop.operation.Version class SOPVImpl(private val api: PGPainless) : SOPV { @@ -22,4 +23,6 @@ class SOPVImpl(private val api: PGPainless) : SOPV { override fun inlineVerify(): InlineVerify = InlineVerifyImpl(api) override fun version(): Version = VersionImpl(api) + + override fun validateUserId(): ValidateUserId = ValidateUserIdImpl(api) } diff --git a/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/VersionImpl.kt b/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/VersionImpl.kt index 5aa405ad..1296fed8 100644 --- a/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/VersionImpl.kt +++ b/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/VersionImpl.kt @@ -16,8 +16,8 @@ import sop.operation.Version class VersionImpl(private val api: PGPainless) : Version { companion object { - const val SOP_VERSION = 11 - const val SOPV_VERSION = "1.0" + const val SOP_VERSION = 14 + const val SOPV_VERSION = "1.2" } override fun getBackendVersion(): String = "PGPainless ${getVersion()}" diff --git a/version.gradle b/version.gradle index bf30b328..7a7a0a4b 100644 --- a/version.gradle +++ b/version.gradle @@ -7,12 +7,12 @@ allprojects { shortVersion = '2.0.0' isSnapshot = true javaSourceCompatibility = 11 - bouncyCastleVersion = '1.80-SNAPSHOT' + bouncyCastleVersion = '1.81' bouncyPgVersion = bouncyCastleVersion junitVersion = '5.8.2' logbackVersion = '1.5.13' mockitoVersion = '4.5.1' slf4jVersion = '1.7.36' - sopJavaVersion = '11.0.0-SNAPSHOT' + sopJavaVersion = '14.0.0-SNAPSHOT' } }