diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/algorithm/OpenPGPKeyVersion.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/algorithm/OpenPGPKeyVersion.kt index 7f919867..f053dd06 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/algorithm/OpenPGPKeyVersion.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/algorithm/OpenPGPKeyVersion.kt @@ -9,20 +9,18 @@ enum class OpenPGPKeyVersion(val numeric: Int) { // PGP 2.5 or before. V2 packets are deprecated and they MUST NOT be generated. /** - * Version 3 packets were first generated by PGP 2.6. - * Version 3 keys are deprecated. They contain three weaknesses. - * First, it is relatively easy to construct a version 3 key that has the same Key ID as - * any other key because the Key ID is simply the low 64 bits of the public modulus. - * Second, because the fingerprint of a version 3 key hashes the key material, but not - * its length, there is an increased opportunity for fingerprint collisions. - * Third, there are weaknesses in the MD5 hash algorithm that cause developers to prefer - * other algorithms. + * Version 3 packets were first generated by PGP 2.6. Version 3 keys are deprecated. They + * contain three weaknesses. First, it is relatively easy to construct a version 3 key that has + * the same Key ID as any other key because the Key ID is simply the low 64 bits of the public + * modulus. Second, because the fingerprint of a version 3 key hashes the key material, but not + * its length, there is an increased opportunity for fingerprint collisions. Third, there are + * weaknesses in the MD5 hash algorithm that cause developers to prefer other algorithms. */ @Deprecated("V3 keys are deprecated.") v3(3), /** - * Version 4 packets are used in RFC2440, RFC4880, RFC9580. - * The version 4 format is widely supported by various implementations. + * Version 4 packets are used in RFC2440, RFC4880, RFC9580. The version 4 format is widely + * supported by various implementations. * * @see [RFC2440](https://www.rfc-editor.org/rfc/rfc2440.html) * @see [RFC4880](https://www.rfc-editor.org/rfc/rfc4880.html) @@ -31,20 +29,19 @@ enum class OpenPGPKeyVersion(val numeric: Int) { v4(4), /** - * "V5"-keys are introduced in the LibrePGP document. - * These are NOT OpenPGP keys and are primarily supported by GnuPG and RNP. + * "V5"-keys are introduced in the LibrePGP document. These are NOT OpenPGP keys and are + * primarily supported by GnuPG and RNP. * * @see [LibrePGP](https://datatracker.ietf.org/doc/draft-koch-librepgp/) */ librePgp(5), /** - * Version 6 packets are introduced in RFC9580. - * The version 6 format is similar to the version 4 format except for the addition of - * a count for the key material. This count helps parsing Secret Key packets (which - * are an extension of the Public Key packet format) in the case of an unknown algorithm. - * In addition, fingerprints of version 6 keys are calculated differently from version 4 keys, - * preventing the KOpenPGP attack. + * Version 6 packets are introduced in RFC9580. The version 6 format is similar to the version 4 + * format except for the addition of a count for the key material. This count helps parsing + * Secret Key packets (which are an extension of the Public Key packet format) in the case of an + * unknown algorithm. In addition, fingerprints of version 6 keys are calculated differently + * from version 4 keys, preventing the KOpenPGP attack. * * @see [RFC9580](https://www.rfc-editor.org/rfc/rfc9580.html) */ diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/bouncycastle/extensions/OpenPGPCertificateExtensions.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/bouncycastle/extensions/OpenPGPCertificateExtensions.kt index 8cc954fa..008ed758 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/bouncycastle/extensions/OpenPGPCertificateExtensions.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/bouncycastle/extensions/OpenPGPCertificateExtensions.kt @@ -7,6 +7,13 @@ package org.pgpainless.bouncycastle.extensions import org.bouncycastle.openpgp.PGPOnePassSignature import org.bouncycastle.openpgp.api.OpenPGPCertificate import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPComponentKey +import org.pgpainless.algorithm.OpenPGPKeyVersion fun OpenPGPCertificate.getSigningKeyFor(ops: PGPOnePassSignature): OpenPGPComponentKey? = this.getKey(ops.keyIdentifier) + +/** Return the [OpenPGPKeyVersion] of the certificates primary key. */ +fun OpenPGPCertificate.getKeyVersion(): OpenPGPKeyVersion = primaryKey.getKeyVersion() + +/** Return the [OpenPGPKeyVersion] of the component key. */ +fun OpenPGPComponentKey.getKeyVersion(): OpenPGPKeyVersion = OpenPGPKeyVersion.from(this.version) diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/info/KeyRingInfo.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/info/KeyRingInfo.kt index f7d873d0..dd1e5a0c 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/info/KeyRingInfo.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/info/KeyRingInfo.kt @@ -95,7 +95,7 @@ class KeyRingInfo( } else null /** OpenPGP key version. */ - val version: Int = primaryKey.version + val version: OpenPGPKeyVersion = keys.getKeyVersion() /** * Return all [public component keys][OpenPGPComponentKey] of this key ring. The first key in diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/info/KeyRingInfoTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/info/KeyRingInfoTest.java index 0a12c04c..3d56dc1b 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/info/KeyRingInfoTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/info/KeyRingInfoTest.java @@ -37,6 +37,7 @@ import org.pgpainless.algorithm.CompressionAlgorithm; import org.pgpainless.algorithm.EncryptionPurpose; import org.pgpainless.algorithm.HashAlgorithm; import org.pgpainless.algorithm.KeyFlag; +import org.pgpainless.algorithm.OpenPGPKeyVersion; import org.pgpainless.algorithm.PublicKeyAlgorithm; import org.pgpainless.algorithm.SymmetricKeyAlgorithm; import org.pgpainless.key.OpenPgpV4Fingerprint; @@ -87,8 +88,8 @@ public class KeyRingInfoTest { assertEquals(Collections.singletonList(""), pInfo.getUserIds()); assertEquals(Collections.singletonList("emil@email.user"), sInfo.getEmailAddresses()); assertEquals(Collections.singletonList("emil@email.user"), pInfo.getEmailAddresses()); - assertEquals(4, sInfo.getVersion()); - assertEquals(4, pInfo.getVersion()); + assertEquals(OpenPGPKeyVersion.v4, sInfo.getVersion()); + assertEquals(OpenPGPKeyVersion.v4, pInfo.getVersion()); assertTrue(sInfo.isSecretKey()); assertFalse(pInfo.isSecretKey());