integrate EdDSAAuthenticationSigner into default signer using enablePreHash parameter

This commit is contained in:
Dominik Schürmann 2021-04-29 17:51:39 +02:00
parent 8c576682e1
commit f8724d3f42
3 changed files with 38 additions and 79 deletions

View File

@ -7,7 +7,6 @@
package org.bouncycastle.openpgp.operator.jcajce; package org.bouncycastle.openpgp.operator.jcajce;
import org.bouncycastle.bcpg.PublicKeyAlgorithmTags;
import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPrivateKey; import org.bouncycastle.openpgp.PGPPrivateKey;
import org.bouncycastle.openpgp.operator.PGPContentSigner; import org.bouncycastle.openpgp.operator.PGPContentSigner;
@ -31,10 +30,10 @@ public class NfcSyncPGPContentSignerBuilder
implements PGPContentSignerBuilder implements PGPContentSignerBuilder
{ {
private JcaPGPDigestCalculatorProviderBuilder digestCalculatorProviderBuilder = new JcaPGPDigestCalculatorProviderBuilder(); private JcaPGPDigestCalculatorProviderBuilder digestCalculatorProviderBuilder = new JcaPGPDigestCalculatorProviderBuilder();
private boolean enablePreHash;
private int hashAlgorithm; private int hashAlgorithm;
private int keyAlgorithm; private int keyAlgorithm;
private long keyID; private long keyID;
private boolean isEdDsaAuthenticationSignature = false;
private Map signedHashes; private Map signedHashes;
@ -51,11 +50,12 @@ public class NfcSyncPGPContentSignerBuilder
} }
} }
public NfcSyncPGPContentSignerBuilder(int keyAlgorithm, int hashAlgorithm, long keyID, Map signedHashes) public NfcSyncPGPContentSignerBuilder(int keyAlgorithm, long keyID, boolean enablePreHash, int hashAlgorithm, Map signedHashes)
{ {
this.keyAlgorithm = keyAlgorithm; this.keyAlgorithm = keyAlgorithm;
this.hashAlgorithm = hashAlgorithm;
this.keyID = keyID; this.keyID = keyID;
this.enablePreHash = enablePreHash;
this.hashAlgorithm = hashAlgorithm;
this.signedHashes = signedHashes; this.signedHashes = signedHashes;
} }
@ -87,13 +87,6 @@ public class NfcSyncPGPContentSignerBuilder
return this; return this;
} }
public NfcSyncPGPContentSignerBuilder configureForEdDsaAuthenticationSignature()
{
isEdDsaAuthenticationSignature = true;
return this;
}
public PGPContentSigner build(final int signatureType, PGPPrivateKey privateKey) public PGPContentSigner build(final int signatureType, PGPPrivateKey privateKey)
throws PGPException { throws PGPException {
// NOTE: privateKey is null in this case! // NOTE: privateKey is null in this case!
@ -103,64 +96,21 @@ public class NfcSyncPGPContentSignerBuilder
public PGPContentSigner build(final int signatureType, final long keyID) public PGPContentSigner build(final int signatureType, final long keyID)
throws PGPException throws PGPException
{ {
if (isEdDsaAuthenticationSignature) {
return buildEdDSAAuthenticationSigner(signatureType, keyID); final PGPDigestCalculator digestCalculator;
final OutputStream outputStream;
if (enablePreHash) {
digestCalculator = digestCalculatorProviderBuilder.build().get(hashAlgorithm);
outputStream = digestCalculator.getOutputStream();
} else {
digestCalculator = null;
outputStream = new ByteArrayOutputStream();
} }
final PGPDigestCalculator digestCalculator = digestCalculatorProviderBuilder.build().get(hashAlgorithm);
return new PGPContentSigner() return new PGPContentSigner()
{ {
public int getType() private byte[] digest;
{
return signatureType;
}
public int getHashAlgorithm()
{
return hashAlgorithm;
}
public int getKeyAlgorithm()
{
return keyAlgorithm;
}
public long getKeyID()
{
return keyID;
}
public OutputStream getOutputStream()
{
return digestCalculator.getOutputStream();
}
public byte[] getSignature() {
byte[] digest = digestCalculator.getDigest();
ByteBuffer buf = ByteBuffer.wrap(digest);
if (signedHashes.containsKey(buf)) {
return (byte[]) signedHashes.get(buf);
}
// catch this when signatureGenerator.generate() is executed and divert digest to card,
// when doing the operation again reuse creationTimestamp (this will be hashed)
throw new NfcInteractionNeeded(digest, getHashAlgorithm());
}
public byte[] getDigest()
{
return digestCalculator.getDigest();
}
};
}
public PGPContentSigner buildEdDSAAuthenticationSigner(final int signatureType, final long keyID)
throws PGPException
{
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
return new PGPContentSigner()
{
public int getType() public int getType()
{ {
return signatureType; return signatureType;
@ -187,22 +137,31 @@ public class NfcSyncPGPContentSignerBuilder
} }
public byte[] getSignature() { public byte[] getSignature() {
byte[] rawData = outputStream.toByteArray(); byte[] digest;
if (enablePreHash) {
ByteBuffer buf = ByteBuffer.wrap(rawData); digest = digestCalculator.getDigest();
} else {
digest = ((ByteArrayOutputStream) getOutputStream()).toByteArray();
}
ByteBuffer buf = ByteBuffer.wrap(digest);
if (signedHashes.containsKey(buf)) { if (signedHashes.containsKey(buf)) {
return (byte[]) signedHashes.get(buf); return (byte[]) signedHashes.get(buf);
} }
// catch this when signatureGenerator.generate() is executed and divert to card, // catch this when signatureGenerator.generate() is executed and divert digest to card,
// when doing the operation again reuse creationTimestamp (this will be hashed) // when doing the operation again reuse creationTimestamp (this will be hashed)
throw new NfcInteractionNeeded(rawData, getHashAlgorithm()); throw new NfcInteractionNeeded(digest, getHashAlgorithm());
} }
public byte[] getDigest() public byte[] getDigest()
{ {
return outputStream.toByteArray(); if (enablePreHash) {
digest = digestCalculator.getDigest();
} else {
digest = ((ByteArrayOutputStream) getOutputStream()).toByteArray();
}
return digest;
} }
}; };
} }
} }

View File

@ -223,8 +223,8 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
if (mPrivateKeyState == PRIVATE_KEY_STATE_DIVERT_TO_CARD) { if (mPrivateKeyState == PRIVATE_KEY_STATE_DIVERT_TO_CARD) {
// use synchronous "NFC based" SignerBuilder // use synchronous "NFC based" SignerBuilder
return new NfcSyncPGPContentSignerBuilder( return new NfcSyncPGPContentSignerBuilder(
mSecretKey.getPublicKey().getAlgorithm(), hashAlgo, mSecretKey.getPublicKey().getAlgorithm(), mSecretKey.getKeyID(),
mSecretKey.getKeyID(), signedHashes) true, hashAlgo, signedHashes)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
} else { } else {
// content signer based on signing key algorithm and chosen hash algorithm // content signer based on signing key algorithm and chosen hash algorithm
@ -257,12 +257,11 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
byte[]> signedHashes) { byte[]> signedHashes) {
if (getAlgorithm() == PublicKeyAlgorithmTags.EDDSA) { if (getAlgorithm() == PublicKeyAlgorithmTags.EDDSA) {
// content signer feeding the input directly into the signature engine, // content signer feeding the input directly into the signature engine,
// since EdDSA hashes the input anyway // no pre-hashing for EdDSA!
if (mPrivateKeyState == PRIVATE_KEY_STATE_DIVERT_TO_CARD) { if (mPrivateKeyState == PRIVATE_KEY_STATE_DIVERT_TO_CARD) {
return new NfcSyncPGPContentSignerBuilder( return new NfcSyncPGPContentSignerBuilder(
mSecretKey.getPublicKey().getAlgorithm(), hashAlgorithm, mSecretKey.getPublicKey().getAlgorithm(), mSecretKey.getKeyID(),
mSecretKey.getKeyID(), signedHashes) false, hashAlgorithm, signedHashes)
.configureForEdDsaAuthenticationSignature()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
} else { } else {
return new EdDsaAuthenticationContentSignerBuilder( return new EdDsaAuthenticationContentSignerBuilder(

View File

@ -1511,8 +1511,9 @@ public class PgpKeyOperation {
if (divertToCard) { if (divertToCard) {
// use synchronous "NFC based" SignerBuilder // use synchronous "NFC based" SignerBuilder
builder = new NfcSyncPGPContentSignerBuilder( builder = new NfcSyncPGPContentSignerBuilder(
pKey.getAlgorithm(), PgpSecurityConstants.SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO, pKey.getAlgorithm(), pKey.getKeyID(),
pKey.getKeyID(), cryptoInput.getCryptoData()) true, PgpSecurityConstants.SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO,
cryptoInput.getCryptoData())
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
} else { } else {
// content signer based on signing key algorithm and chosen hash algorithm // content signer based on signing key algorithm and chosen hash algorithm