This repository has been archived by the owner on Apr 23, 2019. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
adding BLS12-381 sig verification and aggregation
- Loading branch information
Showing
18 changed files
with
876 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ | |
.classpath | ||
.externalToolBuilders/ | ||
.gradle/ | ||
.vscode/ | ||
.idea/* | ||
!.idea/codeStyles/ | ||
.loadpath | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
122 changes: 122 additions & 0 deletions
122
crypto/src/main/java/net/consensys/cava/crypto/mikuli/BLS12381.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
/* | ||
* Copyright 2019 ConsenSys AG. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | ||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations under the License. | ||
*/ | ||
package net.consensys.cava.crypto.mikuli; | ||
|
||
import net.consensys.cava.crypto.mikuli.group.AtePairing; | ||
import net.consensys.cava.crypto.mikuli.group.G1Point; | ||
import net.consensys.cava.crypto.mikuli.group.G2Point; | ||
import net.consensys.cava.crypto.mikuli.group.GTPoint; | ||
|
||
import java.util.List; | ||
|
||
import org.apache.milagro.amcl.BLS381.BIG; | ||
import org.apache.milagro.amcl.BLS381.ECP; | ||
import org.apache.milagro.amcl.BLS381.ECP2; | ||
import org.apache.milagro.amcl.BLS381.MPIN; | ||
|
||
public final class BLS12381 { | ||
|
||
/** | ||
* Generates a SignatureAndPublicKey. | ||
* | ||
* @param keyPair The public and private key pair, not null | ||
* @param message The message to sign, not null | ||
* @return The SignatureAndPublicKey, not null | ||
*/ | ||
public static SignatureAndPublicKey sign(KeyPair keyPair, byte[] message) { | ||
G2Point hashInGroup2 = hashFunction(message); | ||
/* | ||
* The signature is hash point in G2 multiplied by the private key. | ||
*/ | ||
G2Point sig = keyPair.privateKey().sign(hashInGroup2); | ||
return new SignatureAndPublicKey(new Signature(sig), keyPair.publicKey()); | ||
} | ||
|
||
/** | ||
* Verifies the given BLS signature against the message bytes using the public key. | ||
* | ||
* @param publicKey The public key, not null | ||
* @param signature The signature, not null | ||
* @param message The message data to verify, not null | ||
* | ||
* @return True if the verification is successful. | ||
*/ | ||
public static boolean verify(PublicKey publicKey, Signature signature, byte[] message) { | ||
G1Point g1Generator = SystemParameters.g1Generator; | ||
|
||
G2Point hashInGroup2 = hashFunction(message); | ||
GTPoint e1 = AtePairing.pair(publicKey.g1Point(), hashInGroup2); | ||
GTPoint e2 = AtePairing.pair(g1Generator, signature.g2Point()); | ||
|
||
return e1.equals(e2); | ||
} | ||
|
||
/** | ||
* Verifies the given BLS signature against the message bytes using the public key. | ||
* | ||
* @param sigAndPubKey The signature and public key, not null | ||
* @param message The message data to verify, not null | ||
* | ||
* @return True if the verification is successful, not null | ||
*/ | ||
public static boolean verify(SignatureAndPublicKey sigAndPubKey, byte[] message) { | ||
return verify(sigAndPubKey.publicKey(), sigAndPubKey.signature(), message); | ||
} | ||
|
||
/** | ||
* Aggregates list of Signature and PublicKey pairs | ||
* | ||
* @param sigAndPubKeyList The list of Signatures and corresponding Public keys to aggregate, not null | ||
* @return SignatureAndPublicKey, not null | ||
* @throws IllegalArgumentException if parameter list is empty | ||
*/ | ||
public static SignatureAndPublicKey aggregate(List<SignatureAndPublicKey> sigAndPubKeyList) { | ||
listNotEmpty(sigAndPubKeyList); | ||
return sigAndPubKeyList.stream().reduce((a, b) -> a.combine(b)).get(); | ||
} | ||
|
||
/** | ||
* Aggregates list of PublicKey pairs | ||
* | ||
* @param publicKeyList The list of public keys to aggregate, not null | ||
* @return PublicKey The public key, not null | ||
* @throws IllegalArgumentException if parameter list is empty | ||
*/ | ||
public static PublicKey aggregatePublicKey(List<PublicKey> publicKeyList) { | ||
listNotEmpty(publicKeyList); | ||
return publicKeyList.stream().reduce((a, b) -> a.combine(b)).get(); | ||
} | ||
|
||
/** | ||
* Aggregates list of Signature pairs | ||
* | ||
* @param signatureList The list of signatures to aggregate, not null | ||
* @throws IllegalArgumentException if parameter list is empty | ||
* @return Signature, not null | ||
*/ | ||
public static Signature aggregateSignatures(List<Signature> signatureList) { | ||
listNotEmpty(signatureList); | ||
return signatureList.stream().reduce((a, b) -> a.combine(b)).get(); | ||
} | ||
|
||
private static void listNotEmpty(List<?> list) { | ||
if (list.isEmpty()) { | ||
throw new IllegalArgumentException("Parameter list is empty"); | ||
} | ||
} | ||
|
||
private static G2Point hashFunction(byte[] message) { | ||
byte[] hashByte = MPIN.HASH_ID(ECP.SHA256, message, BIG.MODBYTES); | ||
return new G2Point(ECP2.mapit(hashByte)); | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
crypto/src/main/java/net/consensys/cava/crypto/mikuli/KeyPair.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/* | ||
* Copyright 2019 ConsenSys AG. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | ||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations under the License. | ||
*/ | ||
package net.consensys.cava.crypto.mikuli; | ||
|
||
public final class KeyPair { | ||
|
||
private final PrivateKey privateKey; | ||
private final PublicKey publicKey; | ||
|
||
KeyPair(PrivateKey privateKey, PublicKey publicKey) { | ||
if (privateKey == null || publicKey == null) { | ||
throw new NullPointerException("KeyPair was not properly initialized"); | ||
} | ||
this.privateKey = privateKey; | ||
this.publicKey = publicKey; | ||
} | ||
|
||
public PublicKey publicKey() { | ||
return publicKey; | ||
} | ||
|
||
public PrivateKey privateKey() { | ||
return privateKey; | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
crypto/src/main/java/net/consensys/cava/crypto/mikuli/KeyPairFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* Copyright 2019 ConsenSys AG. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | ||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations under the License. | ||
*/ | ||
package net.consensys.cava.crypto.mikuli; | ||
|
||
import net.consensys.cava.crypto.mikuli.group.G1Point; | ||
import net.consensys.cava.crypto.mikuli.group.Scalar; | ||
|
||
import org.apache.milagro.amcl.BLS381.BIG; | ||
import org.apache.milagro.amcl.RAND; | ||
|
||
public final class KeyPairFactory { | ||
|
||
static public KeyPair createKeyPair() { | ||
G1Point g1Generator = SystemParameters.g1Generator; | ||
RAND rng = new RAND(); | ||
|
||
Scalar secret = new Scalar(BIG.randomnum(SystemParameters.curveOrder, rng)); | ||
|
||
PrivateKey privateKey = new PrivateKey(secret); | ||
G1Point g1Point = g1Generator.mul(secret); | ||
PublicKey publicKey = new PublicKey(g1Point); | ||
return new KeyPair(privateKey, publicKey); | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
crypto/src/main/java/net/consensys/cava/crypto/mikuli/PrivateKey.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* | ||
* Copyright 2019 ConsenSys AG. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | ||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations under the License. | ||
*/ | ||
package net.consensys.cava.crypto.mikuli; | ||
|
||
import net.consensys.cava.crypto.mikuli.group.G2Point; | ||
import net.consensys.cava.crypto.mikuli.group.Scalar; | ||
|
||
public final class PrivateKey { | ||
|
||
private final Scalar scalarValue; | ||
|
||
PrivateKey(Scalar value) { | ||
if (value == null) { | ||
throw new NullPointerException("PrivateKey was not properly initialized"); | ||
} | ||
this.scalarValue = value; | ||
} | ||
|
||
protected G2Point sign(G2Point message) { | ||
return message.mul(scalarValue); | ||
} | ||
} |
75 changes: 75 additions & 0 deletions
75
crypto/src/main/java/net/consensys/cava/crypto/mikuli/PublicKey.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/* | ||
* Copyright 2019 ConsenSys AG. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | ||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations under the License. | ||
*/ | ||
package net.consensys.cava.crypto.mikuli; | ||
|
||
import net.consensys.cava.crypto.mikuli.group.G1Point; | ||
|
||
public final class PublicKey { | ||
|
||
private final G1Point point; | ||
|
||
PublicKey(G1Point point) { | ||
if (point == null) { | ||
throw new NullPointerException("PublicKey was not properly initialized"); | ||
} | ||
this.point = point; | ||
} | ||
|
||
public PublicKey combine(PublicKey pk) { | ||
return new PublicKey(point.add(pk.point)); | ||
} | ||
|
||
/** | ||
* Public key serialization | ||
* | ||
* @return byte array representation of the public key | ||
*/ | ||
public byte[] encode() { | ||
return point.toBytes(); | ||
} | ||
|
||
public static PublicKey decode(byte[] bytes) { | ||
G1Point point = G1Point.fromBytes(bytes); | ||
return new PublicKey(point); | ||
} | ||
|
||
|
||
@Override | ||
public int hashCode() { | ||
final int prime = 31; | ||
int result = 1; | ||
result = prime * result + ((point == null) ? 0 : point.hashCode()); | ||
return result; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if (this == obj) | ||
return true; | ||
if (obj == null) | ||
return false; | ||
if (getClass() != obj.getClass()) | ||
return false; | ||
PublicKey other = (PublicKey) obj; | ||
if (point == null) { | ||
if (other.point != null) | ||
return false; | ||
} else if (!point.equals(other.point)) | ||
return false; | ||
return true; | ||
} | ||
|
||
public G1Point g1Point() { | ||
return point; | ||
} | ||
} |
78 changes: 78 additions & 0 deletions
78
crypto/src/main/java/net/consensys/cava/crypto/mikuli/Signature.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* | ||
* Copyright 2019 ConsenSys AG. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | ||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations under the License. | ||
*/ | ||
package net.consensys.cava.crypto.mikuli; | ||
|
||
import net.consensys.cava.crypto.mikuli.group.G2Point; | ||
|
||
public final class Signature { | ||
private final G2Point point; | ||
|
||
Signature(G2Point point) { | ||
if (point == null) { | ||
throw new NullPointerException("Signature was not properly initialized"); | ||
} | ||
this.point = point; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "Signature [ecpPoint=" + point.toString() + "]"; | ||
} | ||
|
||
public Signature combine(Signature sig) { | ||
return new Signature(point.add(sig.point)); | ||
} | ||
|
||
/** | ||
* Signature serialization | ||
* | ||
* @return byte array representation of the signature, not null | ||
*/ | ||
public byte[] encode() { | ||
return point.toBytes(); | ||
} | ||
|
||
public static Signature decode(byte[] bytes) { | ||
G2Point point = G2Point.fromBytes(bytes); | ||
return new Signature(point); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
final int prime = 31; | ||
int result = 1; | ||
result = prime * result + ((point == null) ? 0 : point.hashCode()); | ||
return result; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if (this == obj) | ||
return true; | ||
if (obj == null) | ||
return false; | ||
if (getClass() != obj.getClass()) | ||
return false; | ||
Signature other = (Signature) obj; | ||
if (point == null) { | ||
if (other.point != null) | ||
return false; | ||
} else if (!point.equals(other.point)) | ||
return false; | ||
return true; | ||
} | ||
|
||
G2Point g2Point() { | ||
return point; | ||
} | ||
} |
Oops, something went wrong.