diff --git a/.ci/ci_check.sh b/.ci/ci_check.sh index ee6d6dc3a..0ece21adb 100755 --- a/.ci/ci_check.sh +++ b/.ci/ci_check.sh @@ -1,6 +1,6 @@ #!/bin/bash set -e +# check code format bash gradlew verifyGoogleJavaFormat bash gradlew build - diff --git a/build.gradle b/build.gradle index 25c93b52a..334b099a5 100644 --- a/build.gradle +++ b/build.gradle @@ -57,14 +57,14 @@ dependencies { compile 'org.apache.commons:commons-lang3:3.1' compile 'io.netty:netty-all:4.1.50.Final' compile 'com.fasterxml.jackson.core:jackson-databind:2.11.0' - compile group: 'commons-codec', name: 'commons-codec', version: '1.14' - - + compile 'org.slf4j:slf4j-api:1.7.30' + compile files('lib/pkey-sign.jar') testCompile 'junit:junit:4.12' testCompile 'org.mockito:mockito-core:2.23.0' + } archivesBaseName = 'java-sdk' group = 'org.fisco-bcos' -version = '1.0.0-SNAPSHOT' \ No newline at end of file +version = '1.0.0-SNAPSHOT' diff --git a/lib/pkey-sign.jar b/lib/pkey-sign.jar new file mode 100644 index 000000000..3637530ba Binary files /dev/null and b/lib/pkey-sign.jar differ diff --git a/src/main/java/org/fisco/bcos/sdk/crypto/hash/Hash.java b/src/main/java/org/fisco/bcos/sdk/crypto/hash/Hash.java new file mode 100644 index 000000000..c8f6b6648 --- /dev/null +++ b/src/main/java/org/fisco/bcos/sdk/crypto/hash/Hash.java @@ -0,0 +1,22 @@ +/** + * Copyright 2014-2020 [fisco-dev] + * + *
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. + */ + +/** interface for hash calculation */ +package org.fisco.bcos.sdk.crypto.hash; + +public interface Hash { + String hash(final String inputData); + + byte[] hash(final byte[] inputBytes); +} diff --git a/src/main/java/org/fisco/bcos/sdk/crypto/hash/Keccak256.java b/src/main/java/org/fisco/bcos/sdk/crypto/hash/Keccak256.java new file mode 100644 index 000000000..65151a9bb --- /dev/null +++ b/src/main/java/org/fisco/bcos/sdk/crypto/hash/Keccak256.java @@ -0,0 +1,43 @@ +/** + * Copyright 2014-2020 [fisco-dev] + * + *
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 org.fisco.bcos.sdk.crypto.hash; + +import com.webank.wedpr.crypto.CryptoResult; +import com.webank.wedpr.crypto.NativeInterface; +import org.fisco.bcos.sdk.exceptions.HashException; +import org.fisco.bcos.sdk.utils.Hex; + +public class Keccak256 implements Hash { + + @Override + public String hash(final String inputData) { + return calculateHash(inputData.getBytes()); + } + + @Override + public byte[] hash(final byte[] inputBytes) { + return Hex.decode(calculateHash(inputBytes)); + } + + private String calculateHash(final byte[] inputBytes) { + // Note: the exceptions should be handled by the caller + CryptoResult hashResult = NativeInterface.keccak256(Hex.toHexString(inputBytes)); + if (hashResult.wedprErrorMessage != null && !hashResult.wedprErrorMessage.isEmpty()) { + throw new HashException( + "Calculate hash with keccak256 failed! error message:" + + hashResult.wedprErrorMessage); + } + return hashResult.hash; + } +} diff --git a/src/main/java/org/fisco/bcos/sdk/crypto/hash/SM3Hash.java b/src/main/java/org/fisco/bcos/sdk/crypto/hash/SM3Hash.java new file mode 100644 index 000000000..2cdcc9136 --- /dev/null +++ b/src/main/java/org/fisco/bcos/sdk/crypto/hash/SM3Hash.java @@ -0,0 +1,43 @@ +/** + * Copyright 2014-2020 [fisco-dev] + * + *
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 org.fisco.bcos.sdk.crypto.hash; + +import com.webank.wedpr.crypto.CryptoResult; +import com.webank.wedpr.crypto.NativeInterface; +import org.fisco.bcos.sdk.exceptions.HashException; +import org.fisco.bcos.sdk.utils.Hex; + +public class SM3Hash implements Hash { + @Override + public String hash(final String inputData) { + return calcualteHash(inputData.getBytes()); + } + + @Override + public byte[] hash(final byte[] inputBytes) { + // Considering inefficient string conversion, this interface is not recommended + return Hex.decode(calcualteHash(inputBytes)); + } + + private String calcualteHash(final byte[] inputBytes) { + CryptoResult hashResult = NativeInterface.sm3(Hex.toHexString(inputBytes)); + // call sm3 failed + if (hashResult.wedprErrorMessage != null && !hashResult.wedprErrorMessage.isEmpty()) { + throw new HashException( + "calculate hash with sm3 failed, error message:" + + hashResult.wedprErrorMessage); + } + return hashResult.hash; + } +} diff --git a/src/main/java/org/fisco/bcos/sdk/crypto/keypair/CryptoKeyPair.java b/src/main/java/org/fisco/bcos/sdk/crypto/keypair/CryptoKeyPair.java new file mode 100644 index 000000000..4c15ab2f9 --- /dev/null +++ b/src/main/java/org/fisco/bcos/sdk/crypto/keypair/CryptoKeyPair.java @@ -0,0 +1,105 @@ +/** + * Copyright 2014-2020 [fisco-dev] + * + *
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 org.fisco.bcos.sdk.crypto.keypair; + +import com.webank.wedpr.crypto.CryptoResult; +import java.math.BigInteger; +import java.util.Objects; + +public abstract class CryptoKeyPair { + private BigInteger privateKey; + protected BigInteger publicKey; + + protected String hexPrivateKey; + protected String hexPublicKey; + + public CryptoKeyPair() {} + + public CryptoKeyPair(final BigInteger privateKey) { + this.privateKey = privateKey; + /** + * todo: get publicKey according to privateKey this.publicKey = + * privateKeyToPublic(privateKey); + */ + calculateHexedKeyPair(); + } + + public CryptoKeyPair(final BigInteger privateKey, final BigInteger publicKey) { + this.privateKey = privateKey; + this.publicKey = publicKey; + calculateHexedKeyPair(); + } + + private void calculateHexedKeyPair() { + this.hexPrivateKey = this.privateKey.toString(16); + this.hexPublicKey = this.publicKey.toString(16); + } + + /** + * get CryptoKeyPair information from CryptoResult + * + * @param nativeResult + */ + CryptoKeyPair(final CryptoResult nativeResult) { + this.hexPrivateKey = nativeResult.privteKey; + this.hexPublicKey = nativeResult.publicKey; + this.privateKey = new BigInteger(this.hexPrivateKey, 16); + this.publicKey = new BigInteger(this.hexPublicKey, 16); + } + + public BigInteger getPrivateKey() { + return privateKey; + } + + public BigInteger getPublicKey() { + return publicKey; + } + + public String getHexPrivateKey() { + return hexPrivateKey; + } + + public String getHexPublicKey() { + return hexPublicKey; + } + + /** + * todo: get the public key from the given private key + * + * @param privateKey + * @return: the public key calculated from the private key public abstract BigInteger + * privateKeyToPublic(BigInteger privateKey); + */ + + /** + * generate keyPair randomly + * + * @return: the generated keyPair + */ + public abstract CryptoKeyPair generateKeyPair(); + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CryptoKeyPair keyPair = (CryptoKeyPair) o; + return Objects.equals(privateKey, keyPair.privateKey) + && Objects.equals(publicKey, keyPair.publicKey); + } + + @Override + public int hashCode() { + return Objects.hash(privateKey, publicKey); + } +} diff --git a/src/main/java/org/fisco/bcos/sdk/crypto/keypair/ECDSAKeyPair.java b/src/main/java/org/fisco/bcos/sdk/crypto/keypair/ECDSAKeyPair.java new file mode 100644 index 000000000..5f58fb9b5 --- /dev/null +++ b/src/main/java/org/fisco/bcos/sdk/crypto/keypair/ECDSAKeyPair.java @@ -0,0 +1,45 @@ +/** + * Copyright 2014-2020 [fisco-dev] + * + *
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 org.fisco.bcos.sdk.crypto.keypair; + +import com.webank.wedpr.crypto.CryptoResult; +import com.webank.wedpr.crypto.NativeInterface; +import java.math.BigInteger; + +public class ECDSAKeyPair extends CryptoKeyPair { + + public ECDSAKeyPair() {} + + public ECDSAKeyPair(BigInteger privateKey) { + super(privateKey); + } + + public ECDSAKeyPair(final BigInteger privateKey, final BigInteger publicKey) { + super(privateKey, publicKey); + } + + protected ECDSAKeyPair(final CryptoResult ecKeyPairInfo) { + super(ecKeyPairInfo); + } + + /** + * generate keyPair randomly + * + * @return: the generated keyPair + */ + @Override + public CryptoKeyPair generateKeyPair() { + return new ECDSAKeyPair(NativeInterface.secp256k1keyPair()); + } +} diff --git a/src/main/java/org/fisco/bcos/sdk/crypto/keypair/SM2KeyPair.java b/src/main/java/org/fisco/bcos/sdk/crypto/keypair/SM2KeyPair.java new file mode 100644 index 000000000..41b86558d --- /dev/null +++ b/src/main/java/org/fisco/bcos/sdk/crypto/keypair/SM2KeyPair.java @@ -0,0 +1,35 @@ +/** + * Copyright 2014-2020 [fisco-dev] + * + *
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 org.fisco.bcos.sdk.crypto.keypair; + +import com.webank.wedpr.crypto.CryptoResult; +import com.webank.wedpr.crypto.NativeInterface; + +public class SM2KeyPair extends CryptoKeyPair { + public SM2KeyPair() {} + + protected SM2KeyPair(CryptoResult sm2keyPairInfo) { + super(sm2keyPairInfo); + } + + /** + * generate keyPair randomly + * + * @return: the generated keyPair + */ + @Override + public CryptoKeyPair generateKeyPair() { + return new SM2KeyPair(NativeInterface.sm2keyPair()); + } +} diff --git a/src/main/java/org/fisco/bcos/sdk/crypto/signature/ECDSASignature.java b/src/main/java/org/fisco/bcos/sdk/crypto/signature/ECDSASignature.java new file mode 100644 index 000000000..cf7c35b66 --- /dev/null +++ b/src/main/java/org/fisco/bcos/sdk/crypto/signature/ECDSASignature.java @@ -0,0 +1,48 @@ +/** + * Copyright 2014-2020 [fisco-dev] + * + *
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 org.fisco.bcos.sdk.crypto.signature; + +import com.webank.pkeysign.service.ECCSignService; +import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair; +import org.fisco.bcos.sdk.exceptions.SignatureException; + +public class ECDSASignature implements Signature { + + public static final ECCSignService eccSignService = new ECCSignService(); + + @Override + public SignatureResult sign(final String message, final CryptoKeyPair keyPair) { + String signature = eccSignService.sign(message, keyPair.getHexPrivateKey()); + if (signature == null) { + throw new SignatureException("Sign with secp256k1 failed"); + } + // convert signature string to SignatureResult struct + return new ECDSASignatureResult(signature); + } + + @Override + public SignatureResult sign(final byte[] message, final CryptoKeyPair keyPair) { + return sign(new String(message), keyPair); + } + + @Override + public boolean verify(final String publicKey, final String message, final String signature) { + return eccSignService.verify(message, signature, publicKey); + } + + @Override + public boolean verify(final String publicKey, final byte[] message, final byte[] signature) { + return verify(publicKey, new String(message), new String(signature)); + } +} diff --git a/src/main/java/org/fisco/bcos/sdk/crypto/signature/ECDSASignatureResult.java b/src/main/java/org/fisco/bcos/sdk/crypto/signature/ECDSASignatureResult.java new file mode 100644 index 000000000..a41583954 --- /dev/null +++ b/src/main/java/org/fisco/bcos/sdk/crypto/signature/ECDSASignatureResult.java @@ -0,0 +1,61 @@ +/** + * Copyright 2014-2020 [fisco-dev] + * + *
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 org.fisco.bcos.sdk.crypto.signature;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.fisco.bcos.sdk.exceptions.SignatureException;
+import org.fisco.bcos.sdk.rlp.RlpString;
+import org.fisco.bcos.sdk.rlp.RlpType;
+import org.fisco.bcos.sdk.utils.Hex;
+
+public class ECDSASignatureResult extends SignatureResult {
+ protected byte v;
+
+ ECDSASignatureResult(byte v, byte[] r, byte[] s) {
+ super(r, s);
+ this.v = v;
+ }
+
+ ECDSASignatureResult(final String signatureResult) {
+ super(signatureResult);
+ if (this.signatureBytes.length != 65) {
+ throw new SignatureException(
+ "Invalid signature for invalid length " + this.signatureBytes.length);
+ }
+ this.v = this.signatureBytes[64];
+ }
+
+ /**
+ * covert signatureResult into String
+ *
+ * @return: the signature string with [r, s, v]
+ */
+ @Override
+ public String convertToString() {
+ byte[] SignatureBytes = new byte[65];
+ System.arraycopy(this.r, 0, SignatureBytes, 0, 32);
+ System.arraycopy(this.s, 0, SignatureBytes, 32, 32);
+ SignatureBytes[64] = this.v;
+ return Hex.toHexString(SignatureBytes);
+ }
+
+ @Override
+ public List 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 org.fisco.bcos.sdk.crypto.signature;
+
+import com.webank.pkeysign.service.SM2SignService;
+import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
+import org.fisco.bcos.sdk.exceptions.SignatureException;
+
+public class SM2Signature implements Signature {
+ public static final SM2SignService sm2SignService = new SM2SignService();
+
+ @Override
+ public SignatureResult sign(final String message, final CryptoKeyPair keyPair) {
+ String signature = sm2SignService.sign(message, keyPair.getHexPrivateKey());
+ if (signature == null) {
+ throw new SignatureException("Sign with sm2 failed");
+ }
+ return new SM2SignatureResult(keyPair.getHexPublicKey(), signature);
+ }
+
+ @Override
+ public SignatureResult sign(final byte[] message, final CryptoKeyPair keyPair) {
+ return sign(new String(message), keyPair);
+ }
+
+ @Override
+ public boolean verify(final String publicKey, final String message, final String signature) {
+ return sm2SignService.verify(message, signature, publicKey);
+ }
+
+ @Override
+ public boolean verify(final String publicKey, final byte[] message, final byte[] signature) {
+ return verify(publicKey, new String(message), new String(signature));
+ }
+}
diff --git a/src/main/java/org/fisco/bcos/sdk/crypto/signature/SM2SignatureResult.java b/src/main/java/org/fisco/bcos/sdk/crypto/signature/SM2SignatureResult.java
new file mode 100644
index 000000000..c5664e080
--- /dev/null
+++ b/src/main/java/org/fisco/bcos/sdk/crypto/signature/SM2SignatureResult.java
@@ -0,0 +1,55 @@
+/**
+ * Copyright 2014-2020 [fisco-dev]
+ *
+ * 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 org.fisco.bcos.sdk.crypto.signature;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.fisco.bcos.sdk.rlp.RlpString;
+import org.fisco.bcos.sdk.rlp.RlpType;
+import org.fisco.bcos.sdk.utils.Hex;
+
+public class SM2SignatureResult extends SignatureResult {
+ protected final byte[] pub;
+
+ SM2SignatureResult(final String hexPublicKey, final String signatureString) {
+ super(signatureString);
+ this.pub = Hex.decode(hexPublicKey);
+ }
+
+ SM2SignatureResult(byte[] pub, byte[] r, byte[] s) {
+ super(r, s);
+ this.pub = pub;
+ }
+
+ /**
+ * covert signatureResult into String
+ *
+ * @return: the signature string with [r, s]
+ */
+ @Override
+ public String convertToString() {
+ byte[] SignatureBytes = new byte[64];
+ System.arraycopy(this.r, 0, SignatureBytes, 0, 32);
+ System.arraycopy(this.s, 0, SignatureBytes, 32, 32);
+ return Hex.toHexString(SignatureBytes);
+ }
+
+ @Override
+ public List 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.
+ */
+
+/** interface for sign/verify functions */
+package org.fisco.bcos.sdk.crypto.signature;
+
+import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
+
+public interface Signature {
+ SignatureResult sign(final byte[] message, final CryptoKeyPair keyPair);
+
+ SignatureResult sign(final String message, final CryptoKeyPair keyPair);
+
+ boolean verify(final String publicKey, final String message, final String signature);
+
+ boolean verify(final String publicKey, final byte[] message, final byte[] signature);
+}
diff --git a/src/main/java/org/fisco/bcos/sdk/crypto/signature/SignatureResult.java b/src/main/java/org/fisco/bcos/sdk/crypto/signature/SignatureResult.java
new file mode 100644
index 000000000..28386f4d3
--- /dev/null
+++ b/src/main/java/org/fisco/bcos/sdk/crypto/signature/SignatureResult.java
@@ -0,0 +1,78 @@
+/**
+ * Copyright 2014-2020 [fisco-dev]
+ *
+ * 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 org.fisco.bcos.sdk.crypto.signature;
+
+import java.util.List;
+import org.fisco.bcos.sdk.exceptions.SignatureException;
+import org.fisco.bcos.sdk.rlp.RlpString;
+import org.fisco.bcos.sdk.rlp.RlpType;
+import org.fisco.bcos.sdk.utils.Hex;
+
+public abstract class SignatureResult {
+ protected final byte[] r;
+ protected final byte[] s;
+ protected byte[] signatureBytes;
+
+ SignatureResult(final byte[] r, final byte[] s) {
+ this.r = r;
+ this.s = s;
+ }
+
+ /**
+ * Recover v, r, s from signature string The first 32 bytes are r, and the 32 bytes after r are
+ * s
+ *
+ * @param signatureString: the signatureString
+ */
+ SignatureResult(final String signatureString) {
+ this.signatureBytes = Hex.decode(signatureString);
+ // at least 64 bytes
+ if (this.signatureBytes.length < 64) {
+ throw new SignatureException("Invalid signature: " + signatureString);
+ }
+ // get R
+ this.r = new byte[32];
+ System.arraycopy(this.signatureBytes, 0, this.r, 0, 32);
+ // get S
+ this.s = new byte[32];
+ System.arraycopy(this.signatureBytes, 32, this.s, 0, 32);
+ }
+
+ public byte[] getR() {
+ return r;
+ }
+
+ public byte[] getS() {
+ return s;
+ }
+
+ protected void encodeCommonField(List 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 org.fisco.bcos.sdk.exceptions;
+
+/** Exceptioned when calling hash. */
+public class HashException extends RuntimeException {
+ public HashException(String message) {
+ super(message);
+ }
+
+ public HashException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/org/fisco/bcos/sdk/exceptions/SignatureException.java b/src/main/java/org/fisco/bcos/sdk/exceptions/SignatureException.java
new file mode 100644
index 000000000..7a57f0850
--- /dev/null
+++ b/src/main/java/org/fisco/bcos/sdk/exceptions/SignatureException.java
@@ -0,0 +1,25 @@
+/**
+ * Copyright 2014-2020 [fisco-dev]
+ *
+ * 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 org.fisco.bcos.sdk.exceptions;
+
+/** Exceptioned when calling signature related functions. */
+public class SignatureException extends RuntimeException {
+ public SignatureException(String message) {
+ super(message);
+ }
+
+ public SignatureException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/org/fisco/bcos/sdk/utils/ByteUtil.java b/src/main/java/org/fisco/bcos/sdk/utils/ByteUtil.java
index 37a1e823a..627538519 100644
--- a/src/main/java/org/fisco/bcos/sdk/utils/ByteUtil.java
+++ b/src/main/java/org/fisco/bcos/sdk/utils/ByteUtil.java
@@ -53,17 +53,6 @@ public static byte[] bigIntegerToBytes(BigInteger b, int numBytes) {
return bytes;
}
- public static byte[] bigIntegerToBytesSigned(BigInteger b, int numBytes) {
- if (b == null) return null;
- byte[] bytes = new byte[numBytes];
- Arrays.fill(bytes, b.signum() < 0 ? (byte) 0xFF : 0x00);
- byte[] biBytes = b.toByteArray();
- int start = (biBytes.length == numBytes + 1) ? 1 : 0;
- int length = Math.min(biBytes.length, numBytes);
- System.arraycopy(biBytes, start, bytes, numBytes - length, length);
- return bytes;
- }
-
public static byte[] bigIntegerToBytes(BigInteger value) {
if (value == null) return null;
@@ -77,6 +66,17 @@ public static byte[] bigIntegerToBytes(BigInteger value) {
return data;
}
+ public static byte[] bigIntegerToBytesSigned(BigInteger b, int numBytes) {
+ if (b == null) return null;
+ byte[] bytes = new byte[numBytes];
+ Arrays.fill(bytes, b.signum() < 0 ? (byte) 0xFF : 0x00);
+ byte[] biBytes = b.toByteArray();
+ int start = (biBytes.length == numBytes + 1) ? 1 : 0;
+ int length = Math.min(biBytes.length, numBytes);
+ System.arraycopy(biBytes, start, bytes, numBytes - length, length);
+ return bytes;
+ }
+
/**
* Cast hex encoded value from byte[] to BigInteger null is parsed like byte[0]
*
diff --git a/src/main/java/org/fisco/bcos/sdk/utils/NativeUtils.java b/src/main/java/org/fisco/bcos/sdk/utils/NativeUtils.java
deleted file mode 100644
index 32d10921b..000000000
--- a/src/main/java/org/fisco/bcos/sdk/utils/NativeUtils.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/**
- * Copyright 2014-2020 [fisco-dev]
- *
- * 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 org.fisco.bcos.sdk.utils;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.StandardCopyOption;
-
-public final class NativeUtils {
- /**
- * The minimum length a prefix for a file has to have according to {@link
- * File#createTempFile(String, String)}}.
- */
- private static final int MIN_PREFIX_LENGTH = 3;
-
- public static final String NATIVE_FOLDER_PATH_PREFIX = "nativeutils";
-
- /** Temporary directory which will contain the .so file. */
- private static File temporaryDir;
-
- /** Private constructor - this class will never be instanced */
- private NativeUtils() {}
-
- /**
- * The file from JAR is copied into system temporary directory and then loaded. The temporary
- * file is deleted after exiting.
- *
- * @param path
- * @throws IOException
- * @throws FileNotFoundException
- */
- public static synchronized void loadLibraryFromJar(String path) throws IOException {
-
- if (null == path || !path.startsWith("/")) {
- throw new IllegalArgumentException("The path has to be absolute (start with '/').");
- }
-
- // Obtain filename from path
- String[] parts = path.split("/");
- String filename = (parts.length > 1) ? parts[parts.length - 1] : null;
-
- if (filename == null || filename.length() < MIN_PREFIX_LENGTH) {
- throw new IllegalArgumentException(
- "The filename has to be at least 3 characters long.");
- }
-
- // create temp file
- if (temporaryDir == null) {
- temporaryDir = createTempDirectory(NATIVE_FOLDER_PATH_PREFIX);
- temporaryDir.deleteOnExit();
- }
- File temp = new File(temporaryDir, filename);
-
- // copy file from jar package to temp directory
- try (InputStream is = NativeUtils.class.getResourceAsStream(path)) {
- Files.copy(is, temp.toPath(), StandardCopyOption.REPLACE_EXISTING);
- } catch (IOException e) {
- temp.delete();
- throw e;
- } catch (NullPointerException e) {
- temp.delete();
- throw new FileNotFoundException("File " + path + " was not found inside JAR.");
- }
-
- // load the library
- try {
- System.load(temp.getAbsolutePath());
- } finally {
- temp.deleteOnExit();
- }
- }
-
- /**
- * Prepare temporary file
- *
- * @param prefix
- * @return
- * @throws IOException
- */
- private static File createTempDirectory(String prefix) throws IOException {
- String tempDir = System.getProperty("java.io.tmpdir");
- File generatedDir = new File(tempDir, prefix + System.nanoTime());
-
- if (!generatedDir.mkdir()) {
- throw new IOException("Failed to create temp directory " + generatedDir.getName());
- }
- return generatedDir;
- }
-}
diff --git a/src/test/java/org/fisco/bcos/sdk/test/crypto/HashTest.java b/src/test/java/org/fisco/bcos/sdk/test/crypto/HashTest.java
new file mode 100644
index 000000000..a10cfb4c2
--- /dev/null
+++ b/src/test/java/org/fisco/bcos/sdk/test/crypto/HashTest.java
@@ -0,0 +1,77 @@
+/**
+ * Copyright 2014-2020 [fisco-dev]
+ *
+ * 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 org.fisco.bcos.sdk.test.crypto;
+
+import org.fisco.bcos.sdk.crypto.hash.Hash;
+import org.fisco.bcos.sdk.crypto.hash.Keccak256;
+import org.fisco.bcos.sdk.crypto.hash.SM3Hash;
+import org.fisco.bcos.sdk.utils.Hex;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class HashTest {
+ @Test
+ public void testKeccak256() {
+ Hash hasher = new Keccak256();
+ testKeccak256(hasher);
+ }
+
+ @Test
+ public void testSM3() {
+ Hash sm3Hasher = new SM3Hash();
+ testSM3(sm3Hasher);
+ }
+
+ private void testKeccak256(Hash hasher) {
+
+ // check keccak256 for "abcde"
+ checkHash(
+ hasher,
+ "abcde",
+ "6377c7e66081cb65e473c1b95db5195a27d04a7108b468890224bedbe1a8a6eb");
+
+ // check keccak256 for "hello"
+ checkHash(
+ hasher,
+ "hello",
+ "1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8");
+
+ // check keccak256 for empty string
+ checkHash(hasher, "", "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
+ }
+
+ private void testSM3(Hash hasher) {
+ // check sm3 hash for "abcde"
+ checkHash(
+ hasher,
+ "abcde",
+ "afe4ccac5ab7d52bcae36373676215368baf52d3905e1fecbe369cc120e97628");
+
+ // check sm3 hash for "hello"
+ checkHash(
+ hasher,
+ "hello",
+ "becbbfaae6548b8bf0cfcad5a27183cd1be6093b1cceccc303d9c61d0a645268");
+
+ // check sm3 hash for empty string
+ checkHash(hasher, "", "1ab21d8355cfa17f8e61194831e81a8f22bec8c728fefb747ed035eb5082aa2b");
+ }
+
+ private void checkHash(Hash hasher, String message, String expectedHash) {
+ String calculatedHash = hasher.hash(message);
+ Assert.assertTrue(calculatedHash.equals(expectedHash));
+ byte[] calculatedHashBytes = hasher.hash(message.getBytes());
+ Assert.assertTrue(Hex.toHexString(calculatedHashBytes).equals(expectedHash));
+ }
+}
diff --git a/src/test/java/org/fisco/bcos/sdk/test/crypto/SignatureTest.java b/src/test/java/org/fisco/bcos/sdk/test/crypto/SignatureTest.java
new file mode 100644
index 000000000..cb67f18ce
--- /dev/null
+++ b/src/test/java/org/fisco/bcos/sdk/test/crypto/SignatureTest.java
@@ -0,0 +1,80 @@
+/**
+ * Copyright 2014-2020 [fisco-dev]
+ *
+ * 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 org.fisco.bcos.sdk.test.crypto;
+
+import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
+import org.fisco.bcos.sdk.crypto.keypair.ECDSAKeyPair;
+import org.fisco.bcos.sdk.crypto.keypair.SM2KeyPair;
+import org.fisco.bcos.sdk.crypto.signature.ECDSASignature;
+import org.fisco.bcos.sdk.crypto.signature.SM2Signature;
+import org.fisco.bcos.sdk.crypto.signature.Signature;
+import org.fisco.bcos.sdk.crypto.signature.SignatureResult;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class SignatureTest {
+ @Test
+ public void testECDSASignature() {
+ Signature ecdsaSignature = new ECDSASignature();
+ CryptoKeyPair keyPair = (new ECDSAKeyPair()).generateKeyPair();
+ testSignature(ecdsaSignature, keyPair);
+ }
+
+ @Test
+ public void testSM2Signature() {
+ Signature sm2Signature = new SM2Signature();
+ CryptoKeyPair keyPair = (new SM2KeyPair()).generateKeyPair();
+ testSignature(sm2Signature, keyPair);
+ }
+
+ private void testSignature(Signature signature, CryptoKeyPair keyPair) {
+ String message = "abcde";
+ // check valid case
+ for (int i = 0; i < 10; i++) {
+ message = "abcd----" + Integer.toString(i);
+ // sign
+ SignatureResult signResult = signature.sign(message, keyPair);
+ // verify
+ Assert.assertTrue(
+ signature.verify(
+ keyPair.getHexPublicKey(), message, signResult.convertToString()));
+ signResult = signature.sign(message.getBytes(), keyPair);
+ Assert.assertTrue(
+ signature.verify(
+ keyPair.getHexPublicKey(), message, signResult.convertToString()));
+ }
+
+ // check invalid case
+ for (int i = 0; i < 10; i++) {
+ message = "abcd----" + Integer.toString(i);
+ String invaidMessage = "abcd---" + Integer.toString(i + 1);
+ // sign
+ SignatureResult signResult = signature.sign(message, keyPair);
+ // verify
+ Assert.assertEquals(
+ false,
+ signature.verify(
+ keyPair.getHexPublicKey(),
+ invaidMessage,
+ signResult.convertToString()));
+ signResult = signature.sign(message.getBytes(), keyPair);
+ Assert.assertEquals(
+ false,
+ signature.verify(
+ keyPair.getHexPublicKey(),
+ invaidMessage,
+ signResult.convertToString()));
+ }
+ }
+}