mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-09-09 02:09:38 +02:00
Compare commits
20 commits
880b0720db
...
7daa3783bc
Author | SHA1 | Date | |
---|---|---|---|
7daa3783bc | |||
4d46edf3b6 | |||
7656bcd101 | |||
9f8ce475eb | |||
4f8c52d215 | |||
16a2bf27eb | |||
742f8fa1a3 | |||
916809ad60 | |||
002bd87136 | |||
05cea3e5a9 | |||
95eb73a8c7 | |||
06b3452c6c | |||
307b3ae40b | |||
0d8ce6a50b | |||
32dc1fa1a1 | |||
4a4f85767a | |||
d1826eb961 | |||
0d807cb6b8 | |||
9b0a3cd4c7 | |||
0ee31b232a |
165 changed files with 1532 additions and 55 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -33,3 +33,5 @@ pgpainless-core/.settings/
|
|||
push_html.sh
|
||||
|
||||
node_modules
|
||||
|
||||
*/.cifuzz-corpus/*
|
||||
|
|
|
@ -111,6 +111,12 @@ precedence = "aggregate"
|
|||
SPDX-FileCopyrightText = "2022 Paul Schaub <info@pgpainless.org>"
|
||||
SPDX-License-Identifier = "Apache-2.0"
|
||||
|
||||
[[annotations]]
|
||||
path = "pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/**"
|
||||
precedence = "aggregate"
|
||||
SPDX-FileCopyrightText = "2025 Paul Schaub <info@pgpainless.org>"
|
||||
SPDX-License-Identifier = "CC0-1.0"
|
||||
|
||||
[[annotations]]
|
||||
path = ".github/ISSUE_TEMPLATE/**"
|
||||
precedence = "aggregate"
|
||||
|
|
|
@ -12,6 +12,9 @@ dependencies {
|
|||
testImplementation "org.junit.jupiter:junit-jupiter-params:$junitVersion"
|
||||
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion"
|
||||
|
||||
// Jazzer for Fuzzing
|
||||
testImplementation "com.code-intelligence:jazzer-junit:$jazzerVersion"
|
||||
|
||||
// Mocking Components
|
||||
testImplementation "org.mockito:mockito-core:$mockitoVersion"
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ public class OpenPgpInputStream extends BufferedInputStream {
|
|||
this(in, true);
|
||||
}
|
||||
|
||||
private void inspectBuffer() throws IOException {
|
||||
public void inspectBuffer() throws IOException {
|
||||
if (checkForAsciiArmor()) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -139,7 +139,11 @@ class OpenPgpMessageInputStream(
|
|||
|
||||
// Comsume packets, potentially stepping into nested layers
|
||||
layer@ while (run {
|
||||
packet = pIn.nextPacketTag()
|
||||
packet = try {
|
||||
pIn.nextPacketTag()
|
||||
} catch (e: NoSuchElementException) {
|
||||
throw MalformedOpenPgpMessageException(e.message)
|
||||
}
|
||||
packet
|
||||
} != null) {
|
||||
|
||||
|
@ -206,12 +210,25 @@ class OpenPgpMessageInputStream(
|
|||
syntaxVerifier.next(InputSymbol.LITERAL_DATA)
|
||||
val literalData = packetInputStream!!.readLiteralData()
|
||||
|
||||
val streamEncoding = try {
|
||||
StreamEncoding.requireFromCode(literalData.format)
|
||||
} catch (e: NoSuchElementException) {
|
||||
throw PGPException("Invalid stream encoding format encountered: ${literalData.format}; ${e.message}")
|
||||
}
|
||||
|
||||
val fileName = try {
|
||||
literalData.fileName
|
||||
} catch (e: IllegalArgumentException) {
|
||||
// Non UTF8
|
||||
throw PGPException("Cannot decode literal data filename: ${e.message}")
|
||||
}
|
||||
|
||||
// Extract Metadata
|
||||
layerMetadata.child =
|
||||
LiteralData(
|
||||
literalData.fileName,
|
||||
fileName,
|
||||
literalData.modificationTime,
|
||||
StreamEncoding.requireFromCode(literalData.format))
|
||||
streamEncoding)
|
||||
|
||||
nestedInputStream = literalData.inputStream
|
||||
}
|
||||
|
@ -221,10 +238,16 @@ class OpenPgpMessageInputStream(
|
|||
signatures.enterNesting()
|
||||
val compressedData = packetInputStream!!.readCompressedData()
|
||||
|
||||
val compAlg = try {
|
||||
CompressionAlgorithm.requireFromId(compressedData.algorithm)
|
||||
} catch (e: NoSuchElementException) {
|
||||
throw PGPException(e.message)
|
||||
}
|
||||
|
||||
// Extract Metadata
|
||||
val compressionLayer =
|
||||
CompressedData(
|
||||
CompressionAlgorithm.requireFromId(compressedData.algorithm),
|
||||
compAlg,
|
||||
layerMetadata.depth + 1)
|
||||
|
||||
LOGGER.debug(
|
||||
|
@ -324,7 +347,7 @@ class OpenPgpMessageInputStream(
|
|||
"Symmetrically Encrypted Data Packet at depth ${layerMetadata.depth} encountered.")
|
||||
syntaxVerifier.next(InputSymbol.ENCRYPTED_DATA)
|
||||
val encDataList = packetInputStream!!.readEncryptedDataList()
|
||||
if (!encDataList.isIntegrityProtected && !encDataList.get(0).isAEAD) {
|
||||
if (!encDataList.isIntegrityProtected && !encDataList.isEmpty && !encDataList.get(0).isAEAD) {
|
||||
LOGGER.warn("Symmetrically Encrypted Data Packet is not integrity-protected.")
|
||||
if (!options.isIgnoreMDCErrors()) {
|
||||
throw MessageNotIntegrityProtectedException()
|
||||
|
@ -546,7 +569,13 @@ class OpenPgpMessageInputStream(
|
|||
pkesk: PGPPublicKeyEncryptedData
|
||||
): Boolean {
|
||||
try {
|
||||
val decrypted = pkesk.getDataStream(decryptorFactory)
|
||||
val decrypted = try {
|
||||
pkesk.getDataStream(decryptorFactory)
|
||||
} catch (e: ClassCastException) {
|
||||
throw PGPException(e.message)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
throw PGPException(e.message)
|
||||
}
|
||||
val sessionKey = SessionKey(pkesk.getSessionKey(decryptorFactory))
|
||||
throwIfUnacceptable(sessionKey.algorithm)
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.bouncycastle.openpgp.PGPOnePassSignature
|
|||
import org.bouncycastle.openpgp.PGPPadding
|
||||
import org.bouncycastle.openpgp.PGPSignature
|
||||
import org.pgpainless.algorithm.OpenPgpPacket
|
||||
import org.pgpainless.exception.MalformedOpenPgpMessageException
|
||||
|
||||
/**
|
||||
* Since we need to update signatures with data from the underlying stream, this class is used to
|
||||
|
@ -61,7 +62,12 @@ class TeeBCPGInputStream(inputStream: BCPGInputStream, outputStream: OutputStrea
|
|||
|
||||
fun readEncryptedDataList(): PGPEncryptedDataList {
|
||||
delayedTee.squeeze()
|
||||
return PGPEncryptedDataList(packetInputStream)
|
||||
return try {
|
||||
PGPEncryptedDataList(packetInputStream)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
// Mismatched SKESK / SEIPD version
|
||||
throw MalformedOpenPgpMessageException(e.message)
|
||||
}
|
||||
}
|
||||
|
||||
fun readOnePassSignature(): PGPOnePassSignature {
|
||||
|
|
|
@ -45,7 +45,7 @@ class KeyRingBuilder : KeyRingBuilderInterface<KeyRingBuilder> {
|
|||
}
|
||||
|
||||
override fun addUserId(userId: CharSequence): KeyRingBuilder = apply {
|
||||
userIds[userId.toString().trim()] = null
|
||||
userIds[userId.toString()] = null
|
||||
}
|
||||
|
||||
override fun addUserId(userId: ByteArray): KeyRingBuilder =
|
||||
|
|
|
@ -478,7 +478,7 @@ class SecretKeyRingEditor(
|
|||
val prevBinding =
|
||||
inspectKeyRing(secretKeyRing).getCurrentSubkeyBindingSignature(keyId)
|
||||
?: throw NoSuchElementException(
|
||||
"Previous subkey binding signaure for ${keyId.openPgpKeyId()} MUST NOT be null.")
|
||||
"Previous subkey binding signature for ${keyId.openPgpKeyId()} MUST NOT be null.")
|
||||
val bindingSig = reissueSubkeyBindingSignature(subkey, expiration, protector, prevBinding)
|
||||
secretKeyRing = injectCertification(secretKeyRing, subkey, bindingSig)
|
||||
}
|
||||
|
@ -569,9 +569,10 @@ class SecretKeyRingEditor(
|
|||
}
|
||||
|
||||
private fun sanitizeUserId(userId: CharSequence): CharSequence =
|
||||
// TODO: Further research how to sanitize user IDs.
|
||||
// e.g. what about newlines?
|
||||
userId.toString().trim()
|
||||
// I'm not sure, what kind of sanitization is needed.
|
||||
// Newlines are allowed, they just need to be escaped when emitted in an ASCII armor header
|
||||
// Trailing/Leading whitespace is also fine.
|
||||
userId.toString()
|
||||
|
||||
private fun callbackFromRevocationAttributes(attributes: RevocationAttributes?) =
|
||||
object : RevocationSignatureSubpackets.Callback {
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.io.IOException
|
|||
import java.io.InputStream
|
||||
import java.util.*
|
||||
import openpgp.plusSeconds
|
||||
import org.bouncycastle.bcpg.UnsupportedPacketVersionException
|
||||
import org.bouncycastle.bcpg.sig.KeyExpirationTime
|
||||
import org.bouncycastle.openpgp.*
|
||||
import org.bouncycastle.util.encoders.Hex
|
||||
|
@ -151,37 +152,46 @@ class SignatureUtils {
|
|||
*/
|
||||
@JvmStatic
|
||||
fun readSignatures(inputStream: InputStream, maxIterations: Int): List<PGPSignature> {
|
||||
val signatures = mutableListOf<PGPSignature>()
|
||||
val pgpIn = ArmorUtils.getDecoderStream(inputStream)
|
||||
val objectFactory = ImplementationFactory.getInstance().getPGPObjectFactory(pgpIn)
|
||||
try {
|
||||
val signatures = mutableListOf<PGPSignature>()
|
||||
val pgpIn = ArmorUtils.getDecoderStream(inputStream)
|
||||
val objectFactory = ImplementationFactory.getInstance().getPGPObjectFactory(pgpIn)
|
||||
|
||||
var i = 0
|
||||
var nextObject: Any? = null
|
||||
while (i++ < maxIterations &&
|
||||
objectFactory.nextObject().also { nextObject = it } != null) {
|
||||
// Since signatures are indistinguishable from randomness, there is no point in
|
||||
// having them compressed,
|
||||
// except for an attacker who is trying to exploit flaws in the decompression
|
||||
// algorithm.
|
||||
// Therefore, we ignore compressed data packets without attempting decompression.
|
||||
if (nextObject is PGPCompressedData) {
|
||||
// getInputStream() does not do decompression, contrary to getDataStream().
|
||||
Streams.drain(
|
||||
(nextObject as PGPCompressedData)
|
||||
.inputStream) // Skip packet without decompressing
|
||||
var i = 0
|
||||
var nextObject: Any? = null
|
||||
while (i++ < maxIterations &&
|
||||
objectFactory.nextObject().also { nextObject = it } != null) {
|
||||
// Since signatures are indistinguishable from randomness, there is no point in
|
||||
// having them compressed,
|
||||
// except for an attacker who is trying to exploit flaws in the decompression
|
||||
// algorithm.
|
||||
// Therefore, we ignore compressed data packets without attempting decompression.
|
||||
if (nextObject is PGPCompressedData) {
|
||||
// getInputStream() does not do decompression, contrary to getDataStream().
|
||||
Streams.drain(
|
||||
(nextObject as PGPCompressedData)
|
||||
.inputStream
|
||||
) // Skip packet without decompressing
|
||||
}
|
||||
|
||||
if (nextObject is PGPSignatureList) {
|
||||
signatures.addAll(nextObject as PGPSignatureList)
|
||||
}
|
||||
|
||||
if (nextObject is PGPSignature) {
|
||||
signatures.add(nextObject as PGPSignature)
|
||||
}
|
||||
}
|
||||
|
||||
if (nextObject is PGPSignatureList) {
|
||||
signatures.addAll(nextObject as PGPSignatureList)
|
||||
}
|
||||
|
||||
if (nextObject is PGPSignature) {
|
||||
signatures.add(nextObject as PGPSignature)
|
||||
}
|
||||
pgpIn.close()
|
||||
return signatures.toList()
|
||||
} catch (e: UnsupportedPacketVersionException) {
|
||||
throw PGPException("Unsupported packet version encountered.", e)
|
||||
} catch (e: ClassCastException) {
|
||||
throw PGPException("Unexpected packet encountered.", e)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
throw PGPException("Malformed packet encountered.", e)
|
||||
}
|
||||
|
||||
pgpIn.close()
|
||||
return signatures.toList()
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -247,7 +247,8 @@ class ArmorUtils {
|
|||
.add(OpenPgpFingerprint.of(publicKey).prettyPrint())
|
||||
// Primary / First User ID
|
||||
(primary ?: first)?.let {
|
||||
headerMap.getOrPut(HEADER_COMMENT) { mutableSetOf() }.add(it)
|
||||
headerMap.getOrPut(HEADER_COMMENT) { mutableSetOf() }
|
||||
.add(it.replace("\n", "\\n").replace("\r", "\\r"))
|
||||
}
|
||||
// X-1 further identities
|
||||
when (userIds.size) {
|
||||
|
|
|
@ -11,14 +11,9 @@ import org.bouncycastle.util.Arrays
|
|||
*
|
||||
* @param chars may be null for empty passwords.
|
||||
*/
|
||||
class Passphrase(chars: CharArray?) {
|
||||
class Passphrase(private val chars: CharArray?) {
|
||||
private val lock = Any()
|
||||
private var valid = true
|
||||
private val chars: CharArray?
|
||||
|
||||
init {
|
||||
this.chars = trimWhitespace(chars)
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a copy of the underlying char array. A return value of null represents an empty
|
||||
|
@ -67,6 +62,13 @@ class Passphrase(chars: CharArray?) {
|
|||
|
||||
override fun hashCode(): Int = getChars()?.let { String(it) }.hashCode()
|
||||
|
||||
/**
|
||||
* Return a copy of this [Passphrase], but with whitespace characters trimmed off.
|
||||
*
|
||||
* @return copy with trimmed whitespace
|
||||
*/
|
||||
fun withTrimmedWhitespace(): Passphrase = Passphrase(trimWhitespace(chars))
|
||||
|
||||
companion object {
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
// SPDX-FileCopyrightText: 2025 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.pgpainless.bouncycastle.fuzzing
|
||||
|
||||
import com.code_intelligence.jazzer.api.FuzzedDataProvider
|
||||
import com.code_intelligence.jazzer.junit.DictionaryFile
|
||||
import com.code_intelligence.jazzer.junit.FuzzTest
|
||||
import org.bouncycastle.bcpg.ArmoredInputException
|
||||
import org.bouncycastle.bcpg.UnsupportedPacketVersionException
|
||||
import org.bouncycastle.openpgp.PGPException
|
||||
import org.bouncycastle.openpgp.PGPUtil
|
||||
import org.bouncycastle.openpgp.bc.BcPGPObjectFactory
|
||||
import java.io.EOFException
|
||||
import java.io.IOException
|
||||
|
||||
class PGPObjectFactoryFuzzingTest {
|
||||
|
||||
@FuzzTest
|
||||
@DictionaryFile(resourcePath = "ascii_armor.dict")
|
||||
@DictionaryFile(resourcePath = "openpgp.dict")
|
||||
fun parseFuzzedObjects(provider: FuzzedDataProvider) {
|
||||
val encoding = provider.consumeRemainingAsBytes()
|
||||
|
||||
if (encoding.isEmpty()) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
val decIn = PGPUtil.getDecoderStream(encoding.inputStream())
|
||||
val objFac = BcPGPObjectFactory(decIn)
|
||||
var obj = objFac.nextObject()
|
||||
while (obj != null) {
|
||||
obj = objFac.nextObject()
|
||||
}
|
||||
} catch (e: ArmoredInputException) {
|
||||
return
|
||||
} catch (e: PGPException) {
|
||||
return
|
||||
} catch (e: EOFException) {
|
||||
return
|
||||
} catch (e: IOException) {
|
||||
return
|
||||
} catch (e: UnsupportedPacketVersionException) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
»ЏОхТО---Q(K
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,5 @@
|
|||
-----BEGIN PGP MESSAGÚ-----
|
||||
|
||||
ywtiAAECAwTA/+66vg==
|
||||
=pAS2
|
||||
-----END PGP MESSAGE-----
|
|
@ -0,0 +1,5 @@
|
|||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
ywtiAAECAwTA/+66vg==
|
||||
=pAS2
|
||||
-----END PGP MESSAGE-----
|
|
@ -0,0 +1,39 @@
|
|||
#
|
||||
# AFL Dictionary for OpenPGP (RFC9580)
|
||||
# ------------------------------------------
|
||||
#
|
||||
# Created by Paul Schaub <info@pgpainless.org>
|
||||
|
||||
#
|
||||
# ASCII Armor
|
||||
#
|
||||
BEGIN_PGP_MESSAGE="-----BEGIN PGP MESSAGE-----"
|
||||
END_PGP_MESSAGE="-----END PGP MESSAGE-----"
|
||||
BEGIN_PGP_SIGNATURE="-----BEGIN PGP SIGNATURE-----"
|
||||
END_PGP_SIGNATURE="-----END PGP SIGNATURE-----"
|
||||
BEGIN_PGP_PUBLIC_KEY="-----BEGIN PGP PUBLIC KEY-----"
|
||||
END_PGP_PUBLIC_KEY="-----END PGP PUBLIC KEY-----"
|
||||
BEGIN_PGP_PUBLIC_KEY_BLOCK="-----BEGIN PGP PUBLIC KEY BLOCK-----"
|
||||
END_PGP_PUBLIC_KEY_BLOCK="-----END PGP PUBLIC KEY BLOCK-----"
|
||||
BEGIN_PGP_PRIVATE_KEY="-----BEGIN PGP PRIVATE KEY-----"
|
||||
END_PGP_PRIVATE_KEY="-----END PGP PRIVATE KEY-----"
|
||||
BEGIN_PGP_PRIVATE_KEY_BLOCK="-----BEGIN PGP PRIVATE KEY BLOCK-----"
|
||||
END_PGP_PRIVATE_KEY_BLOCK="-----END PGP PRIVATE KEY BLOCK-----"
|
||||
BEGIN_PGP_SIGNED_MESSAGE="-----BEGIN PGP SIGNED MESSAGE-----"
|
||||
|
||||
HEADER_VERSION="Version"
|
||||
HEADER_COMMENT="Comment"
|
||||
HEADER_HASH="Hash"
|
||||
HEADER_CHARSET="Charset"
|
||||
HASH_SHA224="SHA224"
|
||||
HASH_SHA256="SHA256"
|
||||
HASH_SHA384="SHA384"
|
||||
HASH_SHA512="SHA512"
|
||||
|
||||
PART_BEGIN="BEGIN"
|
||||
PART_PGP="PGP"
|
||||
PART_MESSAGE="MESSAGE"
|
||||
PART_BLOCK="BLOCK"
|
||||
PART_PUBLIC="PUBLIC"
|
||||
PART_PRIVATE="PRIVATE"
|
||||
PART_KEY="KEY"
|
|
@ -0,0 +1,34 @@
|
|||
#
|
||||
# AFL Dictionary for OpenPGP (RFC9580)
|
||||
# ------------------------------------------
|
||||
#
|
||||
# Created by Paul Schaub <info@pgpainless.org>
|
||||
|
||||
#
|
||||
# Packet Type IDs
|
||||
#
|
||||
RESERVED="\x00"
|
||||
PKESK="\x01"
|
||||
SIG="\x02"
|
||||
SKESK="\0x03"
|
||||
OPS="\x04"
|
||||
SECKEY="\x05"
|
||||
PUBKEY="\x06"
|
||||
SECSUBKEY="\x07"
|
||||
COMP="\x08"
|
||||
SED="\x09"
|
||||
MARKER="\x0A"
|
||||
LIT="\x0B"
|
||||
TRUST="\x0C"
|
||||
UID="\x0D"
|
||||
PUBSUBKEY="\x0E"
|
||||
UAT="\x11"
|
||||
SEIPD="\x12"
|
||||
MOD="\x13"
|
||||
RES20="\x14"
|
||||
PADDING="\x15"
|
||||
|
||||
#
|
||||
# Entire Packets
|
||||
#
|
||||
MARKER_PACKET="\xCA\x03\x50\x47\x50"
|
|
@ -18,6 +18,9 @@ dependencies {
|
|||
testImplementation "org.junit.jupiter:junit-jupiter-params:$junitVersion"
|
||||
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion"
|
||||
|
||||
// Jazzer for Fuzzing
|
||||
testImplementation "com.code-intelligence:jazzer-junit:$jazzerVersion"
|
||||
|
||||
// Logging
|
||||
testImplementation "ch.qos.logback:logback-classic:$logbackVersion"
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.pgpainless.util.ArmoredOutputStreamFactory
|
|||
import sop.Ready
|
||||
import sop.exception.SOPGPException
|
||||
import sop.operation.Armor
|
||||
import java.io.IOException
|
||||
|
||||
/** Implementation of the `armor` operation using PGPainless. */
|
||||
class ArmorImpl : Armor {
|
||||
|
@ -26,8 +27,14 @@ class ArmorImpl : Armor {
|
|||
val bufferedOutputStream = BufferedOutputStream(outputStream)
|
||||
|
||||
// Determine the nature of the given data
|
||||
val openPgpIn = OpenPgpInputStream(data)
|
||||
openPgpIn.reset()
|
||||
val openPgpIn = OpenPgpInputStream(data, false).apply {
|
||||
try {
|
||||
inspectBuffer()
|
||||
} catch (e: IOException) {
|
||||
// ignore
|
||||
}
|
||||
reset()
|
||||
}
|
||||
|
||||
if (openPgpIn.isAsciiArmored) {
|
||||
// armoring already-armored data is an idempotent operation
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
package org.pgpainless.sop
|
||||
|
||||
import org.bouncycastle.bcpg.UnsupportedPacketVersionException
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
|
@ -15,6 +16,7 @@ import org.pgpainless.algorithm.SymmetricKeyAlgorithm
|
|||
import org.pgpainless.decryption_verification.ConsumerOptions
|
||||
import org.pgpainless.exception.MalformedOpenPgpMessageException
|
||||
import org.pgpainless.exception.MissingDecryptionMethodException
|
||||
import org.pgpainless.exception.ModificationDetectionException
|
||||
import org.pgpainless.exception.WrongPassphraseException
|
||||
import org.pgpainless.util.Passphrase
|
||||
import sop.DecryptionResult
|
||||
|
@ -23,6 +25,8 @@ import sop.SessionKey
|
|||
import sop.exception.SOPGPException
|
||||
import sop.operation.Decrypt
|
||||
import sop.util.UTF8Util
|
||||
import java.util.zip.ZipException
|
||||
import kotlin.NoSuchElementException
|
||||
|
||||
/** Implementation of the `decrypt` operation using PGPainless. */
|
||||
class DecryptImpl : Decrypt {
|
||||
|
@ -53,15 +57,32 @@ class DecryptImpl : Decrypt {
|
|||
throw SOPGPException.BadData(e)
|
||||
} catch (e: IOException) {
|
||||
throw SOPGPException.BadData(e)
|
||||
} finally {
|
||||
} catch (e: UnsupportedPacketVersionException) {
|
||||
throw SOPGPException.BadData(e)
|
||||
} catch (e: ModificationDetectionException) {
|
||||
throw SOPGPException.BadData(e)
|
||||
}
|
||||
finally {
|
||||
// Forget passphrases after decryption
|
||||
protector.clear()
|
||||
}
|
||||
|
||||
return object : ReadyWithResult<DecryptionResult>() {
|
||||
override fun writeTo(outputStream: OutputStream): DecryptionResult {
|
||||
Streams.pipeAll(decryptionStream, outputStream)
|
||||
decryptionStream.close()
|
||||
try {
|
||||
Streams.pipeAll(decryptionStream, outputStream)
|
||||
decryptionStream.close()
|
||||
} catch (e: MalformedOpenPgpMessageException) {
|
||||
throw SOPGPException.BadData(e)
|
||||
} catch (e: ModificationDetectionException) {
|
||||
throw SOPGPException.BadData(e)
|
||||
} catch (e: ZipException) {
|
||||
throw SOPGPException.BadData(e)
|
||||
} catch (e: IOException) {
|
||||
throw SOPGPException.BadData(e)
|
||||
} catch (e: NoSuchElementException) {
|
||||
throw SOPGPException.BadData(e)
|
||||
}
|
||||
|
||||
val metadata = decryptionStream.metadata
|
||||
if (!metadata.isEncrypted) {
|
||||
|
|
|
@ -29,8 +29,11 @@ class DetachedVerifyImpl : DetachedVerify {
|
|||
override fun data(data: InputStream): List<Verification> {
|
||||
try {
|
||||
val verificationStream =
|
||||
PGPainless.decryptAndOrVerify().onInputStream(data).withOptions(options)
|
||||
|
||||
try {
|
||||
PGPainless.decryptAndOrVerify().onInputStream(data).withOptions(options)
|
||||
} catch (e: RuntimeException) {
|
||||
throw SOPGPException.BadData(e)
|
||||
}
|
||||
Streams.drain(verificationStream)
|
||||
verificationStream.close()
|
||||
|
||||
|
|
|
@ -100,4 +100,14 @@ public class GenerateKeyTest {
|
|||
assertThrows(SOPGPException.UnsupportedProfile.class, () ->
|
||||
sop.generateKey().profile("invalid"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generateKeyWithNewlinesInUserId() throws IOException {
|
||||
byte[] keyBytes = sop.generateKey()
|
||||
.userId("Foo\n\nBar")
|
||||
.generate()
|
||||
.getBytes();
|
||||
|
||||
assertTrue(new String(keyBytes).contains("Foo\\n\\nBar"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
// SPDX-FileCopyrightText: 2025 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.pgpainless.sop.fuzzing;
|
||||
|
||||
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
|
||||
import com.code_intelligence.jazzer.junit.FuzzTest;
|
||||
import org.bouncycastle.util.Arrays;
|
||||
import org.pgpainless.sop.SOPImpl;
|
||||
import sop.SOP;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
|
||||
public class AsciiArmorFuzzTest {
|
||||
|
||||
private final SOP sop = new SOPImpl();
|
||||
|
||||
@FuzzTest(
|
||||
maxDuration = "60s"
|
||||
)
|
||||
public void armorAndDearmorData(FuzzedDataProvider data) throws IOException {
|
||||
byte[] bytes = data.consumeRemainingAsBytes();
|
||||
|
||||
byte[] armored = sop.armor().data(bytes).getBytes();
|
||||
if (Arrays.areEqual(bytes, armored)) {
|
||||
// armoring already armored data is idempotent
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] dearmored = sop.dearmor().data(armored).getBytes();
|
||||
assertArrayEquals(bytes, dearmored, new String(armored));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
// SPDX-FileCopyrightText: 2025 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.pgpainless.sop.fuzzing;
|
||||
|
||||
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
|
||||
import com.code_intelligence.jazzer.junit.FuzzTest;
|
||||
import org.bouncycastle.util.encoders.Hex;
|
||||
import org.bouncycastle.util.io.Streams;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.pgpainless.exception.MissingDecryptionMethodException;
|
||||
import org.pgpainless.exception.ModificationDetectionException;
|
||||
import org.pgpainless.sop.SOPImpl;
|
||||
import sop.SOP;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.operation.Decrypt;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
||||
public class EncryptedMessageFuzzingTest {
|
||||
|
||||
private final SOP sop = new SOPImpl();
|
||||
private final String password = "sw0rdf1sh";
|
||||
private final byte[] data = "Hello, World!\n".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
private static List<byte[]> keys;
|
||||
|
||||
@BeforeAll
|
||||
public static void setup() throws IOException {
|
||||
keys = getKeys();
|
||||
}
|
||||
|
||||
private static List<byte[]> getKeys() throws IOException {
|
||||
List<byte[]> keys = new ArrayList<>();
|
||||
|
||||
String dir = "/org/pgpainless/sop/fuzzing/testKeys";
|
||||
InputStream in = EncryptedMessageFuzzingTest.class.getResourceAsStream(dir);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
|
||||
|
||||
String file;
|
||||
while ((file = reader.readLine()) != null) {
|
||||
if (!file.endsWith(".key.asc")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try(InputStream fIn = EncryptedMessageFuzzingTest.class.getResourceAsStream(dir + "/" + file)) {
|
||||
byte[] b = Streams.readAll(fIn);
|
||||
keys.add(b);
|
||||
}
|
||||
}
|
||||
reader.close();
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
@FuzzTest(
|
||||
maxDuration = "60s"
|
||||
)
|
||||
public void decryptFuzzedMessage(FuzzedDataProvider provider) {
|
||||
byte[] ciphertext = provider.consumeRemainingAsBytes();
|
||||
if (ciphertext.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Decrypt decrypt = sop.decrypt();
|
||||
for (byte[] k : keys) {
|
||||
decrypt.withKey(k);
|
||||
}
|
||||
byte[] decrypted = decrypt.withPassword(password)
|
||||
.ciphertext(ciphertext)
|
||||
.toByteArrayAndResult()
|
||||
.getBytes();
|
||||
|
||||
assertArrayEquals(data, decrypted);
|
||||
} catch (SOPGPException.BadData e) {
|
||||
// expected
|
||||
} catch (SOPGPException.CannotDecrypt e) {
|
||||
// expected
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
// SPDX-FileCopyrightText: 2025 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.pgpainless.sop.fuzzing;
|
||||
|
||||
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
|
||||
import com.code_intelligence.jazzer.junit.FuzzTest;
|
||||
import org.bouncycastle.openpgp.PGPException;
|
||||
import org.bouncycastle.openpgp.api.KeyPassphraseProvider;
|
||||
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||
import org.bouncycastle.openpgp.api.OpenPGPKeyReader;
|
||||
import org.bouncycastle.openpgp.api.exception.KeyPassphraseException;
|
||||
import org.bouncycastle.util.encoders.Hex;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.pgpainless.sop.SOPImpl;
|
||||
import sop.SOP;
|
||||
import sop.exception.SOPGPException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
public class GenerateKeyFuzzTest {
|
||||
|
||||
private final SOP sop = new SOPImpl();
|
||||
|
||||
@FuzzTest(maxDuration = "5m")
|
||||
public void generateKeyWithFuzzedUserId(FuzzedDataProvider provider) throws IOException {
|
||||
String userId = provider.consumeRemainingAsString();
|
||||
|
||||
try {
|
||||
byte[] keyBytes = sop.generateKey()
|
||||
.userId(userId)
|
||||
.generate()
|
||||
.getBytes();
|
||||
|
||||
OpenPGPKey key = new OpenPGPKeyReader().parseKey(keyBytes);
|
||||
assertNotNull(key.getUserId(userId), "Cannot fetch user-id for '" + userId + "' (" + Hex.toHexString(userId.getBytes(StandardCharsets.UTF_8)) + ")\n" + new String(keyBytes));
|
||||
} catch (IllegalArgumentException e) {
|
||||
// expected.
|
||||
}
|
||||
}
|
||||
|
||||
@FuzzTest
|
||||
public void generateKeyWithFuzzedPassphrase(FuzzedDataProvider provider) throws IOException, KeyPassphraseException {
|
||||
byte[] passphrase = provider.consumeRemainingAsBytes();
|
||||
|
||||
try {
|
||||
byte[] keyBytes = sop.generateKey()
|
||||
.withKeyPassword(passphrase)
|
||||
.generate()
|
||||
.getBytes();
|
||||
|
||||
OpenPGPKey key = new OpenPGPKeyReader().parseKey(keyBytes);
|
||||
OpenPGPKey.OpenPGPPrivateKey pk = key.getPrimarySecretKey().unlock(new String(passphrase).toCharArray());
|
||||
assertNotNull(pk, "Got null result unlocking key that was generated with passphrase 0x'" + Hex.toHexString(passphrase) + "'");
|
||||
}
|
||||
catch (SOPGPException.PasswordNotHumanReadable e) {
|
||||
// expected.
|
||||
}
|
||||
catch (PGPException e) {
|
||||
throw new RuntimeException("Cannot unlock key that was generated with passphrase 0x'" + Hex.toHexString(passphrase) + "'", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
// SPDX-FileCopyrightText: 2025 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.pgpainless.sop.fuzzing;
|
||||
|
||||
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
|
||||
import com.code_intelligence.jazzer.junit.FuzzTest;
|
||||
import org.bouncycastle.bcpg.ArmoredInputException;
|
||||
import org.bouncycastle.bcpg.UnsupportedPacketVersionException;
|
||||
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
|
||||
import org.bouncycastle.openpgp.api.OpenPGPKeyReader;
|
||||
import org.pgpainless.sop.SOPImpl;
|
||||
import sop.SOP;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ParseCertFuzzTest {
|
||||
|
||||
private final SOP sop = new SOPImpl();
|
||||
|
||||
@FuzzTest(maxDuration = "30s")
|
||||
public void parseOpenPGPCert(FuzzedDataProvider data) throws IOException {
|
||||
byte[] certEncoding = data.consumeRemainingAsBytes();
|
||||
if (certEncoding.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
OpenPGPCertificate cert = new OpenPGPKeyReader().parseCertificate(certEncoding);
|
||||
}
|
||||
catch (ArmoredInputException e) {
|
||||
// ignore
|
||||
}
|
||||
catch (EOFException e) {
|
||||
// ignore
|
||||
}
|
||||
catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
catch (UnsupportedPacketVersionException e) {
|
||||
// ignore
|
||||
}
|
||||
catch (ClassCastException e) {
|
||||
|
||||
}
|
||||
catch (OutOfMemoryError e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
// SPDX-FileCopyrightText: 2025 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.pgpainless.sop.fuzzing;
|
||||
|
||||
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
|
||||
import com.code_intelligence.jazzer.junit.FuzzTest;
|
||||
import org.bouncycastle.bcpg.UnsupportedPacketVersionException;
|
||||
import org.bouncycastle.openpgp.api.OpenPGPKeyReader;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class PublicKeyPacketFuzzTest {
|
||||
|
||||
private final OpenPGPKeyReader reader = new OpenPGPKeyReader();
|
||||
|
||||
@FuzzTest(maxDuration = "60s")
|
||||
public void parsePublicKeyPacket(FuzzedDataProvider provider) {
|
||||
byte[] encoding = provider.consumeRemainingAsBytes();
|
||||
if (encoding.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
reader.parseCertificate(encoding);
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
} catch (UnsupportedPacketVersionException e) {
|
||||
// ignore
|
||||
} catch (ClassCastException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
// SPDX-FileCopyrightText: 2025 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.pgpainless.sop.fuzzing;
|
||||
|
||||
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
|
||||
import com.code_intelligence.jazzer.junit.FuzzTest;
|
||||
import org.bouncycastle.bcpg.UnsupportedPacketVersionException;
|
||||
import org.bouncycastle.openpgp.api.OpenPGPKeyReader;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class SecretKeyPacketFuzzTest {
|
||||
|
||||
private final OpenPGPKeyReader reader = new OpenPGPKeyReader();
|
||||
|
||||
@FuzzTest(maxDuration = "6ßs")
|
||||
public void parseSecretKeyPacket(FuzzedDataProvider provider)
|
||||
{
|
||||
byte[] encoding = provider.consumeRemainingAsBytes();
|
||||
if (encoding.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
reader.parseKey(encoding);
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
} catch (UnsupportedPacketVersionException e) {
|
||||
// ignore
|
||||
} catch (ClassCastException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,306 @@
|
|||
// SPDX-FileCopyrightText: 2025 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.pgpainless.sop.fuzzing;
|
||||
|
||||
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
|
||||
import com.code_intelligence.jazzer.junit.FuzzTest;
|
||||
import org.pgpainless.sop.SOPImpl;
|
||||
import sop.SOP;
|
||||
import sop.Verification;
|
||||
import sop.exception.SOPGPException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
public class SignatureFuzzTest {
|
||||
|
||||
private final SOP sop = new SOPImpl();
|
||||
private final byte[] data = "Hello, World!\n".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
private final String v4_ed25519 = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
|
||||
"Comment: D7BC FF6B B105 40D9 87F9 CB6E 542D C9F6 FCAE AD63\n" +
|
||||
"Comment: Alice <alice@pgpainless.org>\n" +
|
||||
"\n" +
|
||||
"mDMEaGzu+BYJKwYBBAHaRw8BAQdAlqjB241N44drAJvxa3wx0uRb5bxuVNXrCwPZ\n" +
|
||||
"yf4Qg+O0HEFsaWNlIDxhbGljZUBwZ3BhaW5sZXNzLm9yZz7ClQQTFgoARwWCaGzu\n" +
|
||||
"+AkQVC3J9vyurWMWIQTXvP9rsQVA2Yf5y25ULcn2/K6tYwKeAQKbAQUWAgMBAAQL\n" +
|
||||
"CQgHBRUKCQgLBYkJZgF/ApkBAADVIwEAi599IgoqQbvetYicOt9XobSQKH+4/tB/\n" +
|
||||
"cmHgD7HkGu8A/jYoA0CaYuYNWw8ZYQ8QCUIAkXApm8fO9iyTx0QU1kQMuDMEaGzu\n" +
|
||||
"+BYJKwYBBAHaRw8BAQdA48KEYPTPnV86ycWzAk82aHPF2Fke5cLFsQn7/laFT1DC\n" +
|
||||
"wBUEGBYKAH0Fgmhs7vgCngECmwIFFgIDAQAECwkIBwUVCgkIC18gBBkWCgAGBYJo\n" +
|
||||
"bO74AAoJECL1fW9vQUTUldQBALcsF4e23VatOfew9CXwEiL6P5LMh7E8n/yUVR+j\n" +
|
||||
"NBr9AP0bxSZ1UbdRIrWpg/Itpl9h98gtpT9rdVs02n0+xs5GDAAKCRBULcn2/K6t\n" +
|
||||
"Y4UQAQCG/xpMgjpVNNs3wzHeVB0OCRKXsWkqHQr6xnEDAObdpwD7BD10DpdQDnSa\n" +
|
||||
"HP7CArFQIuA78aIXpaVidfWVMu1mEAm4OARobO74EgorBgEEAZdVAQUBAQdAXgno\n" +
|
||||
"M3Qa9wevqtyAY5MzVz3y6KTYtnfrC/YXG1fc7Q4DAQgHwnUEGBYKAB0Fgmhs7vgC\n" +
|
||||
"ngECmwwFFgIDAQAECwkIBwUVCgkICwAKCRBULcn2/K6tY7GuAP9Kf1Ec1GJmZ99U\n" +
|
||||
"HsgiN60os+6adMLj4G2ASiIbNSDvKgD9F/VLFIb/eN7kJQp3E5C15x5pMMKEI/rj\n" +
|
||||
"wdrKmYH3aAw=\n" +
|
||||
"=4uX6\n" +
|
||||
"-----END PGP PUBLIC KEY BLOCK-----";
|
||||
private static final String v4_rsa4096 = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
|
||||
"Comment: C2C1 DB5E 3AE2 9711 62D9 7BFB 101D 531D 1C69 12A7\n" +
|
||||
"Comment: Alice <alice@pgpainless.org>\n" +
|
||||
"\n" +
|
||||
"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\n" +
|
||||
"XgWruN+wC+b9XY+Rrn+5\n" +
|
||||
"=ppAk\n" +
|
||||
"-----END PGP PUBLIC KEY BLOCK-----";
|
||||
|
||||
private static final String v4_nistP256 = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
|
||||
"Comment: 7A00 864E BC9C 503A 05C7 4687 338C BC25 2B16 66D4\n" +
|
||||
"Comment: Alice <alice@pgpainless.org>\n" +
|
||||
"\n" +
|
||||
"xlIEaG0TDxMIKoZIzj0DAQcCAwRixWErG7QLr7ACFxUGjnVHuy1fzaHArCjhXQdJ\n" +
|
||||
"cFkly6lxXqpth8a6Ef7ww4xicoCBUkMWDcMDmArolc8pzK7ZzRxBbGljZSA8YWxp\n" +
|
||||
"Y2VAcGdwYWlubGVzcy5vcmc+wp8EExMKAFEFgmhtEw8JEDOMvCUrFmbUFqEEegCG\n" +
|
||||
"TrycUDoFx0aHM4y8JSsWZtQCmwEFFQoJCAsFFgIDAQAECwkIBwknCQEJAgkDCAEC\n" +
|
||||
"ngkFiQlmAYACmQEAAAjYAP9/DDAzA0Ykon8ACI6atMQYYnbIU894956akr64mmo9\n" +
|
||||
"FgEAke0o9t/zrH0z1LD7yr3qkW0j+NK2OEy1XIjADrp5wRLOUgRobRMPEwgqhkjO\n" +
|
||||
"PQMBBwIDBAqrl9l6YvdrzOWXO4ZFakQCI22HGw4U806IrjGuYFBwdhnu+lGFVFsD\n" +
|
||||
"CGMXY2ZhslsSNAJNDrxAP+xeAulDaDvCwBgEGBMKAIoFgmhtEw8JEGTDz6W23cHo\n" +
|
||||
"FqEE4bpPaE2vfK5LIsVuZMPPpbbdwegCmwJfIAQZEwoABgWCaG0TDwAKCRBkw8+l\n" +
|
||||
"tt3B6HvEAQDN/84YKO0rDGbVyZEuVrOxeHXTC/8DlhHYx9Am5TZu9wD+NJCIzwzU\n" +
|
||||
"a4fPISDUJRH+vxAHsRSp4rOCod+tgXsq+7wAANrKAP9dyYnyMEfZcts3i/BZo25D\n" +
|
||||
"pqIrfDeZ1ZwP7mMZQ9lmRgEAqKKGBSLnLViyng5Z7Q5BqzW01q7CkLXZZ5IXaNns\n" +
|
||||
"0XTOVgRobRMPEggqhkjOPQMBBwIDBC9IY09+8DOpG9aOK2iY6isENu6TvDClVvug\n" +
|
||||
"SBnnsUdS3fOhVYYfcniboqrV6+BmfpbwptdGyD0yBUwzfL62/QADAQgHwngEGBMK\n" +
|
||||
"ACoFgmhtEw8JEMlGff4yehhJFqEEC15pityd3XNDfeS0yUZ9/jJ6GEkCmwwAAHt4\n" +
|
||||
"AQDG3xESM+ryzFUb8c4ldcb5NQ32eg0L1nFgTQEBHNJFpQEAi5xO1ZM4wEOlzk3e\n" +
|
||||
"SC3qFyx9K6WQBlpY7TNdgqX8aEY=\n" +
|
||||
"=1lGG\n" +
|
||||
"-----END PGP PUBLIC KEY BLOCK-----\n";
|
||||
private static final String v4_nistP384 = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
|
||||
"Comment: C52D CD97 0953 D8A9 3136 509D 20B0 88C6 9BBF 089C\n" +
|
||||
"Comment: Alice <alice@pgpainless.org>\n" +
|
||||
"\n" +
|
||||
"xm8EaG0TIhMFK4EEACIDAwTn7aRgEpefzWD3a9g/h7BA6EOVHxcV93BKE2Zf53kT\n" +
|
||||
"Yvs13YmY1wTDjsYbHTGTMmm46Q+QSphhiWTVyodykqinFnhmmt/R1L4Z3qQWVBWE\n" +
|
||||
"JNyS+swSqPSPQnIEygjqJrPNHEFsaWNlIDxhbGljZUBwZ3BhaW5sZXNzLm9yZz7C\n" +
|
||||
"vwQTEwoAUQWCaG0TIgkQILCIxpu/CJwWoQTFLc2XCVPYqTE2UJ0gsIjGm78InAKb\n" +
|
||||
"AQUVCgkICwUWAgMBAAQLCQgHCScJAQkCCQMIAQKeCQWJCWYBgAKZAQAApfYBgNg1\n" +
|
||||
"Ni0jkkT1TncTslHERidv+teYXTNhtE1Qe4fK9LM/iTruMo3KI5vLQ0yThODrtAF5\n" +
|
||||
"AWzr3j/vhAZ0keXBTFiKj+8L564uGZ/Ab2wQUYVNgyrJ4nIylQqjl5v3AoxaQa8s\n" +
|
||||
"zm8EaG0TIhMFK4EEACIDAwT2Pz19+CkZouSUqvLtDGKdOfiRoAg2TmVEMkjanwyM\n" +
|
||||
"pml7g4XVh0D0WNktvTltHvDepZU4JO5Dse+zC+KlORk6w6KABrC8dujPlO2miFDO\n" +
|
||||
"ziqrZClDgkdeJG0F4I/QIbjCwFgEGBMKAKoFgmhtEyIJEBxvr0D4OkYGFqEEB1Ic\n" +
|
||||
"cXRzT2WMi+p2HG+vQPg6RgYCmwJ/IAQZEwoABgWCaG0TIgAKCRAcb69A+DpGBgnx\n" +
|
||||
"AYDLFfyzoaL02LRlOULvqicJjDuWII4HHQKlWU0bL1CPdVGLizQBPVIrqOE7ne4X\n" +
|
||||
"ofQBf3S4CH2TGJdG6joVa5J22VLXhKFVD9MsO7X+QpLcpvpcdWdZpu8pSEIAQ1ck\n" +
|
||||
"VwJEAgAAzNMBf34fez/WxNFg7autqSXqSRjeQH6EgJeommuCZg90530WnDRQrm53\n" +
|
||||
"a4Ava+p4nW766gGAxzPG8wZ9YiNFWXP80rPaFnVDUvpAzVN6QulNgA9X++PFdnn8\n" +
|
||||
"udhXqbn/tjtmhz4ZznMEaG0TIhIFK4EEACIDAwSyypi9tH1VKoyz+whB1u8Poi9n\n" +
|
||||
"9G5bWBpQwlkqDMz5P7D0To7m2bnif6qjXfBo0e43NLst7XL9YTXKGiHssGWdvBjW\n" +
|
||||
"nUjM9UXWIpuigAEX5Run5Bn/mryfrIL6ocJIrJkDAQkIwpgEGBMKACoFgmhtEyIJ\n" +
|
||||
"EB4h59bAP7IKFqEERagGFBZG9V3Kbwc8HiHn1sA/sgoCmwwAAI91AX4hX/+DJLdN\n" +
|
||||
"jhZXEiY9SX3jyD97VfvZMTokCB7AfPGZ1GIMtaaTgN/fjhlZcQuoQhsBfjUvF5Rr\n" +
|
||||
"S0CgvzBn3v/m72uykFayWZ06cHufSrgkR7UygCjGlVPO5bp4ZoPhW7FUqg==\n" +
|
||||
"=UtdE\n" +
|
||||
"-----END PGP PUBLIC KEY BLOCK-----\n";
|
||||
private static final String v4_nistP521 = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
|
||||
"Comment: E17E 59B5 7DAD 1868 AA48 053F C762 4862 050A 405F\n" +
|
||||
"Comment: Alice <alice@pgpainless.org>\n" +
|
||||
"\n" +
|
||||
"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\n" +
|
||||
"oR99QtE=\n" +
|
||||
"=1kU8\n" +
|
||||
"-----END PGP PUBLIC KEY BLOCK-----\n";
|
||||
private static final String v6_curve25519 = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
|
||||
"Comment: 075CE2AD 721B3A3E 877329F1 24131A25 A43876BC DD09943D\n" +
|
||||
"Comment: B1EB5C73 4E98EFEF\n" +
|
||||
"Comment: Alice <alice@pgpainless.org>\n" +
|
||||
"\n" +
|
||||
"xioGaG0TTxsAAAAgAhlYynX3JdyxowVByJP29cYt7tTRVtMEHzj3ctWRaNvNHEFs\n" +
|
||||
"aWNlIDxhbGljZUBwZ3BhaW5sZXNzLm9yZz7CwAIGExsKAAAAUwWCaG0TTyKhBgdc\n" +
|
||||
"4q1yGzo+h3Mp8SQTGiWkOHa83QmUPbHrXHNOmO/vApsBBRUKCQgLBRYCAwEABAsJ\n" +
|
||||
"CAcJJwkBCQIJAwgBAp4JBYkJZgGAApkBAAAAAD2DIFbG7ai9HSJKlRqtv1c8KTXc\n" +
|
||||
"7PcJeF0wjKcqxrSCp2Gwhd4/CdfHEeDWxE7x0QRuXERQJLPwae1dYITvsBrk7cR4\n" +
|
||||
"DpMe33Kqaj2KuWsPWhU5efaIZ68hxurXPH1eHjpXAc4qBmhtE08bAAAAINBT+USX\n" +
|
||||
"w4Y/WFM6ArUXFrjZAV8+FyUa2aZJps3zZmuiwsB1BhgbCgAAAMYFgmhtE08ioQZB\n" +
|
||||
"a272wKwg9+XBs4b15pDGecNCy5kqOeZzJrWLET546gKbApkgBhkbCgAAACkioQZB\n" +
|
||||
"a272wKwg9+XBs4b15pDGecNCy5kqOeZzJrWLET546gWCaG0TTwAAAABLmSA4FypT\n" +
|
||||
"lEiKE1Jd8isuE3+gXWRZO+/tDkrwsar5dTUFysv0NR+LDOYy/a/HbPCDhEIKjBcY\n" +
|
||||
"qzTP+3R2ZZe2rGkE+77sht2j1YIcBlzm+t3HA8V20iFn4rpWHy0571hVpggAAAAA\n" +
|
||||
"Bt0gnCR4K4AuIH7fZr4b9BVJ3k4kIvdk9X7S25yyjw6JxZH17fluPiJQVCu/m0be\n" +
|
||||
"lj0dfqCHfTPJ2iZl3RLu0e5mBoolbN4JostQ9FzVi9dZ788jYXvnGIUnoBRu57ZO\n" +
|
||||
"n3UAzioGaG0TTxkAAAAgDRJh03RIU+tZWnyRk684h/GqvO7zL8LJFxL/lHEruULC\n" +
|
||||
"mwYYGwoAAAAsBYJobRNPIqEGo8G75Tf7oWt8oa59iQ32S6uKCXrpadeS/Xjdt1iE\n" +
|
||||
"zyECmwwAAAAAQPQgn2hzfU/3y0CkbuuHn0+jdFLJgs8hFpDx0v1cLpiAKvWLBIZI\n" +
|
||||
"sixI3KLQxiqvxZQXCg+/dQoNO1se4XZ/g6KLvGLzJ6BC5MpUfOfJoGc23u68G2K3\n" +
|
||||
"WpYP1EQ/UjACBT4I\n" +
|
||||
"=Uq9u\n" +
|
||||
"-----END PGP PUBLIC KEY BLOCK-----\n";
|
||||
private static final String v6_curve448 = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
|
||||
"Comment: 212F1BC9 7FF7DBF0 B6F18D83 F59BB2BC 075F26C3 2CE5F150\n" +
|
||||
"Comment: 0B770469 11A0A196\n" +
|
||||
"Comment: Alice <alice@pgpainless.org>\n" +
|
||||
"\n" +
|
||||
"xkMGaG0TXxwAAAA5ffh5M4YFiH+SEFbP8SeW7FhJns/56XYfUjk28nejYWQgl4Fd\n" +
|
||||
"vihxLAtryw6iEscMoudI7NsUWC+AzRxBbGljZSA8YWxpY2VAcGdwYWlubGVzcy5v\n" +
|
||||
"cmc+wsA0BhMcCgAAAFMFgmhtE18ioQYhLxvJf/fb8LbxjYP1m7K8B18mwyzl8VAL\n" +
|
||||
"dwRpEaChlgKbAQUVCgkICwUWAgMBAAQLCQgHCScJAQkCCQMIAQKeCQWJCWYBgAKZ\n" +
|
||||
"AQAAAAChXiCvjG1wSHZzZwaVEnfGyMGrhb/l9mjULQFaQmdEgJ33i/iEv6MQYaBS\n" +
|
||||
"nPRCcI9GLjq/kkz957EhvBxeM1K5OHUAhHLy2AY4ReKB/N5Xz3D7pAivqsQzq/DS\n" +
|
||||
"gIKfGQxjEt/QPy7C+qsNNHsss4l2mo3ugdV5mQV4DcBzeHJcz7hMce00HRIVRemw\n" +
|
||||
"JuPhh3gEFN8hAM5DBmhtE18cAAAAOTs6skyf+PcX3A+rsPMjmEGVc1IqJw4xOqoZ\n" +
|
||||
"gPghbYGGqBrYAqzr//xKshyewSMOH5fmGX8aQyoPgMLA2gYYHAoAAAD5BYJobRNf\n" +
|
||||
"IqEGC4EDngLrM73LIg5bZQKYVUAM98vVI86Qq6SE4mUxlxkCmwLACyAGGRwKAAAA\n" +
|
||||
"KSKhBguBA54C6zO9yyIOW2UCmFVADPfL1SPOkKukhOJlMZcZBYJobRNfAAAAAHuS\n" +
|
||||
"IBQQaYywrO5u+n8R7Xcb+WoQ7FtHUmHpW5triJ/tkwfnufiC56CD465EyLJ9g+Mm\n" +
|
||||
"IA+5n03AxeH0Yk7afFBgRw9pQlPb2/1P66iexPV7445sjJ9jCK2NTJaAd/H6R+CW\n" +
|
||||
"iCYl5VCtkoryXNN4yad6OVt+TrEQHCF4vRUpAUAF30EO8LUuUsB0F3D0D0aDglBi\n" +
|
||||
"tiAAAAAAAAR4ILw9d7lfCTtaOpBEr0YHo8kPzVcBxdDbUfo9UAqScZhwCbSVrANI\n" +
|
||||
"CJw614Ss3WhTuV+l465zwccF2xh0D+VAue1AwnwnQzp518zFqTXJmOUcs7YuPWyU\n" +
|
||||
"iQEA/tc+jUg9XL6EQ/5UYMhfj7nO/b8uZuD2KYPtc2e8X3mk1is05fhB9JSOOGib\n" +
|
||||
"d6su8g3Pv+HQGx4AzkIGaG0TXxoAAAA4WAHz84E3zX2mIoVBETPWdzvumbTqFiUM\n" +
|
||||
"uiI96b6XmWi21G8F/BdpWs1Gg347x7PbVWfq9SD7t6TCwA0GGBwKAAAALAWCaG0T\n" +
|
||||
"XyKhBq9bQBVplmkyzKWaEqIweNfJ85ls16CfR2rNXYYs2vDyApsMAAAAAPQUIKzs\n" +
|
||||
"xWkiYn0kM7FsHGMlMGET0wrdKg4F45dGCHDUHeUZSusp5Zs7okmY6HP4tePSMuMq\n" +
|
||||
"9whjVqimGN6Xx0ybErP/ku6jExwN6QtYohZempWCZXv3SJteGI8ADuVKmcNT9MBN\n" +
|
||||
"ic3vixr3vjkXsuUwBQDGDb7SRfA7DGh4mXxAaB5gUwQC+wSIG6D7gIP2Hz0fVj4A\n" +
|
||||
"=9WFq\n" +
|
||||
"-----END PGP PUBLIC KEY BLOCK-----\n";
|
||||
|
||||
@FuzzTest(
|
||||
maxDuration = "60s"
|
||||
)
|
||||
public void verifyFuzzedSig(FuzzedDataProvider provider) throws IOException {
|
||||
byte[] sig = provider.consumeRemainingAsBytes();
|
||||
if (sig.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
List<Verification> verifs = sop.verify()
|
||||
.cert(v4_ed25519.getBytes(StandardCharsets.UTF_8))
|
||||
.cert(v4_rsa4096.getBytes(StandardCharsets.UTF_8))
|
||||
.cert(v4_nistP256.getBytes(StandardCharsets.UTF_8))
|
||||
.cert(v4_nistP384.getBytes(StandardCharsets.UTF_8))
|
||||
.cert(v4_nistP521.getBytes(StandardCharsets.UTF_8))
|
||||
.cert(v6_curve25519.getBytes(StandardCharsets.UTF_8))
|
||||
.cert(v6_curve448.getBytes(StandardCharsets.UTF_8))
|
||||
.signatures(sig)
|
||||
.data(data);
|
||||
|
||||
if (verifs.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Verification v : verifs) {
|
||||
System.out.println(v.toString());
|
||||
}
|
||||
} catch (SOPGPException.NoSignature e) {
|
||||
// ignore
|
||||
} catch (SOPGPException.BadData e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
|
||||
xVgEaGfc0BYJKwYBBAHaRw8BAQdATOdV6wukmqSavJGlnqhkk0fvPzhNnzvp3sv5
|
||||
gMq3BzUAAP9jcz6ydPE5rdNwUAxxOVn2stxGntC6mm0m9RI+1hYhbRCQzRxBbGlj
|
||||
ZSA8YWxpY2VAcGdwYWlubGVzcy5vcmc+wp8EExYKAFEFgmhn3NAJEEjYL/TjDku0
|
||||
FqEE3bruvdTZy1Xd+RNsSNgv9OMOS7QCmwEFFQoJCAsFFgIDAQAECwkIBwknCQEJ
|
||||
AgkDCAECngkFiQlmAYACmQEAAKq4AQC98RHIFbs5pyeWpKimjP3LFZ6rroorBcMc
|
||||
izPAPqXEjQD+N5DSn/TJeKeld6KCB69W2KSj4BBdPvabLG6cRq+/8AbHWARoZ9zQ
|
||||
FgkrBgEEAdpHDwEBB0A9Q+9+bvKSI1voDq+rb7yKjCVKVG4jO1qj/wTPF5PkSQAB
|
||||
AIP7XckHeFuJ8qnp2hU2keb+Xzo+8ZlR57mj37uAuQUzEibCwBgEGBYKAIoFgmhn
|
||||
3NAJEERXJjHxSbsAFqEEFQlMncw3fOJ/EBmfRFcmMfFJuwACmwJfIAQZFgoABgWC
|
||||
aGfc0AAKCRBEVyYx8Um7AEw5AQDkSgGU1E6rmHO2DTj1jNXkD8k3rnyxxjP66RLi
|
||||
whLVYwD9FwWQ5kXwM2qFheWbuMN7sghEt+SDQHc7tgwgnWppEwAAAGNHAQDM4ncO
|
||||
o05rjfFVAaTFJ26Ixm8MK2HnGl+fQT73wyDJEgD/U/g+b7bppnSF4scuZMUSA9xQ
|
||||
oyK3b5J5uNqfj+mxpgDHXQRoZ9zQEgorBgEEAZdVAQUBAQdAdEmUSz3XlPFa+u8I
|
||||
0hJu+RAuJO0Sj64+ZlvawGsQhFcDAQgHAAD/Y78qz+fyfkEa6DjwhhLdZzKWJlII
|
||||
KL1oW1vsNE8SVEAPGMJ4BBgWCgAqBYJoZ9zQCRBqhz9va/rd1hahBOfnmVV9LWWf
|
||||
y/UZPWqHP29r+t3WApsMAADktwD/TSz5ZK5WFaaLSzpIwyA2U9XvgUvGD+5bSban
|
||||
XsYU9LwA/1NWshgcBfDMRoboZGPwWIikfRUOatGph4IRj/5UZmIJ
|
||||
=n5sh
|
||||
-----END PGP PRIVATE KEY BLOCK-----
|
|
@ -0,0 +1,21 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Comment: DDBA EEBD D4D9 CB55 DDF9 136C 48D8 2FF4 E30E 4BB4
|
||||
Comment: Alice <alice@pgpainless.org>
|
||||
|
||||
xjMEaGfc0BYJKwYBBAHaRw8BAQdATOdV6wukmqSavJGlnqhkk0fvPzhNnzvp3sv5
|
||||
gMq3BzXNHEFsaWNlIDxhbGljZUBwZ3BhaW5sZXNzLm9yZz7CnwQTFgoAUQWCaGfc
|
||||
0AkQSNgv9OMOS7QWoQTduu691NnLVd35E2xI2C/04w5LtAKbAQUVCgkICwUWAgMB
|
||||
AAQLCQgHCScJAQkCCQMIAQKeCQWJCWYBgAKZAQAAqrgBAL3xEcgVuzmnJ5akqKaM
|
||||
/csVnquuiisFwxyLM8A+pcSNAP43kNKf9Ml4p6V3ooIHr1bYpKPgEF0+9pssbpxG
|
||||
r7/wBs4zBGhn3NAWCSsGAQQB2kcPAQEHQD1D735u8pIjW+gOr6tvvIqMJUpUbiM7
|
||||
WqP/BM8Xk+RJwsAYBBgWCgCKBYJoZ9zQCRBEVyYx8Um7ABahBBUJTJ3MN3zifxAZ
|
||||
n0RXJjHxSbsAApsCXyAEGRYKAAYFgmhn3NAACgkQRFcmMfFJuwBMOQEA5EoBlNRO
|
||||
q5hztg049YzV5A/JN658scYz+ukS4sIS1WMA/RcFkOZF8DNqhYXlm7jDe7IIRLfk
|
||||
g0B3O7YMIJ1qaRMAAABjRwEAzOJ3DqNOa43xVQGkxSduiMZvDCth5xpfn0E+98Mg
|
||||
yRIA/1P4Pm+26aZ0heLHLmTFEgPcUKMit2+Sebjan4/psaYAzjgEaGfc0BIKKwYB
|
||||
BAGXVQEFAQEHQHRJlEs915TxWvrvCNISbvkQLiTtEo+uPmZb2sBrEIRXAwEIB8J4
|
||||
BBgWCgAqBYJoZ9zQCRBqhz9va/rd1hahBOfnmVV9LWWfy/UZPWqHP29r+t3WApsM
|
||||
AADktwD/TSz5ZK5WFaaLSzpIwyA2U9XvgUvGD+5bSbanXsYU9LwA/1NWshgcBfDM
|
||||
RoboZGPwWIikfRUOatGph4IRj/5UZmIJ
|
||||
=hJD/
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
Binary file not shown.
|
@ -0,0 +1,21 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Comment: DDBA EEBD D4D9 CB55 DDF9 136C 48D8 2FF4 E30E 4BB4
|
||||
Comment: Alice <alice@pgpainless.org>
|
||||
|
||||
xjMEaGfc0BYJKwYBBAHaRw8BAQdATOdV6wukmqSavJGlnqhkk0fvPzhNnzvp3sv5
|
||||
gMq3BzXNHEFsaWNlIDxhbGljZUBwZ3BhaW5sZXNzLm9yZz7CnwQTFgoAUQWCaGfc
|
||||
0AkQSNgv9OMOS7QWoQTduu691NnLVd35E2xI2C/04w5LtAKbAQUVCgkICwUWAgMB
|
||||
AAQLCQgHCScJAQkCCQMIAQKeCQWJCWYBgAKZAQAAqrgBAL3xEcgVuzmnJ5akqKaM
|
||||
/csVnquuiisFwxyLM8A+pcSNAP43kNKf9Ml4p6V3ooIHr1bYpKPgEF0+9pssbpxG
|
||||
r7/wBs4zBGhn3NAWCSsGAQQB2kcPAQEHQD1D735u8pIjW+gOr6tvvIqMJUpUbiM7
|
||||
WqP/BM8Xk+RJwsAYBBgWCgCKBYJoZ9zQCRBEVyYx8Um7ABahBBUJTJ3MN3zifxAZ
|
||||
n0RXJjHxSbsAApsCXyAEGRYKAAYFgmhn3NAACgkQRFcmMfFJuwBMOQEA5EoBlNRO
|
||||
q5hztg049YzV5A/JN658scYz+ukS4sIS1WMA/RcFkOZF8DNqhYXlm7jDe7IIRLfk
|
||||
g0B3O7YMIJ1qaRMAAABjRwEAzOJ3DqNOa43xVQGkxSduiMZvDCth5xpfn0E+98Mg
|
||||
yRIA/1P4Pm+26aZ0heLHLmTFEgPcUKMit2+Sebjan4/psaYAzjgEaGfc0BIKKwYB
|
||||
BAGXVQEFAQEHQHRJlEs915TxWvrvCNISbvkQLiTtEo+uPmZb2sBrEIRXAwEIB8J4
|
||||
BBgWCgAqBYJoZ9zQCRBqhz9va/rd1hahBOfnmVV9LWWfy/UZPWqHP29r+t3WApsM
|
||||
AADktwD/TSz5ZK5WFaaLSzpIwyA2U9XvgUvGD+5bSbanXsYU9LwA/1NWshgcBfDM
|
||||
RoboZGPwWIikfRUOatGph4IRj/5UZmIJ
|
||||
=hJD/
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
|
@ -0,0 +1 @@
|
|||
Hello, World!
|
|
@ -0,0 +1,5 @@
|
|||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
SGVsbG8gV29ybGQK
|
||||
=1hzE
|
||||
-----END PGP MESSAGE-----
|
|
@ -0,0 +1,9 @@
|
|||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
wWwGFQTn55lVfS1ln8v1GT1qhz9va/rd1hIBB0CK2xMAGPBhSAztl26xmFEMGg3a
|
||||
oKnwCwphhU7yshVCOTAY4zKszTvvn3CxMV8HbNQ0jr61kp9H9bwGDz8w6Nz/WQrn
|
||||
S4QPVvXsLOIZd9L/KKbSWgIJAQOoAMCSkjp146L+E1uYItfRk/K4dupbQWX+jAHp
|
||||
6MJvIi4rzyht7qt2C0RPPFDImzCTR9V1Ry/BCa3w4E3x3CBpFVyEy9N8mizUEJU6
|
||||
TPRvAFqekyQpjg==
|
||||
=EL9J
|
||||
-----END PGP MESSAGE-----
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,7 @@
|
|||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
wnUEABYKACcFgmhn3d8JEERXJjHxSbsAFqEEFQlMncw3fOJ/EBmfRFcmMfFJuwAA
|
||||
AOgXAQCAXxXslQv4i9C4kAW9aOJCj7Cn7ZkMsyQvw9vTSW5R6QD9FmncQ64oOGEL
|
||||
gtX9s6OFb7Bd1UEbfL7G3QS2wg0QHQc=
|
||||
=o0Xk
|
||||
-----END PGP SIGNATURE-----
|
|
@ -0,0 +1,5 @@
|
|||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
SGVsbG8gV29ybGQK
|
||||
=1hzA
|
||||
-----END PGP MESSAGE-----
|
|
@ -0,0 +1,4 @@
|
|||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
SGVsbG8gV29ybGQK
|
||||
-----END PGP MESSAGE-----
|
|
@ -0,0 +1 @@
|
|||
ця
▌╞ёН<`╠!J]В╣,й╔┤tс╤р@:╗0▒╩sdЁ╠÷╒Е$X⌠²Зщ,©bcЁv7НG┤┐█5iU▀v·X▌VнЕьЭ▌ыщ
8Р
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
ця
▌╞ёН<`╠!J]В╣,й╔┤tс╤рС▌VнЕьЭ▌ыщ
3
|
|
@ -0,0 +1 @@
|
|||
ÃÑ
ޝ£î<`±!J]÷µ,Ê¥‡tÓ¶Ò@:¨0‘»sd³±Ÿ¢å$X“<58>úÝ,·bc³v7îG‡ƒ<1B>5iUIìæ¦l 'Š,¿½£w—Ñ/3OÖc
|
|
@ -0,0 +1 @@
|
|||
ця
▌╞ёН<`╠!J]В╣,й╔┤tс╤р@:╗0▒╩sdЁ╠÷╒Е$X⌠²Зщ,╥bcЁv7НG┤┐█5iU▀v·X▌VнЕьЭ▌ыщ
8Р
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
ÃÑóæqP\Ù±!J]÷µ,Ê¥‡tÓ¶Ò@:¨0‘.sd³±Ÿ¢å$X“<58>úÝ,·bc«v7îG‡
|
|
@ -0,0 +1 @@
|
|||
ÃÑ
ޝ£î<`±!J]÷µ,Ê¥‡tÓ¶Ò@:¨0‘»sd³±Ÿ¢å$X“<58>úÝ,·&c³v7îG‡ƒ<1B>5iUIìæ¦l 'Š,¿½£w—Ñ/3OÖc
|
|
@ -0,0 +1 @@
|
|||
ÃÑ
ޝ£î<`±!J]÷µ,Ê¥‡tÓ¶Ò@:¨0‘»sd³±Ÿ¢å$X“<58>ú݇tÓ¶Ò@:¨0‘»sd³±Ÿ¢å$X“<58>úÝ,¿½£w—Ñ/7OÖc
|
|
@ -0,0 +1 @@
|
|||
Á^VÝđ]ĚVż!â7<C3A2>~ĘQm‡'ŇçĂŮä\ĎÍkQýZ#ż80ż80Žo¤]FžZs†TAO¬<4F>•"rüyb“züăgî<67>ĎüÝńĎNś"ź<˙ ˇŇ@îi
8ň%mđZ±ˇf´h:"#:Š
|
|
@ -0,0 +1 @@
|
|||
Á^VÝđ]ĚVż@¦!â7<C3A2>~ĘQm‡'ŇçĂŮä@ĎÍkQýZ#ż80Žo¤]FžZs†TAO¬<4F>•"rüyb“züăgî<67>ńĎüÝĎNś"ź<˙ ˇŇ@îi
8ň%mđZ±ˇf´h:"#:Š
|
|
@ -0,0 +1 @@
|
|||
ÃÑ
ޝ£î<`±!J]÷µ,Ê¥‡tÓ¶Ò@:¨0‘»sd³±Ÿ¢å$X“<58>úÝ,·bc³v7îG‡ƒ<1B>ÿÿÿÿÿÿÿÿ 'Š,¿½£w—Ñ/3OÖc
|
|
@ -0,0 +1 @@
|
|||
ÃÑ
ޝ£î<`±!J]÷µ,Ê¥‡tÓ¶Ò@:¨0‘»sd³±Ÿ¢å$X“<58>úÝ,·bc³v7îG‡ƒ<1B>5iUI*ìæ¦l 'Š,¿½£w—Ñ/Ò@¥‡c
|
|
@ -0,0 +1 @@
|
|||
ця
▌╞ёН<`╠!J]В╣,й╔┤tс╤рС▌VнЕьЭ▌ыщ
3Р@:╗0▒╩sd╖С▌VнЕьЭ▌ыщ
3Р
|
|
@ -0,0 +1 @@
|
|||
ÃÑ
ޝ£î<`±!J]÷µ,Ê¥‡tÓ¶Ò@:¨0‘»sd³±Ÿ¢å$X“<58>úÝ,·bc³v7îG‡ƒ<1B>5¬<35>•"rüybŠ,¿½£w—Ñ/3OÖc
|
|
@ -0,0 +1 @@
|
|||
Á^VÝđ]ĚVż@¦!â7<C3A2>~ĘQm‡'ŇçĂŮä\ĎÍkQýZ#ż80Žo¤]FžZs†TAO¬<4F>•"rüyb“züăgî<67>ńĎüÝĎNś"ź<˙ ˇŇ@îikR’yşŞŕ,`Ŕ9<>(<28>dd%‹vžXŽVÎĺŘüŽŮÝ
8ň%mđZ±ˇf´h:"#:Š
|
|
@ -0,0 +1 @@
|
|||
ÃÑ
ޝ£î<`±!J]÷µ,Ê¥‡tÓ¶Ò@:¨0‘»sd³±Ÿ¢å$X“<58>ú—Ñ/7OÖc
|
|
@ -0,0 +1 @@
|
|||
Á^VÝđ]ĚVż@¦!â7<C3A2>~ĘQm‡'ŇçĂŮä\ĎÍkQýZ#ż80Žo¤]FžZs†TAO¬<4F>•"rüyb“züăgî<67>ńĎüÝĎNś"ź<˙ ˇŇ@iîkR’yşŞŕ,`Ŕ9<>(<28>dd%‹vžXŽVÎĺŘüŽŮÝ
8ň%mđZ±ˇf´h:"#:Š
|
|
@ -0,0 +1,8 @@
|
|||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
wV4DVhfd8F3MVr8SAQdAphsh4jeDfsoaUW2HJ9Lnw9nkDlzPzWsDC1ES/Vojvzgw
|
||||
jm/CpF1GA55aHXOGVEFPrIGVInIc/HliApN6/ONn7oPxz/zdz06cCCKfPBT/CQeh
|
||||
0kABae4Oa1KSeboCqhXgLGDAGhY5gSiYZBdkJYt2nlgOjlYHzuXY/I7ZDAjdDSA4
|
||||
GPIWJW0F8FqxoWa0aDoiIzqK
|
||||
=BXMn
|
||||
-----END PGP MESSAGE-----
|
|
@ -0,0 +1 @@
|
|||
ÃÑ
ޝ£î<`±!J]÷µ,Ê¥‡tÓ¶Ò@:¨0‘»sd³±Ÿ¢å$X“<58>úÝ,·bc³v7îG‡ƒ<1B>5iUIìæ¦l 'Š,¿½£w—Ñ/7OÖc
|
|
@ -0,0 +1,7 @@
|
|||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
wx4EBwMC0Q0Zjq+j7jxgsSFKXRX3CLUsyqWHDHTTDLbSQAE6qDCRu3Nks7Gfohbl
|
||||
JFiTnfrdHiwMArdiY7N2NwHuR4eDARuNNWlVSezmpmwFICeKLL+9o3eX0S83Fk8S
|
||||
1mM=
|
||||
=N/kL
|
||||
-----END PGP MESSAGE-----
|
Binary file not shown.
|
@ -0,0 +1,17 @@
|
|||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
wcFMA6SJex80gcWaAQ/8C4tRTyBQhmtBERKS0VHc/nb7cS2dbr7XSMpvk53Fj9Se
|
||||
qWgJloepmkFea0OGy+ectRwGFWj3Aj0bdChRbi3ipfX1QXdhAbdBTb3+GlfPkr6X
|
||||
WfywYYMbKB2eoDpSw5sdgvN3TKOlSL/8snGtrkZYy3VoS6xZ9RRhrmz9KEw6q2vc
|
||||
APz4ldOOMmYTgDT8o8gjqqc+7hK2Ac+jdIq6Jtmrs49yxONU92UL8ormJbGpOFVB
|
||||
+tAUIgFHib/0qc6ch5KhcXJUCT/jt7cn+BoLk4U2ns9mBxwnYJ+vnxzFrJxgySY0
|
||||
TOOGxmuPQOCMZfOxme0HUROxu5xiSM6PRLWilL6YRyw3IXekfVGNeFHnsF/Rxx7c
|
||||
3v9cvnsDQpGE9qRsgtxcvCGJkKnPNFRQPA/vpXB/GhrBtGLSpTMKHxbHyPsb10ZP
|
||||
IN5aR37QqN7LLu1vlFdjz37CL0ib4pHEH1FvpsaY9l+nzv3eltF2U7aFHHdGQd7E
|
||||
mmihSbdzRTYys2yX2P/mYVZo2j/GciGUtd9ucllouTRlBEL1IEgBSeSuaH9xYscN
|
||||
u4rTDgezBS8WF9/0T8elmeTjk2RRojRGKt98HFl/YU8V/MLTDS/c7Hl6U9FIpGrM
|
||||
QIFzunmf4npwrgAEH+spzl6qVYygEqDHTt1K05eEO4ZxoHBwTd9dTgRtj/b35lHS
|
||||
QAHc37MCFlJVNma77AinyVs17c2kgUP+gV5Liwt07kSRca7hzYJgYDvQi2hf08pP
|
||||
abmx0ChGu+JRUAvkFD7k120=
|
||||
=CaPm
|
||||
-----END PGP MESSAGE-----
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
/
|
|
@ -0,0 +1 @@
|
|||
]
M
|
|
@ -0,0 +1 @@
|
|||
牋<EFBFBD>
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD><EFBFBD>
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
]
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD>
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
]
|
||||
]
|
|
@ -0,0 +1,21 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Comment: DDBA EEBD D4D9 CB55 DDF9 136C 48D8 2FF4 E30E 4BB4
|
||||
Comment: Alice <alice@pgpainless.org>
|
||||
|
||||
xjMEaGfc0BYJKwYBBAHaRw8BAQdATOdV6wukmqSavJGlnqhkk0fvPzhNnzvp3sv5
|
||||
gMq3BzXNHEFsaWNlIDxhbGljZUBwZ3BhaW5sZXNzLm9yZz7CnwQTFgoAUQWCaGfc
|
||||
0AkQSNgv9OMOS7QWoQTduu691NnLVd35E2xI2C/04w5LtAKbAQUVCgkICwUWAgMB
|
||||
AAQLCQgHCScJAQkCCQMIAQKeCQWJCWYBgAKZAQAAqrgBAL3xEcgVuzmnJ5akqKaM
|
||||
/csVnquuiisFwxyLM8A+pcSNAP43kNKf9Ml4p6V3ooIHr1bYpKPgEF0+9pssbpxG
|
||||
r7/wBs4zBGhn3NAWCSsGAQQB2kcPAQEHQD1D735u8pIjW+gOr6tvvIqMJUpUbiM7
|
||||
WqP/BM8Xk+RJwsAYBBgWCgCKBYJoZ9zQCRBEVyYx8Um7ABahBBUJTJ3MN3zifxAZ
|
||||
n0RXJjHxSbsAApsCXyAEGRYKAAYFgmhn3NAACgkQRFcmMfFJuwBMOQEA5EoBlNRO
|
||||
q5hztg049YzV5A/JN658scYz+ukS4sIS1WMA/RcFkOZF8DNqhYXlm7jDe7IIRLfk
|
||||
g0B3O7YMIJ1qaRMAAABjRwEAzOJ3DqNOa43xVQGkxSduiMZvDCth5xpfn0E+98Mg
|
||||
yRIA/1P4Pm+26aZ0heLHLmTFEgPcUKMit2+Sebjan4/psaYAzjgEaGfc0BIKKwYB
|
||||
BAGXVQEFAQEHQHRJlEs915TxWvrvCNISbvkQLiTtEo+uPmZb2sBrEIRXAwEIB8J4
|
||||
BBgWCgAqBYJoZ9zQCRBqhz9va/rd1hahBOfnmVV9LWWfy/UZPWqHP29r+t3WApsM
|
||||
AADktwD/TSz5ZK5WFaaLSzpIwyA2U9XvgUvGD+5bSbanXsYU9LwA/1NWshgcBfDM
|
||||
RoboZGPwWIikfRUOatGph4IRj/5UZmIJ
|
||||
=hJD/
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
|
@ -0,0 +1,21 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Comment: DDBA EEBD D4D9 CB55 DDF9 136C 48D8 2FF4 E30E 4BB4
|
||||
Comment: Alice <alice@pgpainless.org>
|
||||
|
||||
xjMEaGfc0BYJKwYBBAHaRw8BAQdATOdV6wukmqSavJGlnqhkk0fvPzhNnzvp3sv5
|
||||
gMq3BzXNHEFsaWNlIDxhbGljZUBwZ3BhaW5sZXNzLm9yZz7CnwQTFgoAUQWCaGfc
|
||||
0AkQSNgv9OMOS7QWoQTduu691NnLVd35E2xI2C/04w5LtAKbAQUVCgkICwUWAgMB
|
||||
AAQLCQgHCScJAQkCCQMIAQKeCQWJCWYBgAKZAQAAqrgBAL3xEcgVuzmnJ5akqKaM
|
||||
/csVnquuiisFwxyLM8A+pcSNAP43kNKf9Ml4p6V3ooIHr1bYpKPgEF0+9pssbpxG
|
||||
r7/wBs4zBGhn3NAWCSsGAQQB2kcPAQEHQD1D735u8pIjW+gOr6tvvIqMJUpUbiM7
|
||||
WqP/BM8Xk+RJwsAYBBgWCgCKBYJoZ9zQCRBEVyYx8Um7ABahBBUJTJ3MN3zifxAZ
|
||||
n0RXJjHxSbsAApsCXyAEGRYKAAYFgmhn3NAACgkQRFcmMfFJuwBMOQEA5EoBlNRO
|
||||
q5hztg049YzV5A/JN658scYz+ukS4sIS1WMA/RcFkOZF8DNqhYXlm7jDe7IIRLfk
|
||||
g0B3O7YMIJ1qaRMAAABjRwEAzOJ3DqNOa43xVQGkxSduiMZvDCth5xpfn0E+98Mg
|
||||
yRIA/1P4Pm+26aZ0heLHLmTFEgPcUKMit2+Sebjan4/psaYAzjgEaGfc0BIKKwYB
|
||||
BAGXVQEFAQEHQHRJlEs915TxWvrvCNISbvkQLiTtEo+uPmZb2sBrEIRXAwEIB8J4
|
||||
BBgWCgAqBYJoZ9zQCRBqhz9va/rd1hahBOfnmVV9LWWfy/UZPWqHP29r+t3WApsM
|
||||
AADktwD/TSz5ZK5WFaaLSzpIwyA2U9XvgUvGD+5bSbanXsYU9LwA/1NWshgcBfDM
|
||||
RoboZGPwWIikfRUOatGph4IRj/5UZmIJ
|
||||
=hJD/
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
Ζ&hp‡xπΥ‰ ΗΊ›Σπ"µϋ^<5E><11>Έhκεeh„(ΐύ
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
фVhp┤*├Hн=$И■;а*вnх╣(У╧²cчЩy▐╨╝НЭ4,▒sU;хТь эй#!┘прA╩gДjL< ▐B▌7?≥
|
Binary file not shown.
|
@ -0,0 +1,2 @@
|
|||
ÆRhp‡*†HÎ=™-ä $öí5?»<0C>¡¥xÄH4—ÅÌt?“Ïè’%<25>[sTpXiý›ý
|
||||
8ãG:I‚)I/a¥¦"‡ÌyA9
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
<EFBFBD><03>vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue