Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
3eb959f
Checkstyle: blocks: AvoidNestedBlocks correction
Korbik Feb 20, 2025
0338de6
Checkstyle: blocks: LeftCurly fix
Korbik Feb 20, 2025
6458a69
Checkstyle: design: FinalClass fix
Korbik Feb 20, 2025
205dcc5
Checkstyle: naming: ConstantName fix
Korbik Feb 20, 2025
7345c1d
Checkstyle: naming: LocalFinalVariableName fix
Korbik Feb 20, 2025
a196c81
Checkstyle: naming switch to contants
Korbik Feb 20, 2025
15f118b
Checkstyle: naming: MemberName
Korbik Feb 20, 2025
5b5b539
Checkstyle: naming: ParameterName fix
Korbik Feb 20, 2025
9fe3973
Checkstyle: naming: LocalVariableName
Korbik Feb 20, 2025
c0d57fe
Checkstyle: naming: MethodName
Korbik Feb 20, 2025
5303c18
Checkstyle: design: HideUtilityClassConstructor
Korbik Feb 20, 2025
015b79d
Checkstyle: imports: UnusedImports
Korbik Feb 20, 2025
a250696
Checkstyle: imports: AvoidStarImport
Korbik Feb 20, 2025
c7e1d62
Checkstyle: misc: NewlineAtEndOfFile
Korbik Feb 20, 2025
8cdc1c1
Checkstyle: modifier: RedundantModifier
Korbik Feb 20, 2025
bd9943c
Checkstyle: design: DesignForExtension
Korbik Feb 22, 2025
a930f4b
Attributes
Korbik Mar 2, 2025
99620bd
Checkstyle: modifier: ModifierOrder
Korbik Mar 2, 2025
0ce34dc
Checkstyle: design: VisibilityModifier
Korbik Mar 2, 2025
995f291
Checkstyle: coding: MissingSwitchDefault
Korbik Mar 2, 2025
0e26dc2
Checkstyle: whitespace cleanup
Korbik Mar 2, 2025
007f1ff
Checkstyle: whitespace: EmptyForIteratorPad
Korbik Mar 2, 2025
85e7691
Checkstyle: whitespace: OperatorWrap
Korbik Mar 2, 2025
6d821c7
Checkstyle: whitespace: WhitespaceAfter
Korbik Mar 2, 2025
c669048
Checkstyle: whitespace
Korbik Mar 2, 2025
405b54a
Checkstyle: blocks: NeedBraces
Korbik Mar 2, 2025
ad20f5c
Spotless Google Format application
Korbik Mar 2, 2025
6d8670d
Checkstyle: DistanceVariable Token
Korbik Mar 4, 2025
90b6756
Checkstyle: DistanteVariable Scope:getPublicKey
Korbik Mar 4, 2025
a95555b
Checkstyle: DistanceVariable LogicError
Korbik Mar 4, 2025
450c010
Checkstyle: DistanceVariable Authorizer
Korbik Mar 4, 2025
2e07758
Checkstyle: DistanceVariable without Biscuit and Block
Korbik Mar 4, 2025
1719c64
Checkstyle: VariableDeclarationUsageDistance
Korbik Mar 4, 2025
2b8ab02
Checkstyle: naming: MethodName
Korbik Mar 3, 2025
fb3c0b4
Checkstyle: naming: LambdaParameterName
Korbik Mar 3, 2025
5f0495e
Checkstyle: coding: ConstructorsDeclarationGrouping
Korbik Mar 4, 2025
5ae94c4
Checkstyle: coding: VariableDeclarationUsageDistance
Korbik Mar 4, 2025
56a505e
Checkstyle: regexp: RegexpSinglelineJava
Korbik Mar 4, 2025
1c495ab
Checkstyle: naming: LambdaParameterName
Korbik Mar 4, 2025
63eae7d
Checkstyle: naming: LocalVariableName
Korbik Mar 4, 2025
a2c0cb4
Checkstyle: naming: MemberName
Korbik Mar 4, 2025
0573d34
Fix compilation errors
Korbik Mar 4, 2025
c683d60
Test: apply the google rules
Korbik Mar 11, 2025
98e468d
Review Feedback
Korbik Mar 11, 2025
b4ab936
Java: facts(), context(), etc.
Korbik Mar 18, 2025
99ae668
SymbolTable symbolTable
Korbik Mar 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,33 +1,47 @@
package org.biscuitsec.biscuit.crypto;

import org.biscuitsec.biscuit.token.format.ExternalSignature;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Optional;
import org.biscuitsec.biscuit.token.format.ExternalSignature;

public final class BlockSignatureBuffer {
public static final int HEADER_SIZE = 4;

private BlockSignatureBuffer() {}

public class BlockSignatureBuffer {
public static byte[] getBufferSignature(PublicKey nextPubKey, byte[] data) {
return getBufferSignature(nextPubKey, data, Optional.empty());
}
public static byte[] getBufferSignature(PublicKey nextPubKey, byte[] data) {
return getBufferSignature(nextPubKey, data, Optional.empty());
}

public static byte[] getBufferSignature(PublicKey nextPubKey, byte[] data, Optional<ExternalSignature> externalSignature) {
var buffer = ByteBuffer.allocate(4 + data.length + nextPubKey.toBytes().length + externalSignature.map((a) -> a.signature.length).orElse(0)).order(ByteOrder.LITTLE_ENDIAN);
buffer.put(data);
externalSignature.ifPresent(signature -> buffer.put(signature.signature));
buffer.putInt(nextPubKey.algorithm.getNumber());
buffer.put(nextPubKey.toBytes());
buffer.flip();
return buffer.array();
}
public static byte[] getBufferSignature(
PublicKey nextPubKey, byte[] data, Optional<ExternalSignature> externalSignature) {
var buffer =
ByteBuffer.allocate(
HEADER_SIZE
+ data.length
+ nextPubKey.toBytes().length
+ externalSignature.map((a) -> a.getSignature().length).orElse(0))
.order(ByteOrder.LITTLE_ENDIAN);
buffer.put(data);
externalSignature.ifPresent(signature -> buffer.put(signature.getSignature()));
buffer.putInt(nextPubKey.getAlgorithm().getNumber());
buffer.put(nextPubKey.toBytes());
buffer.flip();
return buffer.array();
}

public static byte[] getBufferSealedSignature(PublicKey nextPubKey, byte[] data, byte[] blockSignature) {
var buffer = ByteBuffer.allocate(4 + data.length + nextPubKey.toBytes().length + blockSignature.length).order(ByteOrder.LITTLE_ENDIAN);
buffer.put(data);
buffer.putInt(nextPubKey.algorithm.getNumber());
buffer.put(nextPubKey.toBytes());
buffer.put(blockSignature);
buffer.flip();
return buffer.array();
}
public static byte[] getBufferSealedSignature(
PublicKey nextPubKey, byte[] data, byte[] blockSignature) {
var buffer =
ByteBuffer.allocate(
HEADER_SIZE + data.length + nextPubKey.toBytes().length + blockSignature.length)
.order(ByteOrder.LITTLE_ENDIAN);
buffer.put(data);
buffer.putInt(nextPubKey.getAlgorithm().getNumber());
buffer.put(nextPubKey.toBytes());
buffer.put(blockSignature);
buffer.flip();
return buffer.array();
}
}
117 changes: 59 additions & 58 deletions src/main/java/org/biscuitsec/biscuit/crypto/Ed25519KeyPair.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
package org.biscuitsec.biscuit.crypto;

import biscuit.format.schema.Schema;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
import net.i2p.crypto.eddsa.EdDSAEngine;
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
import net.i2p.crypto.eddsa.EdDSAPublicKey;
Expand All @@ -10,80 +16,75 @@
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
import org.biscuitsec.biscuit.token.builder.Utils;

import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;

final class Ed25519KeyPair extends KeyPair {
private static final int BUFFER_SIZE = 32;

static final int SIGNATURE_LENGTH = 64;

private final EdDSAPrivateKey privateKey;
private final EdDSAPublicKey publicKey;
public static final int SIGNATURE_LENGTH = 64;

private static final EdDSANamedCurveSpec ed25519 = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519);
private final EdDSAPrivateKey privateKey;
private final EdDSAPublicKey publicKey;

public Ed25519KeyPair(byte[] bytes) {
EdDSAPrivateKeySpec privKeySpec = new EdDSAPrivateKeySpec(bytes, ed25519);
EdDSAPrivateKey privKey = new EdDSAPrivateKey(privKeySpec);
private static final EdDSANamedCurveSpec ED_25519 =
EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519);

EdDSAPublicKeySpec pubKeySpec = new EdDSAPublicKeySpec(privKey.getA(), ed25519);
EdDSAPublicKey pubKey = new EdDSAPublicKey(pubKeySpec);
Ed25519KeyPair(byte[] bytes) {
EdDSAPrivateKeySpec privKeySpec = new EdDSAPrivateKeySpec(bytes, ED_25519);
EdDSAPrivateKey privKey = new EdDSAPrivateKey(privKeySpec);

this.privateKey = privKey;
this.publicKey = pubKey;
}
EdDSAPublicKeySpec pubKeySpec = new EdDSAPublicKeySpec(privKey.getA(), ED_25519);
EdDSAPublicKey pubKey = new EdDSAPublicKey(pubKeySpec);

public Ed25519KeyPair(SecureRandom rng) {
byte[] b = new byte[32];
rng.nextBytes(b);
this.privateKey = privKey;
this.publicKey = pubKey;
}

EdDSAPrivateKeySpec privKeySpec = new EdDSAPrivateKeySpec(b, ed25519);
EdDSAPrivateKey privKey = new EdDSAPrivateKey(privKeySpec);
Ed25519KeyPair(SecureRandom rng) {
byte[] b = new byte[BUFFER_SIZE];
rng.nextBytes(b);

EdDSAPublicKeySpec pubKeySpec = new EdDSAPublicKeySpec(privKey.getA(), ed25519);
EdDSAPublicKey pubKey = new EdDSAPublicKey(pubKeySpec);
EdDSAPrivateKeySpec privKeySpec = new EdDSAPrivateKeySpec(b, ED_25519);
EdDSAPrivateKey privKey = new EdDSAPrivateKey(privKeySpec);

this.privateKey = privKey;
this.publicKey = pubKey;
}
EdDSAPublicKeySpec pubKeySpec = new EdDSAPublicKeySpec(privKey.getA(), ED_25519);
EdDSAPublicKey pubKey = new EdDSAPublicKey(pubKeySpec);

public Ed25519KeyPair(String hex) {
this(Utils.hexStringToByteArray(hex));
}
this.privateKey = privKey;
this.publicKey = pubKey;
}

public static java.security.PublicKey decode(byte[] data) {
return new EdDSAPublicKey(new EdDSAPublicKeySpec(data, ed25519));
}
Ed25519KeyPair(String hex) {
this(Utils.hexStringToByteArray(hex));
}

public static Signature getSignature() throws NoSuchAlgorithmException {
return new EdDSAEngine(MessageDigest.getInstance(ed25519.getHashAlgorithm()));
}
public static java.security.PublicKey decode(byte[] data) {
return new EdDSAPublicKey(new EdDSAPublicKeySpec(data, ED_25519));
}

@Override
public byte[] sign(byte[] data) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
Signature sgr = KeyPair.generateSignature(Schema.PublicKey.Algorithm.Ed25519);
sgr.initSign(privateKey);
sgr.update(data);
return sgr.sign();
}
public static Signature getSignature() throws NoSuchAlgorithmException {
return new EdDSAEngine(MessageDigest.getInstance(ED_25519.getHashAlgorithm()));
}

@Override
public byte[] toBytes() {
return privateKey.getSeed();
}
@Override
public byte[] sign(byte[] data)
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
Signature sgr = KeyPair.generateSignature(Schema.PublicKey.Algorithm.Ed25519);
sgr.initSign(privateKey);
sgr.update(data);
return sgr.sign();
}

@Override
public String toHex() {
return Utils.byteArrayToHexString(toBytes());
}
@Override
public byte[] toBytes() {
return privateKey.getSeed();
}

@Override
public PublicKey public_key() {
return new PublicKey(Schema.PublicKey.Algorithm.Ed25519, this.publicKey);
}
@Override
public String toHex() {
return Utils.byteArrayToHexString(toBytes());
}

@Override
public PublicKey getPublicKey() {
return new PublicKey(Schema.PublicKey.Algorithm.Ed25519, this.publicKey);
}
}
7 changes: 3 additions & 4 deletions src/main/java/org/biscuitsec/biscuit/crypto/KeyDelegate.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

import io.vavr.control.Option;


/**
* Used to find the key associated with a key id
*
* When the root key is changed, it might happen that multiple root keys are in use at the same time.
* Tokens can carry a root key id, that can be used to indicate which key will verify it.
* <p>When the root key is changed, it might happen that multiple root keys are in use at the same
* time. Tokens can carry a root key id, that can be used to indicate which key will verify it.
*/
public interface KeyDelegate {
public Option<PublicKey> root_key(Option<Integer> key_id);
Option<PublicKey> getRootKey(Option<Integer> keyId);
}
89 changes: 43 additions & 46 deletions src/main/java/org/biscuitsec/biscuit/crypto/KeyPair.java
Original file line number Diff line number Diff line change
@@ -1,69 +1,66 @@
package org.biscuitsec.biscuit.crypto;


import biscuit.format.schema.Schema.PublicKey.Algorithm;
import net.i2p.crypto.eddsa.Utils;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
import net.i2p.crypto.eddsa.Utils;

/**
* Private and public key.
*/
/** Private and public key. */
public abstract class KeyPair implements Signer {

public static KeyPair generate(Algorithm algorithm) {
return generate(algorithm, new SecureRandom());
}
public static KeyPair generate(Algorithm algorithm) {
return generate(algorithm, new SecureRandom());
}

public static KeyPair generate(Algorithm algorithm, String hex) {
return generate(algorithm, Utils.hexToBytes(hex));
}
public static KeyPair generate(Algorithm algorithm, String hex) {
return generate(algorithm, Utils.hexToBytes(hex));
}

public static KeyPair generate(Algorithm algorithm, byte[] bytes) {
if (algorithm == Algorithm.Ed25519) {
return new Ed25519KeyPair(bytes);
} else if (algorithm == Algorithm.SECP256R1) {
return new SECP256R1KeyPair(bytes);
} else {
throw new IllegalArgumentException("Unsupported algorithm");
}
public static KeyPair generate(Algorithm algorithm, byte[] bytes) {
if (algorithm == Algorithm.Ed25519) {
return new Ed25519KeyPair(bytes);
} else if (algorithm == Algorithm.SECP256R1) {
return new SECP256R1KeyPair(bytes);
} else {
throw new IllegalArgumentException("Unsupported algorithm");
}
}

public static KeyPair generate(Algorithm algorithm, SecureRandom rng) {
if (algorithm == Algorithm.Ed25519) {
return new Ed25519KeyPair(rng);
} else if (algorithm == Algorithm.SECP256R1) {
return new SECP256R1KeyPair(rng);
} else {
throw new IllegalArgumentException("Unsupported algorithm");
}
public static KeyPair generate(Algorithm algorithm, SecureRandom rng) {
if (algorithm == Algorithm.Ed25519) {
return new Ed25519KeyPair(rng);
} else if (algorithm == Algorithm.SECP256R1) {
return new SECP256R1KeyPair(rng);
} else {
throw new IllegalArgumentException("Unsupported algorithm");
}
}

public static Signature generateSignature(Algorithm algorithm) throws NoSuchAlgorithmException {
if (algorithm == Algorithm.Ed25519) {
return Ed25519KeyPair.getSignature();
} else if (algorithm == Algorithm.SECP256R1) {
return SECP256R1KeyPair.getSignature();
} else {
throw new NoSuchAlgorithmException("Unsupported algorithm");
}
public static Signature generateSignature(Algorithm algorithm) throws NoSuchAlgorithmException {
if (algorithm == Algorithm.Ed25519) {
return Ed25519KeyPair.getSignature();
} else if (algorithm == Algorithm.SECP256R1) {
return SECP256R1KeyPair.getSignature();
} else {
throw new NoSuchAlgorithmException("Unsupported algorithm");
}
}

public static boolean verify(PublicKey publicKey, byte[] data, byte[] signature) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
Signature sgr = KeyPair.generateSignature(publicKey.algorithm);
sgr.initVerify(publicKey.key);
sgr.update(data);
return sgr.verify(signature);
}
public static boolean verify(PublicKey publicKey, byte[] data, byte[] signature)
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
Signature sgr = KeyPair.generateSignature(publicKey.getAlgorithm());
sgr.initVerify(publicKey.getKey());
sgr.update(data);
return sgr.verify(signature);
}

public abstract byte[] toBytes();
public abstract byte[] toBytes();

public abstract String toHex();
public abstract String toHex();

@Override
public abstract PublicKey public_key();
@Override
public abstract PublicKey getPublicKey();
}
Loading