From 6d4f37b1546b0f525ba97496e6130c5f0cc4b11f Mon Sep 17 00:00:00 2001 From: David Hedberg Date: Sat, 20 Feb 2021 14:27:55 +0100 Subject: [PATCH] Don't hash the data to sign when using EDDSA --- .../NfcSyncPGPContentSignerBuilder.java | 58 +++++++++++++++++++ .../keychain/pgp/CanonicalizedSecretKey.java | 4 +- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/OpenKeychain/src/main/java/org/bouncycastle/openpgp/operator/jcajce/NfcSyncPGPContentSignerBuilder.java b/OpenKeychain/src/main/java/org/bouncycastle/openpgp/operator/jcajce/NfcSyncPGPContentSignerBuilder.java index e38e70c21..95580d07a 100644 --- a/OpenKeychain/src/main/java/org/bouncycastle/openpgp/operator/jcajce/NfcSyncPGPContentSignerBuilder.java +++ b/OpenKeychain/src/main/java/org/bouncycastle/openpgp/operator/jcajce/NfcSyncPGPContentSignerBuilder.java @@ -7,12 +7,14 @@ package org.bouncycastle.openpgp.operator.jcajce; +import org.bouncycastle.bcpg.PublicKeyAlgorithmTags; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPPrivateKey; import org.bouncycastle.openpgp.operator.PGPContentSigner; import org.bouncycastle.openpgp.operator.PGPContentSignerBuilder; import org.bouncycastle.openpgp.operator.PGPDigestCalculator; +import java.io.ByteArrayOutputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.security.Provider; @@ -93,6 +95,10 @@ public class NfcSyncPGPContentSignerBuilder public PGPContentSigner build(final int signatureType, final long keyID) throws PGPException { + if (keyAlgorithm == PublicKeyAlgorithmTags.EDDSA) { + return buildEdDSASigner(signatureType, keyID); + } + final PGPDigestCalculator digestCalculator = digestCalculatorProviderBuilder.build().get(hashAlgorithm); return new PGPContentSigner() @@ -139,4 +145,56 @@ public class NfcSyncPGPContentSignerBuilder } }; } + + public PGPContentSigner buildEdDSASigner(final int signatureType, final long keyID) + throws PGPException + { + final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + return new PGPContentSigner() + { + public int getType() + { + return signatureType; + } + + public int getHashAlgorithm() + { + return hashAlgorithm; + } + + public int getKeyAlgorithm() + { + return keyAlgorithm; + } + + public long getKeyID() + { + return keyID; + } + + public OutputStream getOutputStream() + { + return outputStream; + } + + public byte[] getSignature() { + byte[] rawData = outputStream.toByteArray(); + + ByteBuffer buf = ByteBuffer.wrap(rawData); + if (signedHashes.containsKey(buf)) { + return (byte[]) signedHashes.get(buf); + } + // catch this when signatureGenerator.generate() is executed and divert to card, + // when doing the operation again reuse creationTimestamp (this will be hashed) + throw new NfcInteractionNeeded(rawData, getHashAlgorithm()); + } + + public byte[] getDigest() + { + return outputStream.toByteArray(); + } + }; + + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java index 697e5da7d..6ee583e8c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java @@ -255,7 +255,9 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey { private PGPContentSignerBuilder getAuthenticationContentSignerBuilder(int hashAlgorithm, Map signedHashes) { - if (getAlgorithm() == PublicKeyAlgorithmTags.EDDSA) { + if ( + getAlgorithm() == PublicKeyAlgorithmTags.EDDSA + && mPrivateKeyState != PRIVATE_KEY_STATE_DIVERT_TO_CARD) { // content signer feeding the input directly into the signature engine, // since EdDSA hashes the input anyway return new EdDsaAuthenticationContentSignerBuilder(