mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-11-14 16:32:06 +01:00
Introduce more extension methods
This commit is contained in:
parent
c9971ebc9f
commit
543862d797
9 changed files with 168 additions and 71 deletions
23
pgpainless-core/src/main/kotlin/openpgp/DateExtensions.kt
Normal file
23
pgpainless-core/src/main/kotlin/openpgp/DateExtensions.kt
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package openpgp
|
||||||
|
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new date which represents this date plus the given amount of seconds added.
|
||||||
|
*
|
||||||
|
* Since '0' is a special date value in the OpenPGP specification
|
||||||
|
* (e.g. '0' means no expiration for expiration dates), this method will return 'null' if seconds is 0.
|
||||||
|
*
|
||||||
|
* @param date date
|
||||||
|
* @param seconds number of seconds to be added
|
||||||
|
* @return date plus seconds or null if seconds is '0'
|
||||||
|
*/
|
||||||
|
fun Date.plusSeconds(seconds: Long): Date? {
|
||||||
|
require(Long.MAX_VALUE - time > seconds) { "Adding $seconds seconds to this date would cause time to overflow." }
|
||||||
|
return if (seconds == 0L) null
|
||||||
|
else Date(this.time + 1000 * seconds)
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ import org.bouncycastle.openpgp.PGPKeyRing
|
||||||
import org.bouncycastle.openpgp.PGPOnePassSignature
|
import org.bouncycastle.openpgp.PGPOnePassSignature
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey
|
import org.bouncycastle.openpgp.PGPPublicKey
|
||||||
import org.bouncycastle.openpgp.PGPSignature
|
import org.bouncycastle.openpgp.PGPSignature
|
||||||
|
import org.pgpainless.PGPainless
|
||||||
import org.pgpainless.key.OpenPgpFingerprint
|
import org.pgpainless.key.OpenPgpFingerprint
|
||||||
import org.pgpainless.key.SubkeyIdentifier
|
import org.pgpainless.key.SubkeyIdentifier
|
||||||
|
|
||||||
|
@ -51,7 +52,7 @@ fun PGPKeyRing.getPublicKey(fingerprint: OpenPgpFingerprint): PGPPublicKey? =
|
||||||
* identify the [PGPPublicKey] via its key-ID.
|
* identify the [PGPPublicKey] via its key-ID.
|
||||||
*/
|
*/
|
||||||
fun PGPKeyRing.getPublicKeyFor(signature: PGPSignature): PGPPublicKey? =
|
fun PGPKeyRing.getPublicKeyFor(signature: PGPSignature): PGPPublicKey? =
|
||||||
signature.getFingerprint()?.let { this.getPublicKey(it) } ?:
|
signature.fingerprint?.let { this.getPublicKey(it) } ?:
|
||||||
this.getPublicKey(signature.keyID)
|
this.getPublicKey(signature.keyID)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -59,3 +60,14 @@ fun PGPKeyRing.getPublicKeyFor(signature: PGPSignature): PGPPublicKey? =
|
||||||
*/
|
*/
|
||||||
fun PGPKeyRing.getPublicKeyFor(onePassSignature: PGPOnePassSignature): PGPPublicKey? =
|
fun PGPKeyRing.getPublicKeyFor(onePassSignature: PGPOnePassSignature): PGPPublicKey? =
|
||||||
this.getPublicKey(onePassSignature.keyID)
|
this.getPublicKey(onePassSignature.keyID)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the [OpenPgpFingerprint] of this OpenPGP key.
|
||||||
|
*/
|
||||||
|
val PGPKeyRing.openPgpFingerprint: OpenPgpFingerprint
|
||||||
|
get() = OpenPgpFingerprint.of(this)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return this OpenPGP key as an ASCII armored String.
|
||||||
|
*/
|
||||||
|
fun PGPKeyRing.toAsciiArmor(): String = PGPainless.asciiArmor(this)
|
|
@ -11,6 +11,7 @@ import org.bouncycastle.bcpg.EdDSAPublicBCPGKey
|
||||||
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil
|
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey
|
import org.bouncycastle.openpgp.PGPPublicKey
|
||||||
import org.pgpainless.algorithm.PublicKeyAlgorithm
|
import org.pgpainless.algorithm.PublicKeyAlgorithm
|
||||||
|
import org.pgpainless.key.OpenPgpFingerprint
|
||||||
import org.pgpainless.key.generation.type.eddsa.EdDSACurve
|
import org.pgpainless.key.generation.type.eddsa.EdDSACurve
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,3 +36,15 @@ fun PGPPublicKey.getCurveName(): String {
|
||||||
.let { it to ECUtil.getCurveName(it) }
|
.let { it to ECUtil.getCurveName(it) }
|
||||||
.let { if (it.second != null) return it.second else throw IllegalArgumentException("Unknown curve: ${it.first}") }
|
.let { if (it.second != null) return it.second else throw IllegalArgumentException("Unknown curve: ${it.first}") }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the [PublicKeyAlgorithm] of this key.
|
||||||
|
*/
|
||||||
|
val PGPPublicKey.publicKeyAlgorithm: PublicKeyAlgorithm
|
||||||
|
get() = PublicKeyAlgorithm.requireFromId(algorithm)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the [OpenPgpFingerprint] of this key.
|
||||||
|
*/
|
||||||
|
val PGPPublicKey.openPgpFingerprint: OpenPgpFingerprint
|
||||||
|
get() = OpenPgpFingerprint.of(this)
|
||||||
|
|
|
@ -7,10 +7,13 @@ package org.bouncycastle.extensions
|
||||||
import org.bouncycastle.bcpg.S2K
|
import org.bouncycastle.bcpg.S2K
|
||||||
import org.bouncycastle.openpgp.PGPException
|
import org.bouncycastle.openpgp.PGPException
|
||||||
import org.bouncycastle.openpgp.PGPPrivateKey
|
import org.bouncycastle.openpgp.PGPPrivateKey
|
||||||
|
import org.bouncycastle.openpgp.PGPPublicKey
|
||||||
import org.bouncycastle.openpgp.PGPSecretKey
|
import org.bouncycastle.openpgp.PGPSecretKey
|
||||||
import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor
|
import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor
|
||||||
|
import org.pgpainless.algorithm.PublicKeyAlgorithm
|
||||||
import org.pgpainless.exception.KeyIntegrityException
|
import org.pgpainless.exception.KeyIntegrityException
|
||||||
import org.pgpainless.exception.WrongPassphraseException
|
import org.pgpainless.exception.WrongPassphraseException
|
||||||
|
import org.pgpainless.key.OpenPgpFingerprint
|
||||||
import org.pgpainless.key.protection.SecretKeyRingProtector
|
import org.pgpainless.key.protection.SecretKeyRingProtector
|
||||||
import org.pgpainless.key.protection.UnlockSecretKey
|
import org.pgpainless.key.protection.UnlockSecretKey
|
||||||
import org.pgpainless.util.Passphrase
|
import org.pgpainless.util.Passphrase
|
||||||
|
@ -70,3 +73,15 @@ fun PGPSecretKey?.isDecrypted(): Boolean = (this == null) || (s2KUsage == 0)
|
||||||
* @return true if secret key has S2K of type GNU_DUMMY_S2K, false otherwise.
|
* @return true if secret key has S2K of type GNU_DUMMY_S2K, false otherwise.
|
||||||
*/
|
*/
|
||||||
fun PGPSecretKey?.hasDummyS2K(): Boolean = (this != null) && (s2K?.type == S2K.GNU_DUMMY_S2K)
|
fun PGPSecretKey?.hasDummyS2K(): Boolean = (this != null) && (s2K?.type == S2K.GNU_DUMMY_S2K)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the [PublicKeyAlgorithm] of this key.
|
||||||
|
*/
|
||||||
|
val PGPSecretKey.publicKeyAlgorithm: PublicKeyAlgorithm
|
||||||
|
get() = publicKey.publicKeyAlgorithm
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the [OpenPgpFingerprint] of this key.
|
||||||
|
*/
|
||||||
|
val PGPSecretKey.openPgpFingerprint: OpenPgpFingerprint
|
||||||
|
get() = OpenPgpFingerprint.of(this)
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
package org.bouncycastle.extensions
|
package org.bouncycastle.extensions
|
||||||
|
|
||||||
|
import openpgp.openPgpKeyId
|
||||||
import org.bouncycastle.openpgp.*
|
import org.bouncycastle.openpgp.*
|
||||||
import org.pgpainless.key.OpenPgpFingerprint
|
import org.pgpainless.key.OpenPgpFingerprint
|
||||||
|
|
||||||
|
@ -40,13 +41,29 @@ fun PGPSecretKeyRing.hasSecretKey(fingerprint: OpenPgpFingerprint): Boolean =
|
||||||
fun PGPSecretKeyRing.getSecretKey(fingerprint: OpenPgpFingerprint): PGPSecretKey? =
|
fun PGPSecretKeyRing.getSecretKey(fingerprint: OpenPgpFingerprint): PGPSecretKey? =
|
||||||
this.getSecretKey(fingerprint.bytes)
|
this.getSecretKey(fingerprint.bytes)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the [PGPSecretKey] with the given key-ID.
|
||||||
|
*
|
||||||
|
* @throws NoSuchElementException if the OpenPGP key doesn't contain a secret key with the given key-ID
|
||||||
|
*/
|
||||||
|
fun PGPSecretKeyRing.requireSecretKey(keyId: Long): PGPSecretKey =
|
||||||
|
getSecretKey(keyId) ?: throw NoSuchElementException("OpenPGP key does not contain key with id ${keyId.openPgpKeyId()}.")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the [PGPSecretKey] with the given fingerprint.
|
||||||
|
*
|
||||||
|
* @throws NoSuchElementException of the OpenPGP key doesn't contain a secret key with the given fingerprint
|
||||||
|
*/
|
||||||
|
fun PGPSecretKeyRing.requireSecretKey(fingerprint: OpenPgpFingerprint): PGPSecretKey =
|
||||||
|
getSecretKey(fingerprint) ?: throw NoSuchElementException("OpenPGP key does not contain key with fingerprint $fingerprint.")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the [PGPSecretKey] that matches the [OpenPgpFingerprint] of the given [PGPSignature].
|
* Return the [PGPSecretKey] that matches the [OpenPgpFingerprint] of the given [PGPSignature].
|
||||||
* If the [PGPSignature] does not carry an issuer-fingerprint subpacket, fall back to the issuer-keyID subpacket to
|
* If the [PGPSignature] does not carry an issuer-fingerprint subpacket, fall back to the issuer-keyID subpacket to
|
||||||
* identify the [PGPSecretKey] via its key-ID.
|
* identify the [PGPSecretKey] via its key-ID.
|
||||||
*/
|
*/
|
||||||
fun PGPSecretKeyRing.getSecretKeyFor(signature: PGPSignature): PGPSecretKey? =
|
fun PGPSecretKeyRing.getSecretKeyFor(signature: PGPSignature): PGPSecretKey? =
|
||||||
signature.getFingerprint()?.let { this.getSecretKey(it) } ?:
|
signature.fingerprint?.let { this.getSecretKey(it) } ?:
|
||||||
this.getSecretKey(signature.keyID)
|
this.getSecretKey(signature.keyID)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,10 +4,12 @@
|
||||||
|
|
||||||
package org.bouncycastle.extensions
|
package org.bouncycastle.extensions
|
||||||
|
|
||||||
|
import openpgp.plusSeconds
|
||||||
import org.bouncycastle.openpgp.PGPSignature
|
import org.bouncycastle.openpgp.PGPSignature
|
||||||
import org.pgpainless.algorithm.RevocationState
|
import org.pgpainless.algorithm.RevocationState
|
||||||
|
import org.pgpainless.algorithm.SignatureType
|
||||||
import org.pgpainless.key.OpenPgpFingerprint
|
import org.pgpainless.key.OpenPgpFingerprint
|
||||||
import org.pgpainless.signature.SignatureUtils
|
import org.pgpainless.key.util.RevocationAttributes.Reason
|
||||||
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil
|
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
@ -16,42 +18,74 @@ import java.util.*
|
||||||
* such a subpacket.
|
* such a subpacket.
|
||||||
*/
|
*/
|
||||||
fun PGPSignature.getKeyExpirationDate(keyCreationDate: Date): Date? =
|
fun PGPSignature.getKeyExpirationDate(keyCreationDate: Date): Date? =
|
||||||
SignatureUtils.getKeyExpirationDate(keyCreationDate, this)
|
SignatureSubpacketsUtil.getKeyExpirationTime(this)
|
||||||
|
?.let { keyCreationDate.plusSeconds(it.time) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the value of the signature ExpirationTime subpacket, or null, if the signature
|
* Return the value of the signature ExpirationTime subpacket, or null, if the signature
|
||||||
* does not carry such a subpacket.
|
* does not carry such a subpacket.
|
||||||
*/
|
*/
|
||||||
fun PGPSignature.getSignatureExpirationDate(): Date? =
|
val PGPSignature.signatureExpirationDate: Date?
|
||||||
SignatureUtils.getSignatureExpirationDate(this)
|
get() = SignatureSubpacketsUtil.getSignatureExpirationTime(this)
|
||||||
|
?.let { this.creationTime.plusSeconds(it.time) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true, if the signature is expired at the given reference time.
|
* Return true, if the signature is expired at the given reference time.
|
||||||
*/
|
*/
|
||||||
fun PGPSignature.isExpired(referenceTime: Date = Date()) =
|
fun PGPSignature.isExpired(referenceTime: Date = Date()) =
|
||||||
SignatureUtils.isSignatureExpired(this, referenceTime)
|
signatureExpirationDate?.let { referenceTime >= it } ?: false
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the key-ID of the issuer, determined by examining the IssuerKeyId and IssuerFingerprint
|
* Return the key-ID of the issuer, determined by examining the IssuerKeyId and IssuerFingerprint
|
||||||
* subpackets of the signature.
|
* subpackets of the signature.
|
||||||
*/
|
*/
|
||||||
fun PGPSignature.getIssuerKeyId() = SignatureUtils.determineIssuerKeyId(this)
|
val PGPSignature.issuerKeyId: Long
|
||||||
|
get() = when (version) {
|
||||||
|
2, 3 -> keyID
|
||||||
|
else -> {
|
||||||
|
SignatureSubpacketsUtil.getIssuerKeyIdAsLong(this)
|
||||||
|
?.let { if (it != 0L) it else null }
|
||||||
|
?: fingerprint?.keyId
|
||||||
|
?: 0L
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true, if the signature was likely issued by the key with the given fingerprint.
|
* Return true, if the signature was likely issued by a key with the given fingerprint.
|
||||||
*/
|
*/
|
||||||
fun PGPSignature.wasIssuedBy(fingerprint: OpenPgpFingerprint) = SignatureUtils.wasIssuedBy(fingerprint, this)
|
fun PGPSignature.wasIssuedBy(fingerprint: OpenPgpFingerprint): Boolean =
|
||||||
|
this.fingerprint?.let { it.keyId == fingerprint.keyId } ?: (keyID == fingerprint.keyId)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true, if the signature was likely issued by a key with the given fingerprint.
|
||||||
|
* @param fingerprint fingerprint bytes
|
||||||
|
*/
|
||||||
|
@Deprecated("Discouraged in favor of method taking an OpenPgpFingerprint.")
|
||||||
|
fun PGPSignature.wasIssuedBy(fingerprint: ByteArray): Boolean =
|
||||||
|
try {
|
||||||
|
wasIssuedBy(OpenPgpFingerprint.parseFromBinary(fingerprint))
|
||||||
|
} catch (e : IllegalArgumentException) {
|
||||||
|
// Unknown fingerprint length / format
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true, if this signature is a hard revocation.
|
* Return true, if this signature is a hard revocation.
|
||||||
*/
|
*/
|
||||||
fun PGPSignature.isHardRevocation() = SignatureUtils.isHardRevocation(this)
|
val PGPSignature.isHardRevocation
|
||||||
|
get() = when (SignatureType.requireFromCode(signatureType)) {
|
||||||
|
SignatureType.KEY_REVOCATION, SignatureType.SUBKEY_REVOCATION, SignatureType.CERTIFICATION_REVOCATION -> {
|
||||||
|
SignatureSubpacketsUtil.getRevocationReason(this)
|
||||||
|
?.let { Reason.isHardRevocation(it.revocationReason) }
|
||||||
|
?: true // no reason -> hard revocation
|
||||||
|
}
|
||||||
|
else -> false // Not a revocation
|
||||||
|
}
|
||||||
|
|
||||||
fun PGPSignature?.toRevocationState() =
|
fun PGPSignature?.toRevocationState() =
|
||||||
if (this == null) RevocationState.notRevoked()
|
if (this == null) RevocationState.notRevoked()
|
||||||
else
|
else if (isHardRevocation) RevocationState.hardRevoked()
|
||||||
if (isHardRevocation()) RevocationState.hardRevoked()
|
|
||||||
else RevocationState.softRevoked(creationTime)
|
else RevocationState.softRevoked(creationTime)
|
||||||
|
|
||||||
fun PGPSignature.getFingerprint(): OpenPgpFingerprint? =
|
val PGPSignature.fingerprint: OpenPgpFingerprint?
|
||||||
SignatureSubpacketsUtil.getIssuerFingerprintAsOpenPgpFingerprint(this)
|
get() = SignatureSubpacketsUtil.getIssuerFingerprintAsOpenPgpFingerprint(this)
|
|
@ -121,7 +121,7 @@ class KeyRingInfo(
|
||||||
val validAndExpiredUserIds: List<String> = userIds.filter {
|
val validAndExpiredUserIds: List<String> = userIds.filter {
|
||||||
val certification = signatures.userIdCertifications[it] ?: return@filter false
|
val certification = signatures.userIdCertifications[it] ?: return@filter false
|
||||||
val revocation = signatures.userIdRevocations[it] ?: return@filter true
|
val revocation = signatures.userIdRevocations[it] ?: return@filter true
|
||||||
return@filter !revocation.isHardRevocation() && certification.creationTime > revocation.creationTime
|
return@filter !revocation.isHardRevocation && certification.creationTime > revocation.creationTime
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -272,7 +272,7 @@ class KeyRingInfo(
|
||||||
* @return true, if the given user-ID is hard-revoked.
|
* @return true, if the given user-ID is hard-revoked.
|
||||||
*/
|
*/
|
||||||
fun isHardRevoked(userId: CharSequence): Boolean {
|
fun isHardRevoked(userId: CharSequence): Boolean {
|
||||||
return signatures.userIdRevocations[userId]?.isHardRevocation() ?: false
|
return signatures.userIdRevocations[userId]?.isHardRevocation ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -632,7 +632,7 @@ class KeyRingInfo(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
signatures.userIdRevocations[userId]?.let { rev ->
|
signatures.userIdRevocations[userId]?.let { rev ->
|
||||||
if (rev.isHardRevocation()) {
|
if (rev.isHardRevocation) {
|
||||||
return false // hard revoked -> invalid
|
return false // hard revoked -> invalid
|
||||||
}
|
}
|
||||||
sig.creationTime > rev.creationTime// re-certification after soft revocation?
|
sig.creationTime > rev.creationTime// re-certification after soft revocation?
|
||||||
|
|
|
@ -8,6 +8,7 @@ import openpgp.openPgpKeyId
|
||||||
import org.bouncycastle.bcpg.S2K
|
import org.bouncycastle.bcpg.S2K
|
||||||
import org.bouncycastle.bcpg.SecretKeyPacket
|
import org.bouncycastle.bcpg.SecretKeyPacket
|
||||||
import org.bouncycastle.extensions.certificate
|
import org.bouncycastle.extensions.certificate
|
||||||
|
import org.bouncycastle.extensions.requireSecretKey
|
||||||
import org.bouncycastle.openpgp.*
|
import org.bouncycastle.openpgp.*
|
||||||
import org.bouncycastle.util.Strings
|
import org.bouncycastle.util.Strings
|
||||||
import org.pgpainless.exception.MissingPassphraseException
|
import org.pgpainless.exception.MissingPassphraseException
|
||||||
|
@ -34,9 +35,10 @@ class KeyRingUtils {
|
||||||
* @return primary secret key
|
* @return primary secret key
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@Deprecated("Deprecated in favor of PGPSecretKeyRing extension function.",
|
||||||
|
ReplaceWith("secretKeys.requireSecretKey(keyId)"))
|
||||||
fun requirePrimarySecretKeyFrom(secretKeys: PGPSecretKeyRing): PGPSecretKey {
|
fun requirePrimarySecretKeyFrom(secretKeys: PGPSecretKeyRing): PGPSecretKey {
|
||||||
return getPrimarySecretKeyFrom(secretKeys)
|
return secretKeys.requireSecretKey(secretKeys.publicKey.keyID)
|
||||||
?: throw NoSuchElementException("Provided PGPSecretKeyRing has no primary secret key.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
|
|
||||||
package org.pgpainless.signature
|
package org.pgpainless.signature
|
||||||
|
|
||||||
|
import openpgp.plusSeconds
|
||||||
import org.bouncycastle.bcpg.sig.KeyExpirationTime
|
import org.bouncycastle.bcpg.sig.KeyExpirationTime
|
||||||
|
import org.bouncycastle.extensions.*
|
||||||
import org.bouncycastle.openpgp.*
|
import org.bouncycastle.openpgp.*
|
||||||
import org.bouncycastle.util.encoders.Hex
|
import org.bouncycastle.util.encoders.Hex
|
||||||
import org.bouncycastle.util.io.Streams
|
import org.bouncycastle.util.io.Streams
|
||||||
|
@ -17,6 +19,7 @@ import org.pgpainless.util.ArmorUtils
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.math.sign
|
||||||
|
|
||||||
const val MAX_ITERATIONS = 10000
|
const val MAX_ITERATIONS = 10000
|
||||||
|
|
||||||
|
@ -32,10 +35,10 @@ class SignatureUtils {
|
||||||
* @return key expiration date as given by the signature
|
* @return key expiration date as given by the signature
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@Deprecated("Deprecated in favor of PGPSignature extension method.",
|
||||||
|
ReplaceWith("signature.getKeyExpirationDate(keyCreationDate)"))
|
||||||
fun getKeyExpirationDate(keyCreationDate: Date, signature: PGPSignature): Date? {
|
fun getKeyExpirationDate(keyCreationDate: Date, signature: PGPSignature): Date? {
|
||||||
val expirationPacket: KeyExpirationTime = SignatureSubpacketsUtil.getKeyExpirationTime(signature) ?: return null
|
return signature.getKeyExpirationDate(keyCreationDate)
|
||||||
val expiresInSeconds = expirationPacket.time
|
|
||||||
return datePlusSeconds(keyCreationDate, expiresInSeconds)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,12 +49,9 @@ class SignatureUtils {
|
||||||
* @return expiration date of the signature, or null if it does not expire.
|
* @return expiration date of the signature, or null if it does not expire.
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getSignatureExpirationDate(signature: PGPSignature): Date? {
|
@Deprecated("Deprecated in favor of PGPSignature extension method.",
|
||||||
val expirationTime = SignatureSubpacketsUtil.getSignatureExpirationTime(signature) ?: return null
|
ReplaceWith("signature.signatureExpirationDate"))
|
||||||
|
fun getSignatureExpirationDate(signature: PGPSignature): Date? = signature.signatureExpirationDate
|
||||||
val expiresInSeconds = expirationTime.time
|
|
||||||
return datePlusSeconds(signature.creationTime, expiresInSeconds)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a new date which represents the given date plus the given amount of seconds added.
|
* Return a new date which represents the given date plus the given amount of seconds added.
|
||||||
|
@ -64,11 +64,10 @@ class SignatureUtils {
|
||||||
* @return date plus seconds or null if seconds is '0'
|
* @return date plus seconds or null if seconds is '0'
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@Deprecated("Deprecated in favor of Date extension method.",
|
||||||
|
ReplaceWith("date.plusSeconds(seconds)"))
|
||||||
fun datePlusSeconds(date: Date, seconds: Long): Date? {
|
fun datePlusSeconds(date: Date, seconds: Long): Date? {
|
||||||
if (seconds == 0L) {
|
return date.plusSeconds(seconds)
|
||||||
return null
|
|
||||||
}
|
|
||||||
return Date(date.time + 1000 * seconds)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,8 +78,10 @@ class SignatureUtils {
|
||||||
* @return true if expired, false otherwise
|
* @return true if expired, false otherwise
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@Deprecated("Deprecated in favor of PGPSignature extension method.",
|
||||||
|
ReplaceWith("signature.isExpired()"))
|
||||||
fun isSignatureExpired(signature: PGPSignature): Boolean {
|
fun isSignatureExpired(signature: PGPSignature): Boolean {
|
||||||
return isSignatureExpired(signature, Date())
|
return signature.isExpired()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,9 +93,10 @@ class SignatureUtils {
|
||||||
* @return true if sig is expired at reference date, false otherwise
|
* @return true if sig is expired at reference date, false otherwise
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@Deprecated("Deprecated in favor of PGPSignature extension method.",
|
||||||
|
ReplaceWith("signature.isExpired(referenceTime)"))
|
||||||
fun isSignatureExpired(signature: PGPSignature, referenceTime: Date): Boolean {
|
fun isSignatureExpired(signature: PGPSignature, referenceTime: Date): Boolean {
|
||||||
val expirationDate = getSignatureExpirationDate(signature) ?: return false
|
return signature.isExpired(referenceTime)
|
||||||
return referenceTime >= expirationDate
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -106,15 +108,10 @@ class SignatureUtils {
|
||||||
* @return true if signature is a hard revocation
|
* @return true if signature is a hard revocation
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@Deprecated("Deprecated in favor of PGPSignature extension function.",
|
||||||
|
ReplaceWith("signature.isHardRevocation()"))
|
||||||
fun isHardRevocation(signature: PGPSignature): Boolean {
|
fun isHardRevocation(signature: PGPSignature): Boolean {
|
||||||
val type = SignatureType.requireFromCode(signature.signatureType)
|
return signature.isHardRevocation
|
||||||
if (type != SignatureType.KEY_REVOCATION && type != SignatureType.SUBKEY_REVOCATION && type != SignatureType.CERTIFICATION_REVOCATION) {
|
|
||||||
// Not a revocation
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
val reason = SignatureSubpacketsUtil.getRevocationReason(signature) ?: return true // no reason -> hard revocation
|
|
||||||
return Reason.isHardRevocation(reason.revocationReason)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@ -181,22 +178,10 @@ class SignatureUtils {
|
||||||
* @return signatures issuing key id
|
* @return signatures issuing key id
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@Deprecated("Deprecated in favor of PGPSignature extension method.",
|
||||||
|
ReplaceWith("signature.issuerKeyId"))
|
||||||
fun determineIssuerKeyId(signature: PGPSignature): Long {
|
fun determineIssuerKeyId(signature: PGPSignature): Long {
|
||||||
if (signature.version == 3) {
|
return signature.issuerKeyId
|
||||||
// V3 sigs do not contain subpackets
|
|
||||||
return signature.keyID
|
|
||||||
}
|
|
||||||
|
|
||||||
val issuerKeyId = SignatureSubpacketsUtil.getIssuerKeyId(signature)
|
|
||||||
val issuerFingerprint = SignatureSubpacketsUtil.getIssuerFingerprintAsOpenPgpFingerprint(signature)
|
|
||||||
|
|
||||||
if (issuerKeyId != null && issuerKeyId.keyID != 0L) {
|
|
||||||
return issuerKeyId.keyID
|
|
||||||
}
|
|
||||||
if (issuerKeyId == null && issuerFingerprint != null) {
|
|
||||||
return issuerFingerprint.keyId
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -211,21 +196,17 @@ class SignatureUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@Deprecated("Deprecated in favor of PGPSignature extension method",
|
||||||
|
ReplaceWith("signature.wasIssuedBy(fingerprint)"))
|
||||||
fun wasIssuedBy(fingerprint: ByteArray, signature: PGPSignature): Boolean {
|
fun wasIssuedBy(fingerprint: ByteArray, signature: PGPSignature): Boolean {
|
||||||
return try {
|
return signature.wasIssuedBy(fingerprint)
|
||||||
val pgpFingerprint = OpenPgpFingerprint.parseFromBinary(fingerprint)
|
|
||||||
wasIssuedBy(pgpFingerprint, signature)
|
|
||||||
} catch (e : IllegalArgumentException) {
|
|
||||||
// Unknown fingerprint length
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@Deprecated("Deprecated in favor of PGPSignature extension method",
|
||||||
|
ReplaceWith("signature.wasIssuedBy(fingerprint)"))
|
||||||
fun wasIssuedBy(fingerprint: OpenPgpFingerprint, signature: PGPSignature): Boolean {
|
fun wasIssuedBy(fingerprint: OpenPgpFingerprint, signature: PGPSignature): Boolean {
|
||||||
val issuerFp = SignatureSubpacketsUtil.getIssuerFingerprintAsOpenPgpFingerprint(signature)
|
return signature.wasIssuedBy(fingerprint)
|
||||||
?: return fingerprint.keyId == signature.keyID
|
|
||||||
return fingerprint == issuerFp
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue