validateSignatureLength(Algorithm algorithm, int l
return error;
}
+ public static void setEd25519Factory(Factory factory) {
+ ed25519Factory = factory;
+ }
+
+ public static void setSECP256R1Factory(Factory factory) {
+ secp256r1Factory = factory;
+ }
+
public abstract Algorithm getAlgorithm();
public abstract boolean verify(byte[] data, byte[] signature)
diff --git a/src/main/java/org/eclipse/biscuit/crypto/SECP256R1KeyPair.java b/src/main/java/org/eclipse/biscuit/crypto/SECP256R1KeyPair.java
index 8c032c32..f8821320 100644
--- a/src/main/java/org/eclipse/biscuit/crypto/SECP256R1KeyPair.java
+++ b/src/main/java/org/eclipse/biscuit/crypto/SECP256R1KeyPair.java
@@ -5,12 +5,11 @@
package org.eclipse.biscuit.crypto;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
+import java.io.IOException;
import java.security.SecureRandom;
-import java.security.Security;
-import java.security.Signature;
-import java.security.SignatureException;
+import org.bouncycastle.crypto.digests.SHA256Digest;
+import org.bouncycastle.crypto.signers.ECDSASigner;
+import org.bouncycastle.crypto.signers.StandardDSAEncoding;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.ECNamedCurveTable;
@@ -19,6 +18,7 @@
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.util.BigIntegers;
+import org.eclipse.biscuit.error.Error;
import org.eclipse.biscuit.token.builder.Utils;
@SuppressWarnings("checkstyle:AbbreviationAsWordInName")
@@ -31,15 +31,14 @@ final class SECP256R1KeyPair extends KeyPair {
private final BCECPrivateKey privateKey;
private final BCECPublicKey publicKey;
- static {
- Security.addProvider(new BouncyCastleProvider());
- }
-
static final String ALGORITHM = "ECDSA";
static final String CURVE = "secp256r1";
static final ECNamedCurveParameterSpec SECP256R1 = ECNamedCurveTable.getParameterSpec(CURVE);
- SECP256R1KeyPair(byte[] bytes) {
+ SECP256R1KeyPair(byte[] bytes) throws Error.FormatError.InvalidKeySize {
+ if (bytes.length != BUFFER_SIZE) {
+ throw new Error.FormatError.InvalidKeySize(bytes.length);
+ }
var privateKeySpec = new ECPrivateKeySpec(BigIntegers.fromUnsignedByteArray(bytes), SECP256R1);
var privateKey =
new BCECPrivateKey(ALGORITHM, privateKeySpec, BouncyCastleProvider.CONFIGURATION);
@@ -68,18 +67,22 @@ final class SECP256R1KeyPair extends KeyPair {
this.publicKey = publicKey;
}
- static Signature getSignature() throws NoSuchAlgorithmException {
- return Signature.getInstance(
- "SHA256withECDSA", Security.getProvider(BouncyCastleProvider.PROVIDER_NAME));
- }
-
@Override
- public byte[] sign(byte[] data)
- throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
- Signature sgr = getSignature();
- sgr.initSign(privateKey);
- sgr.update(data);
- return sgr.sign();
+ public byte[] sign(byte[] data) {
+ var digest = new SHA256Digest();
+ digest.update(data, 0, data.length);
+ var hash = new byte[digest.getDigestSize()];
+ digest.doFinal(hash, 0);
+
+ var signer = new ECDSASigner();
+ signer.init(true, privateKey.engineGetKeyParameters());
+ var sig = signer.generateSignature(hash);
+
+ try {
+ return StandardDSAEncoding.INSTANCE.encode(signer.getOrder(), sig[0], sig[1]);
+ } catch (IOException e) {
+ throw new IllegalStateException(e.toString());
+ }
}
@Override
diff --git a/src/main/java/org/eclipse/biscuit/crypto/SECP256R1PublicKey.java b/src/main/java/org/eclipse/biscuit/crypto/SECP256R1PublicKey.java
index 370a3c93..5199eab7 100644
--- a/src/main/java/org/eclipse/biscuit/crypto/SECP256R1PublicKey.java
+++ b/src/main/java/org/eclipse/biscuit/crypto/SECP256R1PublicKey.java
@@ -6,21 +6,37 @@
package org.eclipse.biscuit.crypto;
import static org.eclipse.biscuit.crypto.SECP256R1KeyPair.CURVE;
-import static org.eclipse.biscuit.crypto.SECP256R1KeyPair.getSignature;
import biscuit.format.schema.Schema.PublicKey.Algorithm;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.SignatureException;
+import java.io.IOException;
+import java.math.BigInteger;
import java.util.Arrays;
+import org.bouncycastle.asn1.sec.SECNamedCurves;
+import org.bouncycastle.asn1.x9.X9ECParameters;
+import org.bouncycastle.crypto.digests.SHA256Digest;
+import org.bouncycastle.crypto.params.ECDomainParameters;
+import org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import org.bouncycastle.crypto.signers.ECDSASigner;
+import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
+import org.bouncycastle.crypto.signers.StandardDSAEncoding;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
+import org.bouncycastle.math.ec.ECPoint;
+import org.eclipse.biscuit.error.Error;
@SuppressWarnings("checkstyle:AbbreviationAsWordInName")
class SECP256R1PublicKey extends PublicKey {
+ private static final X9ECParameters x9ECParameters = SECNamedCurves.getByName("secp256r1");
+ private static final ECDomainParameters domainParameters =
+ new ECDomainParameters(
+ x9ECParameters.getCurve(),
+ x9ECParameters.getG(),
+ x9ECParameters.getN(),
+ x9ECParameters.getH());
+
private final BCECPublicKey publicKey;
SECP256R1PublicKey(BCECPublicKey publicKey) {
@@ -28,9 +44,15 @@ class SECP256R1PublicKey extends PublicKey {
this.publicKey = publicKey;
}
- static SECP256R1PublicKey loadSECP256R1(byte[] data) {
+ static SECP256R1PublicKey loadSECP256R1(byte[] data) throws Error.FormatError.InvalidKey {
var params = ECNamedCurveTable.getParameterSpec(CURVE);
- var spec = new ECPublicKeySpec(params.getCurve().decodePoint(data), params);
+ ECPoint ecPoint;
+ try {
+ ecPoint = params.getCurve().decodePoint(data);
+ } catch (IllegalArgumentException e) {
+ throw new Error.FormatError.InvalidKey(e.getMessage());
+ }
+ var spec = new ECPublicKeySpec(ecPoint, params);
return new SECP256R1PublicKey(
new BCECPublicKey(SECP256R1KeyPair.ALGORITHM, spec, BouncyCastleProvider.CONFIGURATION));
}
@@ -69,11 +91,22 @@ public Algorithm getAlgorithm() {
}
@Override
- public boolean verify(byte[] data, byte[] signature)
- throws InvalidKeyException, SignatureException, NoSuchAlgorithmException {
- var sgr = getSignature();
- sgr.initVerify(this.publicKey);
- sgr.update(data);
- return sgr.verify(signature);
+ public boolean verify(byte[] data, byte[] signature) {
+ var digest = new SHA256Digest();
+ digest.update(data, 0, data.length);
+ var hash = new byte[digest.getDigestSize()];
+ digest.doFinal(hash, 0);
+
+ var signer = new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest()));
+ signer.init(false, new ECPublicKeyParameters(publicKey.getQ(), domainParameters));
+
+ BigInteger[] sig;
+ try {
+ sig = StandardDSAEncoding.INSTANCE.decode(signer.getOrder(), signature);
+ } catch (IOException e) {
+ throw new IllegalStateException(e.toString());
+ }
+
+ return signer.verifySignature(hash, sig[0], sig[1]);
}
}
diff --git a/src/main/java/org/eclipse/biscuit/error/Error.java b/src/main/java/org/eclipse/biscuit/error/Error.java
index 8830b9b8..76bad6e0 100644
--- a/src/main/java/org/eclipse/biscuit/error/Error.java
+++ b/src/main/java/org/eclipse/biscuit/error/Error.java
@@ -401,6 +401,82 @@ public JsonElement toJson() {
return FormatError.jsonWrapper(jo);
}
}
+
+ public static final class InvalidKeySize extends FormatError {
+ private final int size;
+
+ public InvalidKeySize(int size) {
+ this.size = size;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ InvalidKeySize iss = (InvalidKeySize) o;
+
+ return size == iss.size;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(size);
+ }
+
+ @Override
+ public String toString() {
+ return "InvalidKeySize{" + "size=" + size + '}';
+ }
+
+ @Override
+ public JsonElement toJson() {
+ JsonObject jo = new JsonObject();
+ jo.add("InvalidKeySize", new JsonPrimitive(size));
+ return FormatError.jsonWrapper(jo);
+ }
+ }
+
+ public static final class InvalidKey extends FormatError {
+ private final String err;
+
+ public InvalidKey(String e) {
+ this.err = e;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ InvalidKey other = (InvalidKey) o;
+ return err.equals(other.err);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(err);
+ }
+
+ @Override
+ public String toString() {
+ return "Err(Format(InvalidKey(\"" + this.err + "\"))";
+ }
+
+ @Override
+ public JsonElement toJson() {
+ JsonObject jo = new JsonObject();
+ jo.addProperty("InvalidKey", this.err);
+ return FormatError.jsonWrapper(jo);
+ }
+ }
}
public static final class InvalidAuthorityIndex extends Error {
diff --git a/src/main/java/org/eclipse/biscuit/token/ThirdPartyBlockContents.java b/src/main/java/org/eclipse/biscuit/token/ThirdPartyBlockContents.java
index af34dec6..cc76e3c4 100644
--- a/src/main/java/org/eclipse/biscuit/token/ThirdPartyBlockContents.java
+++ b/src/main/java/org/eclipse/biscuit/token/ThirdPartyBlockContents.java
@@ -39,7 +39,7 @@ public Schema.ThirdPartyBlockContents serialize() throws Error.FormatError.Seria
}
public static ThirdPartyBlockContents deserialize(Schema.ThirdPartyBlockContents b)
- throws Error.FormatError.DeserializationError {
+ throws Error.FormatError {
byte[] payload = b.getPayload().toByteArray();
byte[] signature = b.getExternalSignature().getSignature().toByteArray();
PublicKey publicKey = PublicKey.deserialize(b.getExternalSignature().getPublicKey());
@@ -48,7 +48,7 @@ public static ThirdPartyBlockContents deserialize(Schema.ThirdPartyBlockContents
}
public static ThirdPartyBlockContents fromBytes(byte[] slice)
- throws InvalidProtocolBufferException, Error.FormatError.DeserializationError {
+ throws InvalidProtocolBufferException, Error.FormatError {
return ThirdPartyBlockContents.deserialize(Schema.ThirdPartyBlockContents.parseFrom(slice));
}
diff --git a/src/main/java/org/eclipse/biscuit/token/builder/parser/Parser.java b/src/main/java/org/eclipse/biscuit/token/builder/parser/Parser.java
index 43febdde..9a2eaa83 100644
--- a/src/main/java/org/eclipse/biscuit/token/builder/parser/Parser.java
+++ b/src/main/java/org/eclipse/biscuit/token/builder/parser/Parser.java
@@ -41,8 +41,8 @@ private Parser() {}
* If one succeeds it returns Right(Block) else it returns a Map[lineNumber, List[Error]]
*
* @param s datalog string to parse
- * @return Either