mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-25 12:27:58 +01:00
Sanitize key flags
This commit is contained in:
parent
61c6c2116a
commit
6cfeba064e
2 changed files with 131 additions and 42 deletions
|
@ -20,6 +20,7 @@ import org.pgpainless.algorithm.AlgorithmSuite
|
||||||
import org.pgpainless.algorithm.CertificationType
|
import org.pgpainless.algorithm.CertificationType
|
||||||
import org.pgpainless.algorithm.HashAlgorithm
|
import org.pgpainless.algorithm.HashAlgorithm
|
||||||
import org.pgpainless.algorithm.KeyFlag
|
import org.pgpainless.algorithm.KeyFlag
|
||||||
|
import org.pgpainless.algorithm.PublicKeyAlgorithm
|
||||||
import org.pgpainless.implementation.ImplementationFactory
|
import org.pgpainless.implementation.ImplementationFactory
|
||||||
import org.pgpainless.key.generation.DefinePrimaryKey.PrimaryKeyBuilder
|
import org.pgpainless.key.generation.DefinePrimaryKey.PrimaryKeyBuilder
|
||||||
import org.pgpainless.key.generation.DefineSubkeys.SubkeyBuilder
|
import org.pgpainless.key.generation.DefineSubkeys.SubkeyBuilder
|
||||||
|
@ -169,7 +170,13 @@ internal constructor(val policy: Policy, val creationTime: Date, val preferences
|
||||||
keyFlags: List<KeyFlag>? = listOf(KeyFlag.CERTIFY_OTHER),
|
keyFlags: List<KeyFlag>? = listOf(KeyFlag.CERTIFY_OTHER),
|
||||||
creationTime: Date = this.creationTime,
|
creationTime: Date = this.creationTime,
|
||||||
block: PrimaryKeyBlock? = null
|
block: PrimaryKeyBlock? = null
|
||||||
): O = doSetPrimaryKey(type, keyFlags, creationTime, block)
|
): O {
|
||||||
|
require(type.canCertify) {
|
||||||
|
"Primary key cannot use algorithm ${type.algorithm} because it needs to be " +
|
||||||
|
"signing capable."
|
||||||
|
}
|
||||||
|
return doSetPrimaryKey(type, keyFlags, creationTime, block)
|
||||||
|
}
|
||||||
|
|
||||||
fun setPrimaryKey(type: KeyType, block: PrimaryKeyBlock?): O =
|
fun setPrimaryKey(type: KeyType, block: PrimaryKeyBlock?): O =
|
||||||
setPrimaryKey(type, listOf(KeyFlag.CERTIFY_OTHER), this.creationTime, block)
|
setPrimaryKey(type, listOf(KeyFlag.CERTIFY_OTHER), this.creationTime, block)
|
||||||
|
@ -200,6 +207,10 @@ internal constructor(val policy: Policy, val creationTime: Date, val preferences
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected open fun sanitizeKeyFlags(algorithm: PublicKeyAlgorithm, keyFlags: List<KeyFlag>?) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function that can be applied to the primary key.
|
* Function that can be applied to the primary key.
|
||||||
*
|
*
|
||||||
|
@ -407,14 +418,23 @@ internal constructor(
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun addSubkey(
|
fun addSubkey(
|
||||||
type: KeyType,
|
type: KeyType,
|
||||||
|
flags: List<KeyFlag>? = null,
|
||||||
creationTime: Date = this.creationTime,
|
creationTime: Date = this.creationTime,
|
||||||
block: SubkeyBlock? = null
|
block: SubkeyBlock? = null
|
||||||
): B =
|
): B =
|
||||||
apply {
|
apply {
|
||||||
|
sanitizeKeyFlags(type.algorithm, flags)
|
||||||
sanitizeSubkeyCreationTime(creationTime, primaryKey)
|
sanitizeSubkeyCreationTime(creationTime, primaryKey)
|
||||||
|
|
||||||
var subkey = generateSubkey(type, creationTime)
|
var subkey = generateSubkey(type, creationTime)
|
||||||
subkey = invokeOnSubkey(subkey, block)
|
val subkeyBlock =
|
||||||
|
block
|
||||||
|
?: {
|
||||||
|
addBindingSignature(
|
||||||
|
SelfSignatureSubpackets.applyHashed { flags?.let { setKeyFlags(it) } },
|
||||||
|
bindingTime = creationTime)
|
||||||
|
}
|
||||||
|
subkey = invokeOnSubkey(subkey, subkeyBlock)
|
||||||
subkeys.add(subkey)
|
subkeys.add(subkey)
|
||||||
}
|
}
|
||||||
as B
|
as B
|
||||||
|
@ -490,6 +510,10 @@ internal constructor(
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected open fun sanitizeKeyFlags(algorithm: PublicKeyAlgorithm, keyFlags: List<KeyFlag>?) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function that can be applied to subkeys.
|
* Function that can be applied to subkeys.
|
||||||
*
|
*
|
||||||
|
@ -723,8 +747,6 @@ internal constructor(policy: Policy, creationTime: Date, preferences: AlgorithmS
|
||||||
creationTime: Date,
|
creationTime: Date,
|
||||||
block: PrimaryKeyBlock?
|
block: PrimaryKeyBlock?
|
||||||
): OpinionatedDefineSubkeysV4 {
|
): OpinionatedDefineSubkeysV4 {
|
||||||
// Check algorithm is signing capable
|
|
||||||
require(type.algorithm.isSigningCapable()) { "Primary Key MUST be capable of signing." }
|
|
||||||
|
|
||||||
// Check key strength
|
// Check key strength
|
||||||
require(policy.publicKeyAlgorithmPolicy.isAcceptable(type.algorithm, type.bitStrength)) {
|
require(policy.publicKeyAlgorithmPolicy.isAcceptable(type.algorithm, type.bitStrength)) {
|
||||||
|
@ -732,6 +754,9 @@ internal constructor(policy: Policy, creationTime: Date, preferences: AlgorithmS
|
||||||
" for the current public key algorithm policy."
|
" for the current public key algorithm policy."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sanitize key flags
|
||||||
|
sanitizeKeyFlags(type.algorithm, keyFlags)
|
||||||
|
|
||||||
// Remember flags for DK and UID signatures
|
// Remember flags for DK and UID signatures
|
||||||
this.keyFlags = keyFlags
|
this.keyFlags = keyFlags
|
||||||
|
|
||||||
|
@ -762,6 +787,27 @@ internal constructor(policy: Policy, creationTime: Date, preferences: AlgorithmS
|
||||||
"key was created at ${primaryKey.publicKey.creationTime.formatUTC()}."
|
"key was created at ${primaryKey.publicKey.creationTime.formatUTC()}."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun sanitizeKeyFlags(algorithm: PublicKeyAlgorithm, keyFlags: List<KeyFlag>?) {
|
||||||
|
keyFlags?.forEach { flag ->
|
||||||
|
when (flag) {
|
||||||
|
KeyFlag.CERTIFY_OTHER,
|
||||||
|
KeyFlag.SIGN_DATA,
|
||||||
|
KeyFlag.AUTHENTICATION ->
|
||||||
|
require(algorithm.isSigningCapable()) {
|
||||||
|
"Primary key cannot carry key flag $flag because the " +
|
||||||
|
"algorithm $algorithm is not signing capable."
|
||||||
|
}
|
||||||
|
KeyFlag.ENCRYPT_COMMS,
|
||||||
|
KeyFlag.ENCRYPT_STORAGE ->
|
||||||
|
require(algorithm.isEncryptionCapable()) {
|
||||||
|
"Primary key cannot carry key flag $flag because the " +
|
||||||
|
"algorithm $algorithm is not encryption capable."
|
||||||
|
}
|
||||||
|
else -> {} // no special requirements for SPLIT and SHARED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -842,11 +888,10 @@ internal constructor(primaryKey: PGPKeyPair, policy: Policy, creationTime: Date)
|
||||||
fun addSigningSubkey(
|
fun addSigningSubkey(
|
||||||
type: KeyType,
|
type: KeyType,
|
||||||
creationTime: Date = this.creationTime,
|
creationTime: Date = this.creationTime,
|
||||||
block: SubkeyBlock? = {
|
block: SubkeyBlock? = null
|
||||||
addBindingSignature(
|
): OpinionatedDefineSubkeysV4 {
|
||||||
SelfSignatureSubpackets.applyHashed { setKeyFlags(KeyFlag.SIGN_DATA) })
|
return addSubkey(type, listOf(KeyFlag.SIGN_DATA), creationTime, block)
|
||||||
}
|
}
|
||||||
) = addSubkey(type, creationTime, block)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a subkey for signing messages to the OpenPGP key.
|
* Add a subkey for signing messages to the OpenPGP key.
|
||||||
|
@ -868,13 +913,11 @@ internal constructor(primaryKey: PGPKeyPair, policy: Policy, creationTime: Date)
|
||||||
fun addEncryptionSubkey(
|
fun addEncryptionSubkey(
|
||||||
type: KeyType,
|
type: KeyType,
|
||||||
creationTime: Date = this.creationTime,
|
creationTime: Date = this.creationTime,
|
||||||
block: SubkeyBlock? = {
|
block: SubkeyBlock? = null,
|
||||||
addBindingSignature(
|
): OpinionatedDefineSubkeysV4 {
|
||||||
SelfSignatureSubpackets.applyHashed {
|
return addSubkey(
|
||||||
setKeyFlags(KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE)
|
type, listOf(KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE), creationTime, block)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
) = addSubkey(type, creationTime, block)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a subkey for message encryption to the OpenPGP key.
|
* Add a subkey for message encryption to the OpenPGP key.
|
||||||
|
@ -907,6 +950,27 @@ internal constructor(primaryKey: PGPKeyPair, policy: Policy, creationTime: Date)
|
||||||
"Primary key was created at ${primaryKey.publicKey.creationTime.formatUTC()}."
|
"Primary key was created at ${primaryKey.publicKey.creationTime.formatUTC()}."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun sanitizeKeyFlags(algorithm: PublicKeyAlgorithm, keyFlags: List<KeyFlag>?) {
|
||||||
|
keyFlags?.forEach { flag ->
|
||||||
|
when (flag) {
|
||||||
|
KeyFlag.CERTIFY_OTHER,
|
||||||
|
KeyFlag.SIGN_DATA,
|
||||||
|
KeyFlag.AUTHENTICATION ->
|
||||||
|
require(algorithm.isSigningCapable()) {
|
||||||
|
"Subkey cannot carry key flag $flag because the " +
|
||||||
|
"algorithm $algorithm is not signing capable."
|
||||||
|
}
|
||||||
|
KeyFlag.ENCRYPT_COMMS,
|
||||||
|
KeyFlag.ENCRYPT_STORAGE ->
|
||||||
|
require(algorithm.isEncryptionCapable()) {
|
||||||
|
"Subkey cannot carry key flag $flag because the " +
|
||||||
|
"algorithm $algorithm is not encryption capable."
|
||||||
|
}
|
||||||
|
else -> {} // no special requirements for SPLIT and SHARED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1078,17 +1142,9 @@ class OpenPgpKeyTemplates private constructor() {
|
||||||
SelfSignatureSubpackets.applyHashed { setKeyFlags(KeyFlag.CERTIFY_OTHER) })
|
SelfSignatureSubpackets.applyHashed { setKeyFlags(KeyFlag.CERTIFY_OTHER) })
|
||||||
}
|
}
|
||||||
// singing key
|
// singing key
|
||||||
.addSubkey(KeyType.EDDSA(EdDSACurve._Ed25519)) {
|
.addSigningSubkey(KeyType.EDDSA(EdDSACurve._Ed25519))
|
||||||
addBindingSignature(
|
|
||||||
SelfSignatureSubpackets.applyHashed { setKeyFlags(KeyFlag.SIGN_DATA) })
|
|
||||||
}
|
|
||||||
// encryption key
|
// encryption key
|
||||||
.addSubkey(KeyType.XDH(XDHSpec._X25519)) {
|
.addEncryptionSubkey(KeyType.XDH(XDHSpec._X25519))
|
||||||
addBindingSignature(
|
|
||||||
SelfSignatureSubpackets.applyHashed {
|
|
||||||
setKeyFlags(KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1122,17 +1178,9 @@ class OpenPgpKeyTemplates private constructor() {
|
||||||
SelfSignatureSubpackets.applyHashed { setKeyFlags(KeyFlag.CERTIFY_OTHER) })
|
SelfSignatureSubpackets.applyHashed { setKeyFlags(KeyFlag.CERTIFY_OTHER) })
|
||||||
}
|
}
|
||||||
// signing key
|
// signing key
|
||||||
.addSubkey(KeyType.RSA(length)) {
|
.addSigningSubkey(KeyType.RSA(length))
|
||||||
addBindingSignature(
|
|
||||||
SelfSignatureSubpackets.applyHashed { setKeyFlags(KeyFlag.SIGN_DATA) })
|
|
||||||
}
|
|
||||||
// encryption key
|
// encryption key
|
||||||
.addSubkey(KeyType.RSA(length)) {
|
.addEncryptionSubkey(KeyType.RSA(length))
|
||||||
addBindingSignature(
|
|
||||||
SelfSignatureSubpackets.applyHashed {
|
|
||||||
setKeyFlags(KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -109,10 +109,7 @@ class OpenPgpKeyGeneratorTest {
|
||||||
val key =
|
val key =
|
||||||
OpenPgpKeyGenerator.buildV4Key()
|
OpenPgpKeyGenerator.buildV4Key()
|
||||||
.setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519))
|
.setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519))
|
||||||
.addSubkey(KeyType.EDDSA(EdDSACurve._Ed25519)) {
|
.addSubkey(KeyType.EDDSA(EdDSACurve._Ed25519), listOf(KeyFlag.SIGN_DATA))
|
||||||
addBindingSignature(
|
|
||||||
SelfSignatureSubpackets.applyHashed { setKeyFlags(KeyFlag.SIGN_DATA) })
|
|
||||||
}
|
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
assertFalse(
|
assertFalse(
|
||||||
|
@ -376,7 +373,7 @@ class OpenPgpKeyGeneratorTest {
|
||||||
assertThrows<IllegalArgumentException> {
|
assertThrows<IllegalArgumentException> {
|
||||||
OpenPgpKeyGenerator.buildV4Key(policy, t1)
|
OpenPgpKeyGenerator.buildV4Key(policy, t1)
|
||||||
.setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519))
|
.setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519))
|
||||||
.addSubkey(KeyType.XDH(XDHSpec._X25519), t0)
|
.addSubkey(KeyType.XDH(XDHSpec._X25519), null, t0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,7 +386,7 @@ class OpenPgpKeyGeneratorTest {
|
||||||
OpenPgpKeyGenerator.buildV4Key(policy, t1)
|
OpenPgpKeyGenerator.buildV4Key(policy, t1)
|
||||||
.unopinionated()
|
.unopinionated()
|
||||||
.setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519))
|
.setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519))
|
||||||
.addSubkey(KeyType.XDH(XDHSpec._X25519), t0)
|
.addSubkey(KeyType.XDH(XDHSpec._X25519), null, t0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -442,6 +439,50 @@ class OpenPgpKeyGeneratorTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `opinionated set primary key to encryption key fails`() {
|
||||||
|
val policy = Policy()
|
||||||
|
|
||||||
|
assertThrows<IllegalArgumentException> {
|
||||||
|
OpenPgpKeyGenerator.buildV4Key(policy).setPrimaryKey(KeyType.XDH(XDHSpec._X25519))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `opinionated set primary key to sign-only algorithm but with encryption flag fails`() {
|
||||||
|
val policy = Policy()
|
||||||
|
|
||||||
|
assertThrows<IllegalArgumentException> {
|
||||||
|
OpenPgpKeyGenerator.buildV4Key(policy)
|
||||||
|
.setPrimaryKey(
|
||||||
|
KeyType.EDDSA(EdDSACurve._Ed25519),
|
||||||
|
listOf(KeyFlag.CERTIFY_OTHER, KeyFlag.ENCRYPT_STORAGE))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `unopinionated set primary key to sign-only algorithm but with encryption flag is okay`() {
|
||||||
|
val policy = Policy()
|
||||||
|
|
||||||
|
OpenPgpKeyGenerator.buildV4Key(policy)
|
||||||
|
.unopinionated()
|
||||||
|
.setPrimaryKey(
|
||||||
|
KeyType.EDDSA(EdDSACurve._Ed25519),
|
||||||
|
listOf(KeyFlag.CERTIFY_OTHER, KeyFlag.ENCRYPT_STORAGE))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `opinionated add encryption-only subkey with additional sign flag fails`() {
|
||||||
|
val policy = Policy()
|
||||||
|
|
||||||
|
assertThrows<IllegalArgumentException> {
|
||||||
|
OpenPgpKeyGenerator.buildV4Key(policy)
|
||||||
|
.setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519))
|
||||||
|
.addSubkey(
|
||||||
|
KeyType.XDH(XDHSpec._X25519), listOf(KeyFlag.ENCRYPT_COMMS, KeyFlag.SIGN_DATA))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `add image attribute to key`() {
|
fun `add image attribute to key`() {
|
||||||
// smallest JPEG according to https://stackoverflow.com/a/2349470/11150851
|
// smallest JPEG according to https://stackoverflow.com/a/2349470/11150851
|
||||||
|
|
Loading…
Reference in a new issue