Skip to content

Commit

Permalink
fix: PasetoPublicTest fails when running (say 1000) times with - The … (
Browse files Browse the repository at this point in the history
#96)

The ASN split can also be less than 48, so we need to add padding in front of it. Instead of writing code to change a BigInteger to a byte array we now use the BC utility method.

Closes gh-95
  • Loading branch information
nbaars authored Jun 5, 2023
1 parent b35f2d9 commit c0c7066
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 7 deletions.
17 changes: 10 additions & 7 deletions version3/src/main/java/org/paseto4j/version3/CryptoFunctions.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
Expand All @@ -48,6 +47,7 @@
import org.bouncycastle.crypto.generators.HKDFBytesGenerator;
import org.bouncycastle.crypto.params.HKDFParameters;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.BigIntegers;
import org.paseto4j.commons.ByteUtils;
import org.paseto4j.commons.Pair;

Expand Down Expand Up @@ -141,12 +141,14 @@ public static byte[] hkdfSha384(byte[] key, byte[] info) {
return out;
}

public static byte[] toUnsignedByteArray(BigInteger value) {
byte[] signedValue = value.toByteArray();
if (signedValue[0] != 0x00) {
return signedValue;
private static byte[] toUnsignedByteArray(BigInteger n, int length) {
byte[] bs = BigIntegers.asUnsignedByteArray(n);
if (bs.length < length) {
byte[] tmp = new byte[length];
System.arraycopy(bs, 0, tmp, length - bs.length, bs.length);
bs = tmp;
}
return Arrays.copyOfRange(signedValue, 1, signedValue.length);
return bs;
}

public static byte[] sign(PrivateKey privateKey, byte[] msg) {
Expand All @@ -162,7 +164,8 @@ public static byte[] sign(PrivateKey privateKey, byte[] msg) {
ASN1Integer r = (ASN1Integer) seq.getObjectAt(0);
ASN1Integer s = (ASN1Integer) seq.getObjectAt(1);

return ByteUtils.concat(toUnsignedByteArray(r.getValue()), toUnsignedByteArray(s.getValue()));
return ByteUtils.concat(
toUnsignedByteArray(r.getValue(), 48), toUnsignedByteArray(s.getValue(), 48));

} catch (GeneralSecurityException e) {
throw new IllegalStateException(e);
Expand Down
31 changes: 31 additions & 0 deletions version3/src/test/java/org/paseto4j/version3/PasetoPublicTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
Expand All @@ -40,9 +41,14 @@
import java.security.SignatureException;
import java.security.spec.ECGenParameterSpec;
import java.util.stream.Stream;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemWriter;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
Expand All @@ -65,6 +71,17 @@ public static KeyPair readEC(String pem) throws IOException {
return new JcaPEMKeyConverter().getKeyPair((org.bouncycastle.openssl.PEMKeyPair) parsed);
}

public static String writeToPEM(java.security.PrivateKey privateKey) throws IOException {
var writer = new StringWriter();
try (var pemWriter = new PemWriter(writer)) {
var pki = PrivateKeyInfo.getInstance(ASN1Sequence.getInstance(privateKey.getEncoded()));
ASN1Object asn = (ASN1Object) pki.parsePrivateKey();
pemWriter.writeObject(new PemObject("EC PRIVATE KEY", asn.getEncoded("DER")));
pemWriter.flush();
return writer.toString();
}
}

@ParameterizedTest
@MethodSource("testVectors")
void signTestVectors(
Expand Down Expand Up @@ -111,8 +128,22 @@ void normalUsage()
generator.initialize(spec);
var expectedPayload = "test message";
var keyPair = generator.generateKeyPair();

var signedMessage = Paseto.sign(new PrivateKey(keyPair.getPrivate(), V3), expectedPayload);
var payload =
Paseto.parse(new org.paseto4j.commons.PublicKey(keyPair.getPublic(), V3), signedMessage);

Assertions.assertEquals(expectedPayload, payload);
}

@Test
void signingWhereASNPartsShouldBePadded() throws IOException, SignatureException {
var pem =
"-----BEGIN EC PRIVATE KEY-----\nMIGkAgEBBDBKvAg41dsJ64e+CY5Ona1PdhkHtDXZawacdj4fcUQVqR2hy19NML7S\nWpHchEsBzCegBwYFK4EEACKhZANiAARnuVQrWJkAJ7tBA9HkSvgpyn6haQQHZ4a2\nKqJwZ6LwVujOpP4gOPaIrL0fGDR2zQSZMaggHfYemqordD9nq9oPzBwVI+KZ8Rnq\nl35zsijbS3D6g5tN1cfcxtmB9c/2KVs=\n-----END EC PRIVATE KEY-----";
var keyPair = readEC(pem);
var expectedPayload = "test message";

var signedMessage = Paseto.sign(new PrivateKey(keyPair.getPrivate(), V3), expectedPayload);
var payload =
Paseto.parse(new org.paseto4j.commons.PublicKey(keyPair.getPublic(), V3), signedMessage);

Expand Down

0 comments on commit c0c7066

Please sign in to comment.