Browse Source

merge the dev

tags/1.0.0
zhaoguangwei 6 years ago
parent
commit
624e1d8cc3
100 changed files with 5471 additions and 1149 deletions
  1. +2
    -0
      source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java
  2. +25
    -6
      source/base/src/main/java/com/jd/blockchain/provider/ProviderManager.java
  3. +1
    -1
      source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartMessageService.java
  4. +1
    -0
      source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployMojo.java
  5. +0
    -10
      source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/StringUtils.java
  6. +3
    -3
      source/contract/contract-maven-plugin/src/main/resources/sys-contract.properties
  7. +0
    -80
      source/contract/contract-tools/pom.xml
  8. +7
    -0
      source/crypto/crypto-adv/pom.xml
  9. +9
    -38
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/PaillierUtilsTest.java
  10. +6
    -0
      source/crypto/crypto-classic/pom.xml
  11. +4
    -4
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RSACryptoFunction.java
  12. +26
    -22
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java
  13. +49
    -0
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/SSHKeyParser.java
  14. +9
    -258
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/RSACryptoFunctionTest.java
  15. +30
    -62
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java
  16. +231
    -0
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/SSHKeyUtilsTest.java
  17. +38
    -0
      source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/Crypto.java
  18. +8
    -2
      source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoAlgorithm.java
  19. +13
    -25
      source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoAlgorithmDefinition.java
  20. +17
    -0
      source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoProvider.java
  21. +24
    -0
      source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoProviderInfo.java
  22. +34
    -0
      source/crypto/crypto-pki/pom.xml
  23. +26
    -0
      source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/PKIAlgorithm.java
  24. +38
    -0
      source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/PKICryptoService.java
  25. +220
    -0
      source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunction.java
  26. +220
    -0
      source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunction.java
  27. +236
    -0
      source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunction.java
  28. +129
    -0
      source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CSRBuilder.java
  29. +131
    -0
      source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CertParser.java
  30. +1
    -0
      source/crypto/crypto-pki/src/main/resources/META-INF/services/com.jd.blockchain.crypto.CryptoService
  31. +128
    -0
      source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunctionTest.java
  32. +128
    -0
      source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunctionTest.java
  33. +273
    -0
      source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunctionTest.java
  34. +396
    -0
      source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CSRBuilderTest.java
  35. +146
    -0
      source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CertParserTest.java
  36. +1
    -0
      source/crypto/pom.xml
  37. +0
    -67
      source/deployment/deployment-peer/src/main/resources/config/init/ledger-init.conf
  38. +97
    -0
      source/deployment/deployment-peer/src/main/resources/config/init/ledger.init
  39. +0
    -8
      source/deployment/deployment-peer/src/main/resources/config/init/local.conf
  40. +1
    -19
      source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceHandler.java
  41. +7
    -0
      source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java
  42. +53
    -2
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/CryptoConfig.java
  43. +3
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java
  44. +77
    -21
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerManager.java
  45. +62
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java
  46. +5
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java
  47. +14
    -0
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/AccountSetTest.java
  48. +13
    -0
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/BaseAccountTest.java
  49. +13
    -0
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerAdminAccountTest.java
  50. +13
    -0
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerEditerTest.java
  51. +12
    -0
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitOperationTest.java
  52. +15
    -2
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitSettingSerializeTest.java
  53. +16
    -0
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java
  54. +27
    -0
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerMetaDataTest.java
  55. +13
    -0
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTestUtils.java
  56. +26
    -0
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/MerkleDataSetTest.java
  57. +48
    -26
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractEventSendOperation.java
  58. +0
    -12
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/CryptoProviderInfo.java
  59. +13
    -1
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/CryptoSetting.java
  60. +26
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataVO.java
  61. +18
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVInfoVO.java
  62. +1
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantNode.java
  63. +21
    -21
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContent.java
  64. +36
    -36
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContentBody.java
  65. +5
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionState.java
  66. +2
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java
  67. +50
    -40
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractEventSendOpTemplate.java
  68. +4
    -3
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractEventSendOperationBuilderImpl.java
  69. +2
    -2
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOpTemplate.java
  70. +96
    -96
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxBuilder.java
  71. +91
    -91
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxContentBlob.java
  72. +132
    -0
      source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java
  73. +170
    -0
      source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java
  74. +72
    -6
      source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java
  75. +15
    -156
      source/peer/src/main/java/com/jd/blockchain/peer/web/ManagementController.java
  76. +14
    -8
      source/peer/src/main/java/com/jd/blockchain/peer/web/PeerTimeTasks.java
  77. +3
    -20
      source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/LedgerInitSettings.java
  78. +5
    -0
      source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java
  79. +6
    -1
      source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java
  80. +34
    -0
      source/state-transfer/pom.xml
  81. +75
    -0
      source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequence.java
  82. +53
    -0
      source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceElement.java
  83. +37
    -0
      source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceInfo.java
  84. +39
    -0
      source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceReader.java
  85. +59
    -0
      source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceReaderImpl.java
  86. +30
    -0
      source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java
  87. +142
    -0
      source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriterImpl.java
  88. +32
    -0
      source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/comparator/DataSequenceComparator.java
  89. +21
    -0
      source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/exception/DataSequenceException.java
  90. +80
    -0
      source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSDefaultMessageExecutor.java
  91. +34
    -0
      source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSMsgResolverFactory.java
  92. +28
    -0
      source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceLoadMessage.java
  93. +107
    -0
      source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgDecoder.java
  94. +133
    -0
      source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgEncoder.java
  95. +186
    -0
      source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSProcessManager.java
  96. +216
    -0
      source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSTransferProcess.java
  97. +45
    -0
      source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSDiffRequestResult.java
  98. +37
    -0
      source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSInfoResponseResult.java
  99. +155
    -0
      source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/StateTransferLayerTest.java
  100. +21
    -0
      source/stp/pom.xml

+ 2
- 0
source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java View File

@@ -68,6 +68,8 @@ public interface DataCodes {
// public static final int METADATA_PARTICIPANT_INFO = 0x640;

public static final int METADATA_CRYPTO_SETTING = 0x642;
public static final int METADATA_CRYPTO_SETTING_PROVIDER = 0x643;

// public static final int ACCOUNT = 0x700;



+ 25
- 6
source/base/src/main/java/com/jd/blockchain/provider/ProviderManager.java View File

@@ -4,6 +4,7 @@ import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -48,32 +49,45 @@ public final class ProviderManager {
* @return
*/
public <S> S getService(Class<S> serviceClazz, String providerName) {
NamedProviders<S> providers = getServiceProvider(serviceClazz);
NamedProviders<S> providers = getNamedProviders(serviceClazz);
return providers.getService(providerName);
}
public <S> Provider<S> getProvider(Class<S> serviceClazz, String providerName) {
@SuppressWarnings("unchecked")
NamedProviders<S> providers = (NamedProviders<S>) serviceProviders.get(serviceClazz);
if (providers == null) {
return null;
}
return providers.getProvider(providerName);
}

public <S> Collection<Provider<S>> getAllProviders(Class<S> serviceClazz) {
NamedProviders<S> providers = getServiceProvider(serviceClazz);
@SuppressWarnings("unchecked")
NamedProviders<S> providers = (NamedProviders<S>) serviceProviders.get(serviceClazz);
if (providers == null) {
return Collections.emptyList();
}
return providers.getProviders();
}

public <S> S installProvider(Class<S> serviceClazz, String providerFullName) {
NamedProviders<S> providers = getServiceProvider(serviceClazz);
NamedProviders<S> providers = getNamedProviders(serviceClazz);
return providers.install(providerFullName);
}

public <S> S installProvider(Class<S> service, String providerFullName, ClassLoader classLoader) {
NamedProviders<S> providers = getServiceProvider(service);
NamedProviders<S> providers = getNamedProviders(service);
return providers.install(providerFullName, classLoader);
}

public <S> void installAllProviders(Class<S> serviceClazz, ClassLoader classLoader) {
NamedProviders<S> providers = getServiceProvider(serviceClazz);
NamedProviders<S> providers = getNamedProviders(serviceClazz);
providers.installAll(classLoader);
}

@SuppressWarnings("unchecked")
private <S> NamedProviders<S> getServiceProvider(Class<S> serviceClazz) {
private <S> NamedProviders<S> getNamedProviders(Class<S> serviceClazz) {
NamedProviders<S> providers = (NamedProviders<S>) serviceProviders.get(serviceClazz);
if (providers == null) {
synchronized (mutex) {
@@ -189,6 +203,11 @@ public final class ProviderManager {
public Collection<Provider<S>> getProviders() {
return namedProviders.values();
}

public Provider<S> getProvider(String providerFullName) {
return namedProviders.get(providerFullName);
}

public S getService(String name) {
String fullName = shortNames.get(name);


+ 1
- 1
source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartMessageService.java View File

@@ -40,7 +40,7 @@ public class BftsmartMessageService implements MessageService {
asyncFuture.complete(result);

} catch (Exception e) {
throw new RuntimeException();
throw new RuntimeException(e);

} finally {
asyncPeerProxyPool.returnObject(asynchServiceProxy);


+ 1
- 0
source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployMojo.java View File

@@ -5,6 +5,7 @@ import com.jd.blockchain.crypto.PrivKey;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.tools.keygen.KeyGenCommand;
import com.jd.blockchain.utils.StringUtils;
import com.jd.blockchain.utils.codec.Base58Utils;
import com.jd.blockchain.utils.io.FileUtils;
import org.apache.maven.plugin.AbstractMojo;


+ 0
- 10
source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/StringUtils.java View File

@@ -1,10 +0,0 @@
package com.jd.blockchain;
/**
* @Author zhaogw
* @Date 2018/11/26 20:46
*/
public abstract class StringUtils {
public static boolean isEmpty(Object str) {
return str == null || "".equals(str);
}
}

+ 3
- 3
source/contract/contract-maven-plugin/src/main/resources/sys-contract.properties View File

@@ -1,9 +1,9 @@
#项目源文件存放的位置;
#PROJECT_BASE_DIR
PROJECT_BASE_DIR=E:\\gitCode\\block\\prototype\\
#合同使用的类库存放的位置,可能不在项目中,故采用全新的地址;
#LEDGER_BASE_CLASS_PATH
LEDGER_BASE_CLASS_PATH=E:\\gitCode\\block\\prototype\\libs\\

#为了测试,临时添加的变量;
#deploy and execute the contract;
cParam=com.jd.blockchain.contract.AssetContract3
sParam=E:\\gitCode\\block\\prototype\\source\\sdk\\contract-sample\\src\\main\\java\\
eParam=utf-8


+ 0
- 80
source/contract/contract-tools/pom.xml View File

@@ -1,80 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>contract</artifactId>
<version>0.9.0-SNAPSHOT</version>
</parent>
<artifactId>contract-tools</artifactId>

<dependencies>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>contract-compiler</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>contract-jar</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>

<!--<build>-->
<!--<plugins>-->
<!--<plugin>-->
<!--<groupId>org.apache.maven.plugins</groupId>-->
<!--<artifactId>maven-compiler-plugin</artifactId>-->
<!--<version>3.1</version>-->
<!--<configuration>-->
<!--<source>1.8</source>-->
<!--<target>1.8</target>-->
<!--<encoding>UTF-8</encoding>-->
<!--<compilerArgs>-->
<!--&lt;!&ndash;<arg>-verbose</arg>&ndash;&gt;-->
<!--&lt;!&ndash;<arg>-Xlint:unchecked</arg>&ndash;&gt;-->
<!--&lt;!&ndash;<arg>-Xlint:deprecation</arg>&ndash;&gt;-->
<!--&lt;!&ndash;<arg>-bootclasspath</arg>&ndash;&gt;-->
<!--&lt;!&ndash;<arg>${env.JAVA_HOME}/jre/lib/rt.jar</arg>&ndash;&gt;-->
<!--<arg>-extdirs</arg>-->
<!--<arg>${project.basedir}/../contract/contract-libs;$JAVA_HOME/jre/lib/ext</arg>-->
<!--</compilerArgs>-->
<!--</configuration>-->
<!--</plugin>-->
<!--</plugins>-->
<!--</build>-->
</project>

+ 7
- 0
source/crypto/crypto-adv/pom.xml View File

@@ -21,6 +21,13 @@
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.61</version>
</dependency>

<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>binary-proto</artifactId>


+ 9
- 38
source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/PaillierUtilsTest.java View File

@@ -19,7 +19,7 @@ import static org.junit.Assert.assertEquals;
*/
public class PaillierUtilsTest {
@Test
public void generateKeyPairTest() {
public void test() {

AsymmetricCipherKeyPair keyPair = PaillierUtils.generateKeyPair();
PaillierPublicKeyParameters pubKeyParams = (PaillierPublicKeyParameters) keyPair.getPublic();
@@ -58,13 +58,6 @@ public class PaillierUtilsTest {
assertEquals(pInverseConverted, pInverse);
assertEquals(muPConverted, muP);
assertEquals(muQConverted, muQ);
}

@Test
public void encryptTest() {

AsymmetricCipherKeyPair keyPair = PaillierUtils.generateKeyPair();
PaillierPublicKeyParameters pubKeyParams = (PaillierPublicKeyParameters) keyPair.getPublic();

byte[] pubKeyBytes = PaillierUtils.pubKey2Bytes(pubKeyParams);

@@ -77,23 +70,15 @@ public class PaillierUtilsTest {

assertEquals(512,ciphertextFromParams.length);
assertEquals(512,ciphertextFromBytes.length);
}

@Test
public void decryptTest(){

AsymmetricCipherKeyPair keyPair = PaillierUtils.generateKeyPair();
PaillierPublicKeyParameters pubKeyParams = (PaillierPublicKeyParameters) keyPair.getPublic();
PaillierPrivateKeyParameters privKeyParams = (PaillierPrivateKeyParameters) keyPair.getPrivate();

byte[] pubKeyBytes = PaillierUtils.pubKey2Bytes(pubKeyParams);
byte[] privKeyBytes = PaillierUtils.privKey2Bytes(privKeyParams);

int input = 666;
byte[] data = intToByteArray(input);
byte[] inputBytes = intToByteArray(input);

byte[] ciphertextFromParams = PaillierUtils.encrypt(data,pubKeyParams);
byte[] ciphertextFromBytes = PaillierUtils.encrypt(data,pubKeyBytes);
ciphertextFromParams = PaillierUtils.encrypt(inputBytes,pubKeyParams);
ciphertextFromBytes = PaillierUtils.encrypt(inputBytes,pubKeyBytes);

byte[] plaintextFromParams = PaillierUtils.decrypt(ciphertextFromBytes,privKeyParams);
byte[] plaintextFromBytes = PaillierUtils.decrypt(ciphertextFromParams,privKeyBytes);
@@ -103,16 +88,9 @@ public class PaillierUtilsTest {

assertEquals(input,outputFromParams);
assertEquals(input,outputFromBytes);
}

@Test
public void addTest() {

AsymmetricCipherKeyPair keyPair = PaillierUtils.generateKeyPair();
PaillierPublicKeyParameters pubKeyParams = (PaillierPublicKeyParameters) keyPair.getPublic();
PaillierPrivateKeyParameters privKeyParams = (PaillierPrivateKeyParameters) keyPair.getPrivate();

byte[] pubKeyBytes = PaillierUtils.pubKey2Bytes(pubKeyParams);
pubKeyBytes = PaillierUtils.pubKey2Bytes(pubKeyParams);

int input1 = 600;
int input2 = 60;
@@ -139,26 +117,19 @@ public class PaillierUtilsTest {

output = byteArrayToInt(plaintext);
assertEquals(sum,output);
}

@Test
public void scalarMultiplyTest() {

AsymmetricCipherKeyPair keyPair = PaillierUtils.generateKeyPair();
PaillierPublicKeyParameters pubKeyParams = (PaillierPublicKeyParameters) keyPair.getPublic();
PaillierPrivateKeyParameters privKeyParams = (PaillierPrivateKeyParameters) keyPair.getPrivate();

byte[] pubKeyBytes = PaillierUtils.pubKey2Bytes(pubKeyParams);
pubKeyBytes = PaillierUtils.pubKey2Bytes(pubKeyParams);

int input = 111;
input = 111;
int scalar = 6;
byte[] data = intToByteArray(input);
data = intToByteArray(input);

byte[] ciphertext = PaillierUtils.encrypt(data,pubKeyParams);
byte[] ciphertextPowered = PaillierUtils.scalarMultiply(pubKeyBytes,ciphertext,scalar);
byte[] plaintextMultiplied = PaillierUtils.decrypt(ciphertextPowered,privKeyParams);

int output = byteArrayToInt(plaintextMultiplied);
output = byteArrayToInt(plaintextMultiplied);
assertEquals(input * scalar, output);
}



+ 6
- 0
source/crypto/crypto-classic/pom.xml View File

@@ -15,6 +15,12 @@
<artifactId>crypto-framework</artifactId>
<version>${project.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.61</version>
</dependency>

</dependencies>
</project>

+ 4
- 4
source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RSACryptoFunction.java View File

@@ -21,11 +21,11 @@ public class RSACryptoFunction implements AsymmetricEncryptionFunction, Signatur

private static final CryptoAlgorithm RSA = ClassicAlgorithm.RSA;

// modulus.length = 256, publicExponent.length = 1
private static final int PUBKEY_SIZE = 257;
// modulus.length = 256, publicExponent.length = 1, privateExponent.length = 256, p.length = 128, q.length =128,
// modulus.length = 256, publicExponent.length = 3
private static final int PUBKEY_SIZE = 259;
// modulus.length = 256, publicExponent.length = 3, privateExponent.length = 256, p.length = 128, q.length =128,
// dP.length = 128, dQ.length = 128, qInv.length = 128
private static final int PRIVKEY_SIZE = 1153;
private static final int PRIVKEY_SIZE = 1155;

private static final int SIGNATUREDIGEST_SIZE = 256;
private static final int CIPHERTEXTBLOCK_SIZE = 256;


+ 26
- 22
source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java View File

@@ -60,6 +60,7 @@ public class RSAUtils {
private static final int QINV_LENGTH = 1024 / 8;

private static final BigInteger PUBEXP_0X03 = BigInteger.valueOf(0x03);
private static final BigInteger PUBEXP_0X010001 = BigInteger.valueOf(0x010001);

private static final BigInteger VERSION_2PRIMES = BigInteger.valueOf(0);

@@ -82,6 +83,21 @@ public class RSAUtils {
}

public static AsymmetricCipherKeyPair generateKeyPair(SecureRandom random){
AsymmetricCipherKeyPairGenerator kpGen = new RSAKeyPairGenerator();
kpGen.init(new RSAKeyGenerationParameters(PUBEXP_0X010001, random, KEYSIZEBITS, CERTAINTY));
return kpGen.generateKeyPair();
}

/**
* key pair generation with short public exponent, resulting in verifying and encrypting more efficiently
*
* @return key pair
*/
public static AsymmetricCipherKeyPair generateKeyPair_shortExp(){
return generateKeyPair_shortExp(new SecureRandom());
}

public static AsymmetricCipherKeyPair generateKeyPair_shortExp(SecureRandom random){
AsymmetricCipherKeyPairGenerator kpGen = new RSAKeyPairGenerator();
kpGen.init(new RSAKeyGenerationParameters(PUBEXP_0X03, random, KEYSIZEBITS, CERTAINTY));
return kpGen.generateKeyPair();
@@ -303,22 +319,16 @@ public class RSAUtils {

X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubKeyBytes);

KeyFactory keyFactory = null;
try {
keyFactory = KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e);
}
KeyFactory keyFactory;
RSAPublicKey publicKey;

RSAPublicKey publicKey = null;
try {
keyFactory = KeyFactory.getInstance("RSA");
publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
} catch (InvalidKeySpecException e) {
} catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e);
}

assert publicKey != null;

BigInteger exponent = publicKey.getPublicExponent();
BigInteger modulus = publicKey.getModulus();

@@ -414,7 +424,7 @@ public class RSAUtils {
BigInteger qInv = privKey.getQInv();

byte[] modulusBytes = bigInteger2Bytes(modulus,MODULUS_LENGTH);
byte[] pubExpBytes = pubExp.toByteArray();
byte[] pubExpBytes = pubExp.toByteArray();
byte[] privExpBytes = bigInteger2Bytes(privExp,PRIVEXP_LENGTH);
byte[] pBytes = bigInteger2Bytes(p,P_LENGTH);
byte[] qBytes = bigInteger2Bytes(q,Q_LENGTH);
@@ -446,22 +456,16 @@ public class RSAUtils {

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privKeyBytes);

KeyFactory keyFactory = null;
try {
keyFactory = KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e);
}

KeyFactory keyFactory;
RSAPrivateCrtKey privateKey;

try {
keyFactory = KeyFactory.getInstance("RSA");
privateKey = (RSAPrivateCrtKey) keyFactory.generatePrivate(keySpec);
} catch (InvalidKeySpecException e) {
} catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e);
}

assert privateKey != null;

BigInteger modulus = privateKey.getModulus();
BigInteger pubExp = privateKey.getPublicExponent();
BigInteger privExp = privateKey.getPrivateExponent();
@@ -524,7 +528,7 @@ public class RSAUtils {
result,0, length);
} else {
System.arraycopy(srcBytes,0,
result,length - srcLength, length);
result,length - srcLength, srcLength);
}

return result;


+ 49
- 0
source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/SSHKeyParser.java View File

@@ -0,0 +1,49 @@
package com.jd.blockchain.crypto.utils.classic;

import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.util.OpenSSHPublicKeyUtil;
import org.bouncycastle.jce.spec.OpenSSHPublicKeySpec;
import org.bouncycastle.util.encoders.Base64;

/**
* @author zhanglin33
* @title: SSHKeyParser
* @description: a parser for parsing asymmetric keys in Base64 format
* @date 2019-05-17, 17:52
*/
public class SSHKeyParser {

private String pubKeyFormat;
private String pubKeyType;

public AsymmetricKeyParameter pubKeyParse(String pubKeyStr) {

byte[] pubKeyBytes;

if (pubKeyStr.startsWith("ssh") || pubKeyStr.startsWith("ecdsa")) {
String[] algoAndKeyAndLocal = pubKeyStr.split(" ");
pubKeyBytes = Base64.decode(algoAndKeyAndLocal[1]);
} else {
pubKeyBytes = Base64.decode(pubKeyStr);
}

OpenSSHPublicKeySpec pubKeySpec = new OpenSSHPublicKeySpec(pubKeyBytes);

pubKeyFormat = pubKeySpec.getFormat();
pubKeyType = pubKeySpec.getType();

return OpenSSHPublicKeyUtil.parsePublicKey(pubKeyBytes);
}





public String getPubKeyFormat() {
return pubKeyFormat;
}

public String getPubKeyType() {
return pubKeyType;
}
}

+ 9
- 258
source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/RSACryptoFunctionTest.java View File

@@ -42,7 +42,7 @@ public class RSACryptoFunctionTest {
}

@Test
public void generateKeyPairTest() {
public void test() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);
@@ -55,15 +55,15 @@ public class RSACryptoFunctionTest {
PrivKey privKey = keyPair.getPrivKey();

assertEquals(PUBLIC.CODE, pubKey.getKeyType().CODE);
assertEquals(257, pubKey.getRawKeyBytes().length);
assertEquals(259, pubKey.getRawKeyBytes().length);
assertEquals(PRIVATE.CODE, privKey.getKeyType().CODE);
assertEquals(1153, privKey.getRawKeyBytes().length);
assertEquals(1155, privKey.getRawKeyBytes().length);

assertEquals(algorithm.code(), pubKey.getAlgorithm());
assertEquals(algorithm.code(), privKey.getAlgorithm());

assertEquals(2 + 1 + 257, pubKey.toBytes().length);
assertEquals(2 + 1 + 1153, privKey.toBytes().length);
assertEquals(2 + 1 + 259, pubKey.toBytes().length);
assertEquals(2 + 1 + 1155, privKey.toBytes().length);

byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm);
byte[] pubKeyTypeBytes = new byte[] { PUBLIC.CODE };
@@ -72,20 +72,7 @@ public class RSACryptoFunctionTest {
byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();
assertArrayEquals(BytesUtils.concat(algoBytes, pubKeyTypeBytes, rawPubKeyBytes), pubKey.toBytes());
assertArrayEquals(BytesUtils.concat(algoBytes, privKeyTypeBytes, rawPrivKeyBytes), privKey.toBytes());
}

@Test
public void retrievePubKeyTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();
PrivKey privKey = keyPair.getPrivKey();

PubKey retrievedPubKey = signatureFunction.retrievePubKey(privKey);

@@ -93,23 +80,12 @@ public class RSACryptoFunctionTest {
assertEquals(pubKey.getRawKeyBytes().length, retrievedPubKey.getRawKeyBytes().length);
assertEquals(pubKey.getAlgorithm(), retrievedPubKey.getAlgorithm());
assertArrayEquals(pubKey.toBytes(), retrievedPubKey.toBytes());
}

@Test
public void signTest() {

byte[] data = new byte[1024];
byte[] data = new byte[128];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PrivKey privKey = keyPair.getPrivKey();
SignatureDigest signatureDigest = signatureFunction.sign(privKey, data);

byte[] signatureBytes = signatureDigest.toBytes();
@@ -121,48 +97,16 @@ public class RSACryptoFunctionTest {
assertEquals((short) (SIGNATURE_ALGORITHM | ENCRYPTION_ALGORITHM | ASYMMETRIC_KEY | ((byte) 23 & 0x00FF)),
signatureDigest.getAlgorithm());

byte[] algoBytes = BytesUtils.toBytes(signatureDigest.getAlgorithm());
byte[] rawSinatureBytes = signatureDigest.getRawDigest();
assertArrayEquals(BytesUtils.concat(algoBytes, rawSinatureBytes), signatureBytes);
}

@Test
public void verifyTest() {
byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();
PrivKey privKey = keyPair.getPrivKey();
SignatureDigest signatureDigest = signatureFunction.sign(privKey, data);

assertTrue(signatureFunction.verify(signatureDigest, pubKey, data));
}

@Test
public void encryptTest() {

byte[] data = new byte[128];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

AsymmetricEncryptionFunction asymmetricEncryptionFunction = Crypto
.getAsymmetricEncryptionFunction(algorithm);

AsymmetricKeypair keyPair = asymmetricEncryptionFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();

Ciphertext ciphertext = asymmetricEncryptionFunction.encrypt(pubKey, data);

byte[] ciphertextBytes = ciphertext.toBytes();
@@ -172,90 +116,32 @@ public class RSACryptoFunctionTest {
assertEquals((short) (SIGNATURE_ALGORITHM | ENCRYPTION_ALGORITHM | ASYMMETRIC_KEY | ((byte) 23 & 0x00FF)),
ciphertext.getAlgorithm());

byte[] algoBytes = BytesUtils.toBytes(ciphertext.getAlgorithm());
byte[] rawCiphertextBytes = ciphertext.getRawCiphertext();
assertArrayEquals(BytesUtils.concat(algoBytes, rawCiphertextBytes), ciphertextBytes);
}

@Test
public void decryptTest() {

byte[] data = new byte[128];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

AsymmetricEncryptionFunction asymmetricEncryptionFunction = Crypto
.getAsymmetricEncryptionFunction(algorithm);

AsymmetricKeypair keyPair = asymmetricEncryptionFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();
PrivKey privKey = keyPair.getPrivKey();

Ciphertext ciphertext = asymmetricEncryptionFunction.encrypt(pubKey, data);

byte[] decryptedPlaintext = asymmetricEncryptionFunction.decrypt(privKey, ciphertext);

assertArrayEquals(data, decryptedPlaintext);
}

@Test
public void supportPrivKeyTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PrivKey privKey = keyPair.getPrivKey();
byte[] privKeyBytes = privKey.toBytes();

assertTrue(signatureFunction.supportPrivKey(privKeyBytes));

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm);
byte[] pubKeyTypeBytes = new byte[] { PUBLIC.CODE };
byte[] rawKeyBytes = privKey.getRawKeyBytes();
byte[] ripemd160PubKeyBytes = BytesUtils.concat(algoBytes, pubKeyTypeBytes, rawKeyBytes);

assertFalse(signatureFunction.supportPrivKey(ripemd160PubKeyBytes));
}

@Test
public void resolvePrivKeyTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PrivKey privKey = keyPair.getPrivKey();
byte[] privKeyBytes = privKey.toBytes();

PrivKey resolvedPrivKey = signatureFunction.resolvePrivKey(privKeyBytes);

assertEquals(PRIVATE.CODE, resolvedPrivKey.getKeyType().CODE);
assertEquals(1153, resolvedPrivKey.getRawKeyBytes().length);
assertEquals(1155, resolvedPrivKey.getRawKeyBytes().length);
assertEquals(ClassicAlgorithm.RSA.code(), resolvedPrivKey.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ENCRYPTION_ALGORITHM | ASYMMETRIC_KEY | ((byte) 23 & 0x00FF)),
resolvedPrivKey.getAlgorithm());
assertArrayEquals(privKeyBytes, resolvedPrivKey.toBytes());

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm);
byte[] pubKeyTypeBytes = new byte[] { PUBLIC.CODE };
byte[] rawKeyBytes = privKey.getRawKeyBytes();
byte[] ripemd160PubKeyBytes = BytesUtils.concat(algoBytes, pubKeyTypeBytes, rawKeyBytes);

Class<?> expectedException = CryptoException.class;
Exception actualEx = null;
try {
@@ -265,64 +151,26 @@ public class RSACryptoFunctionTest {
}
assertNotNull(actualEx);
assertTrue(expectedException.isAssignableFrom(actualEx.getClass()));
}

@Test
public void supportPubKeyTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();
byte[] pubKeyBytes = pubKey.toBytes();

assertTrue(signatureFunction.supportPubKey(pubKeyBytes));

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm);
byte[] privKeyTypeBytes = new byte[] { PRIVATE.CODE };
byte[] rawKeyBytes = pubKey.getRawKeyBytes();
byte[] ripemd160PrivKeyBytes = BytesUtils.concat(algoBytes, privKeyTypeBytes, rawKeyBytes);

assertFalse(signatureFunction.supportPubKey(ripemd160PrivKeyBytes));
}

@Test
public void resolvePubKeyTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();
byte[] pubKeyBytes = pubKey.toBytes();

PubKey resolvedPubKey = signatureFunction.resolvePubKey(pubKeyBytes);

assertEquals(PUBLIC.CODE, resolvedPubKey.getKeyType().CODE);
assertEquals(257, resolvedPubKey.getRawKeyBytes().length);
assertEquals(259, resolvedPubKey.getRawKeyBytes().length);
assertEquals(ClassicAlgorithm.RSA.code(), resolvedPubKey.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ENCRYPTION_ALGORITHM | ASYMMETRIC_KEY | ((byte) 23 & 0x00FF)),
resolvedPubKey.getAlgorithm());
assertArrayEquals(pubKeyBytes, resolvedPubKey.toBytes());

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm);
byte[] privKeyTypeBytes = new byte[] { PRIVATE.CODE };
byte[] rawKeyBytes = pubKey.getRawKeyBytes();
byte[] ripemd160PrivKeyBytes = BytesUtils.concat(algoBytes, privKeyTypeBytes, rawKeyBytes);

Class<?> expectedException = CryptoException.class;
Exception actualEx = null;
try {
signatureFunction.resolvePrivKey(ripemd160PrivKeyBytes);
} catch (Exception e) {
@@ -330,57 +178,18 @@ public class RSACryptoFunctionTest {
}
assertNotNull(actualEx);
assertTrue(expectedException.isAssignableFrom(actualEx.getClass()));
}

@Test
public void supportDigestTest() {

byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PrivKey privKey = keyPair.getPrivKey();

SignatureDigest signatureDigest = signatureFunction.sign(privKey, data);

byte[] signatureDigestBytes = signatureDigest.toBytes();
assertTrue(signatureFunction.supportDigest(signatureDigestBytes));

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm);
byte[] rawDigestBytes = signatureDigest.toBytes();
byte[] ripemd160SignatureBytes = BytesUtils.concat(algoBytes, rawDigestBytes);

assertFalse(signatureFunction.supportDigest(ripemd160SignatureBytes));
}

@Test
public void resolveDigestTest() {

byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PrivKey privKey = keyPair.getPrivKey();

SignatureDigest signatureDigest = signatureFunction.sign(privKey, data);

byte[] signatureDigestBytes = signatureDigest.toBytes();

SignatureDigest resolvedSignatureDigest = signatureFunction.resolveDigest(signatureDigestBytes);

@@ -392,12 +201,8 @@ public class RSACryptoFunctionTest {

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm);
byte[] rawDigestBytes = signatureDigest.getRawDigest();
byte[] ripemd160SignatureDigestBytes = BytesUtils.concat(algoBytes, rawDigestBytes);

Class<?> expectedException = CryptoException.class;
Exception actualEx = null;
try {
signatureFunction.resolveDigest(ripemd160SignatureDigestBytes);
} catch (Exception e) {
@@ -405,77 +210,24 @@ public class RSACryptoFunctionTest {
}
assertNotNull(actualEx);
assertTrue(expectedException.isAssignableFrom(actualEx.getClass()));
}

@Test
public void supportCiphertextTest() {

byte[] data = new byte[128];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

AsymmetricEncryptionFunction asymmetricEncryptionFunction = Crypto
.getAsymmetricEncryptionFunction(algorithm);

AsymmetricKeypair keyPair = asymmetricEncryptionFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();

Ciphertext ciphertext = asymmetricEncryptionFunction.encrypt(pubKey, data);

byte[] ciphertextBytes = ciphertext.toBytes();

assertTrue(asymmetricEncryptionFunction.supportCiphertext(ciphertextBytes));

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm);
byte[] rawCiphertextBytes = ciphertext.toBytes();
algoBytes = CryptoAlgorithm.getCodeBytes(algorithm);
byte[] ripemd160CiphertextBytes = BytesUtils.concat(algoBytes, rawCiphertextBytes);

assertFalse(asymmetricEncryptionFunction.supportCiphertext(ripemd160CiphertextBytes));
}

@Test
public void resolveCiphertextTest() {

byte[] data = new byte[128];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

AsymmetricEncryptionFunction asymmetricEncryptionFunction = Crypto
.getAsymmetricEncryptionFunction(algorithm);

AsymmetricKeypair keyPair = asymmetricEncryptionFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();

Ciphertext ciphertext = asymmetricEncryptionFunction.encrypt(pubKey, data);

byte[] ciphertextBytes = ciphertext.toBytes();

Ciphertext resolvedCiphertext = asymmetricEncryptionFunction.resolveCiphertext(ciphertextBytes);

assertEquals(256, resolvedCiphertext.getRawCiphertext().length);
assertEquals(ClassicAlgorithm.RSA.code(), resolvedCiphertext.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ENCRYPTION_ALGORITHM | ASYMMETRIC_KEY | ((byte) 23 & 0x00FF)),
resolvedCiphertext.getAlgorithm());
assertArrayEquals(ciphertextBytes, resolvedCiphertext.toBytes());

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm);
byte[] rawCiphertextBytes = ciphertext.getRawCiphertext();
byte[] ripemd160CiphertextBytes = BytesUtils.concat(algoBytes, rawCiphertextBytes);

Class<?> expectedException = CryptoException.class;
Exception actualEx = null;
try {
asymmetricEncryptionFunction.resolveCiphertext(ripemd160CiphertextBytes);
} catch (Exception e) {
@@ -484,5 +236,4 @@ public class RSACryptoFunctionTest {
assertNotNull(actualEx);
assertTrue(expectedException.isAssignableFrom(actualEx.getClass()));
}

}

+ 30
- 62
source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java View File

@@ -1,16 +1,22 @@
package test.com.jd.blockchain.crypto.utils.classic;

import com.jd.blockchain.crypto.utils.classic.RSAUtils;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil;
import org.bouncycastle.util.encoders.Hex;
import org.junit.Test;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.IOException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
@@ -27,10 +33,20 @@ import static org.junit.Assert.*;
public class RSAUtilsTest {

@Test
public void generateKeyPairTest(){
public void generateKeyPairTest() {
AsymmetricCipherKeyPair kp = RSAUtils.generateKeyPair();
RSAKeyParameters pubKey = (RSAKeyParameters) kp.getPublic();
RSAPrivateCrtKeyParameters privKey = (RSAPrivateCrtKeyParameters) kp.getPrivate();
keyPairTest(kp);
}

@Test
public void generateKeyPair_ShortExpTest() {
AsymmetricCipherKeyPair kp = RSAUtils.generateKeyPair_shortExp();
keyPairTest(kp);
}

private void keyPairTest(AsymmetricCipherKeyPair keyPair) {
RSAKeyParameters pubKey = (RSAKeyParameters) keyPair.getPublic();
RSAPrivateCrtKeyParameters privKey = (RSAPrivateCrtKeyParameters) keyPair.getPrivate();

byte[] pubKeyBytes_RawKey = RSAUtils.pubKey2Bytes_RawKey(pubKey);
byte[] pubKeyBytesConverted_RawKey =
@@ -42,9 +58,6 @@ public class RSAUtilsTest {
RSAUtils.privKey2Bytes_RawKey(RSAUtils.bytes2PrivKey_RawKey(privKeyBytes_RawKey));
assertArrayEquals(privKeyBytes_RawKey,privKeyBytesConverted_RawKey);

System.out.println(pubKeyBytes_RawKey.length);
System.out.println(privKeyBytes_RawKey.length);

byte[] pubKeyBytes_PKCS1 = RSAUtils.pubKey2Bytes_PKCS1(pubKey);
byte[] pubKeyBytesConverted_PKCS1 =
RSAUtils.pubKey2Bytes_PKCS1(RSAUtils.bytes2PubKey_PKCS1(pubKeyBytes_PKCS1));
@@ -67,7 +80,7 @@ public class RSAUtilsTest {
}

@Test
public void retrievePublicKeyTest(){
public void test(){

AsymmetricCipherKeyPair kp = RSAUtils.generateKeyPair();
RSAKeyParameters pubKey = (RSAKeyParameters) kp.getPublic();
@@ -78,38 +91,17 @@ public class RSAUtilsTest {
byte[] retrievedPubKeyBytes = RSAUtils.retrievePublicKey(privKeyBytes);

assertArrayEquals(pubKeyBytes,retrievedPubKeyBytes);
}

@Test
public void signTest(){

byte[] data = new byte[1024];
byte[] data = new byte[128];
Random random = new Random();
random.nextBytes(data);

AsymmetricCipherKeyPair keyPair = RSAUtils.generateKeyPair();
AsymmetricKeyParameter privKey = keyPair.getPrivate();
byte[] privKeyBytes = RSAUtils.privKey2Bytes_RawKey((RSAPrivateCrtKeyParameters) privKey);

byte[] signatureFromPrivKey = RSAUtils.sign(data, privKey);
byte[] signatureFromPrivKeyBytes = RSAUtils.sign(data, privKeyBytes);

assertNotNull(signatureFromPrivKey);
assertEquals(2048 / 8, signatureFromPrivKey.length);
assertArrayEquals(signatureFromPrivKeyBytes,signatureFromPrivKey);
}

@Test
public void verifyTest(){

byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);

AsymmetricCipherKeyPair keyPair = RSAUtils.generateKeyPair();
AsymmetricKeyParameter privKey = keyPair.getPrivate();
AsymmetricKeyParameter pubKey = keyPair.getPublic();
byte[] pubKeyBytes = RSAUtils.pubKey2Bytes_RawKey((RSAKeyParameters) pubKey);

byte[] signature = RSAUtils.sign(data,privKey);

@@ -118,47 +110,23 @@ public class RSAUtilsTest {

assertTrue(isValidFromPubKey);
assertTrue(isValidFromPubKeyBytes);
}

@Test
public void encryptTest(){

byte[] data = new byte[246];
Random random = new Random();
random.nextBytes(data);

AsymmetricCipherKeyPair keyPair = RSAUtils.generateKeyPair();
AsymmetricKeyParameter pubKey = keyPair.getPublic();
byte[] pubKeyBytes = RSAUtils.pubKey2Bytes_RawKey((RSAKeyParameters) pubKey);

byte[] ciphertextFromPubKey = RSAUtils.encrypt(data,pubKey);
byte[] ciphertextFromPubKeyBytes = RSAUtils.encrypt(data,pubKeyBytes);

assertEquals(512,ciphertextFromPubKey.length);
assertEquals(512,ciphertextFromPubKeyBytes.length);
}

@Test
public void decryptTest(){
assertEquals(256,ciphertextFromPubKey.length);
assertEquals(256,ciphertextFromPubKeyBytes.length);

AsymmetricCipherKeyPair keyPair = RSAUtils.generateKeyPair();
AsymmetricKeyParameter pubKey = keyPair.getPublic();
AsymmetricKeyParameter privKey = keyPair.getPrivate();
byte[] privKeyBytes = RSAUtils.privKey2Bytes_RawKey((RSAPrivateCrtKeyParameters) privKey);

byte[] data;
for (int i = 1; i < 1024; i++) {
data = new byte[i];
Random random = new Random();
random.nextBytes(data);
byte[] ciphertext = RSAUtils.encrypt(data, pubKey);
data = new byte[1024];
random.nextBytes(data);
byte[] ciphertext = RSAUtils.encrypt(data, pubKey);

byte[] plaintextFromPrivKey = RSAUtils.decrypt(ciphertext, privKey);
byte[] plaintextFromPrivKeyBytes = RSAUtils.decrypt(ciphertext, privKeyBytes);
byte[] plaintextFromPrivKey = RSAUtils.decrypt(ciphertext, privKey);
byte[] plaintextFromPrivKeyBytes = RSAUtils.decrypt(ciphertext, privKeyBytes);

assertArrayEquals(data, plaintextFromPrivKey);
assertArrayEquals(data, plaintextFromPrivKeyBytes);
}
assertArrayEquals(data, plaintextFromPrivKey);
assertArrayEquals(data, plaintextFromPrivKeyBytes);
}




+ 231
- 0
source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/SSHKeyUtilsTest.java View File

@@ -0,0 +1,231 @@
//package test.com.jd.blockchain.crypto.utils.classic;
//
//import com.jd.blockchain.crypto.utils.classic.SSHKeyParser;
//import org.bouncycastle.asn1.ASN1Sequence;
//import org.bouncycastle.crypto.params.RSAKeyParameters;
//import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
//import org.bouncycastle.crypto.util.OpenSSHPrivateKeyUtil;
//import org.bouncycastle.crypto.util.OpenSSHPublicKeyUtil;
//import org.bouncycastle.jce.spec.OpenSSHPrivateKeySpec;
//import org.bouncycastle.jce.spec.OpenSSHPublicKeySpec;
//import org.bouncycastle.util.Strings;
//import org.bouncycastle.util.encoders.Base64;
//import org.bouncycastle.util.encoders.Hex;
//import org.bouncycastle.util.io.pem.PemReader;
//import org.junit.Test;
//
//import java.io.IOException;
//import java.io.StringReader;
//import java.math.BigInteger;
//
//import static org.junit.Assert.assertEquals;
//
///**
// * @author zhanglin33
// * @title: SSHKeyUtilsTest
// * @description: Tests for methods in SSHKeyUtils
// * @date 2019-05-07, 15:14
// */
//public class SSHKeyUtilsTest {
//
// @Test
// public void parseRSAPublicKeyTest() {
//
// String pubKeyStr = "AAAAB3NzaC1yc2EAAAADAQABAAABAQCYwLN4EXy7g0Xugv4lQfoujbARi48gPSxVupt" +
// "GsSoGqsS00e9rA7v0qzFKa9Zhnw1WkjCnEXRYAMiCAJYkM/mGI8mb3qkcdNhGWZmPnopV+D46CTFB1" +
// "4yeR9mjoOPXs4pjX3zGveKx5Nx8jvdoFewbTCtdN0x1XWTjNT5bXqP/4gXkLENEU5tLsWVAOu0ME/N" +
// "e/9gMujAtDoolJ181a9P06bvEpIw5cLtUnsm5CtvBuiL7WBXxDJ/IASJrKNGBdK8xib1+Kb8tNLAT6" +
// "Dj25BwylqiRNhb5l1Ni4aKrE2FqSEc5Nx5+csQMEl9MBJ3pEsLHBNbohDL+jbwLguRVD6CJ";
//
// BigInteger exponent = new BigInteger("010001",16);
// BigInteger modulus = new BigInteger("0098c0b378117cbb8345ee82fe2541fa2e8db0118b8f2" +
// "03d2c55ba9b46b12a06aac4b4d1ef6b03bbf4ab314a6bd6619f0d569230a711745800c88200962" +
// "433f98623c99bdea91c74d84659998f9e8a55f83e3a093141d78c9e47d9a3a0e3d7b38a635f7cc" +
// "6bde2b1e4dc7c8ef76815ec1b4c2b5d374c755d64e3353e5b5ea3ffe205e42c4344539b4bb1654" +
// "03aed0c13f35effd80cba302d0e8a25275f356bd3f4e9bbc4a48c3970bb549ec9b90adbc1ba22f" +
// "b5815f10c9fc801226b28d18174af3189bd7e29bf2d34b013e838f6e41c3296a8913616f997536" +
// "2e1a2ab13616a484739371e7e72c40c125f4c049de912c2c704d6e88432fe8dbc0b82e4550fa089",16);
// String pubKeyFormat = "OpenSSH";
// String pubKeyType = "ssh-rsa";
//
// SSHKeyParser parser = new SSHKeyParser();
//
// RSAKeyParameters pubKey = (RSAKeyParameters) parser.pubKeyParse(pubKeyStr);
// BigInteger e = pubKey.getExponent();
// BigInteger n = pubKey.getModulus();
// assertEquals(exponent,e);
// assertEquals(modulus,n);
// assertEquals(pubKeyFormat,parser.getPubKeyFormat());
// assertEquals(pubKeyType,parser.getPubKeyType());
//
// String pubKeyStrWithHead = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCYwLN4EXy7g0Xugv4lQfou" +
// "jbARi48gPSxVuptGsSoGqsS00e9rA7v0qzFKa9Zhnw1WkjCnEXRYAMiCAJYkM/mGI8mb3qkcdNhGWZm" +
// "PnopV+D46CTFB14yeR9mjoOPXs4pjX3zGveKx5Nx8jvdoFewbTCtdN0x1XWTjNT5bXqP/4gXkLENEU5" +
// "tLsWVAOu0ME/Ne/9gMujAtDoolJ181a9P06bvEpIw5cLtUnsm5CtvBuiL7WBXxDJ/IASJrKNGBdK8xi" +
// "b1+Kb8tNLAT6Dj25BwylqiRNhb5l1Ni4aKrE2FqSEc5Nx5+csQMEl9MBJ3pEsLHBNbohDL+jbwLguRV" +
// "D6CJ zhanglin33@zhanglin33.local\n";
// pubKey = (RSAKeyParameters) parser.pubKeyParse(pubKeyStrWithHead);
// e = pubKey.getExponent();
// n = pubKey.getModulus();
// assertEquals(exponent,e);
// assertEquals(modulus,n);
// assertEquals(pubKeyFormat,parser.getPubKeyFormat());
// assertEquals(pubKeyType,parser.getPubKeyType());
// }
//
// @Test
// public void parseRSAPrivateKeyTest() {
//
// String str2 = "-----BEGIN OPENSSH PRIVATE KEY-----\n" +
// "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn\n" +
// "NhAAAAAwEAAQAAAQEAwFyeWgHFu/ZMvqWa28QUGlKMDV7vpbzT7kyA/4yuotfprZKHNeEy\n" +
// "GugleJ/Kv5kqHh8Km4IZcfNcerTYds+U5m/uX4bSYpEbXco3DQ2lYQbYo7PBWwPMq2aIdd\n" +
// "i7WxUAlt0z1ugLNimskPzJ7DNra+ax0Wh9RnMsjZkfuBZiKq7wbBm7NyJmpg2B7xo5cz+G\n" +
// "Lw9e0tDlvgeLe+n68WvYWWFP59mfP6Qoy+NwjQnnwrhJi2j4dEexO97KmgnJhL07lu4eCQ\n" +
// "fdv68Tai9+aeDNawe7nmFYf2eNjah2jW/DwOwA/ErXnvgjLSMsgc6WGKfokhytAOFDGgvH\n" +
// "KKNd6BMYZwAAA9A7JircOyYq3AAAAAdzc2gtcnNhAAABAQDAXJ5aAcW79ky+pZrbxBQaUo\n" +
// "wNXu+lvNPuTID/jK6i1+mtkoc14TIa6CV4n8q/mSoeHwqbghlx81x6tNh2z5Tmb+5fhtJi\n" +
// "kRtdyjcNDaVhBtijs8FbA8yrZoh12LtbFQCW3TPW6As2KayQ/MnsM2tr5rHRaH1GcyyNmR\n" +
// "+4FmIqrvBsGbs3ImamDYHvGjlzP4YvD17S0OW+B4t76frxa9hZYU/n2Z8/pCjL43CNCefC\n" +
// "uEmLaPh0R7E73sqaCcmEvTuW7h4JB92/rxNqL35p4M1rB7ueYVh/Z42NqHaNb8PA7AD8St\n" +
// "ee+CMtIyyBzpYYp+iSHK0A4UMaC8coo13oExhnAAAAAwEAAQAAAQAEEvIXnen+LR06/G7n\n" +
// "MKPsWss0jUouDG3AokYpI2WfdUsxreTHM1nIUBpbD6dPn4LQ2H91A7BeRXUz9BiRi5vvtX\n" +
// "cq9sQF6mTV+65mzF8wSuDTtr7lmpL/HlDNjiWJrEwy5cRvTMLQBtnsyC3OntgrlNs3QCtH\n" +
// "DrFm3lNZpr+1f62Vu43dbcTPvLwcc335cJ73BU5WsMGaouCAqVXsVsgfkA66u6+gQs8O3F\n" +
// "IQntdzS8vYpkzH8N9qqNZit7kbFCRUTI7CDLHquJmclzB8uVwO0pR5+Aross+YL3QxPZoJ\n" +
// "+LXLlCi27oSmYk3fx3uh0XwwO3JFDQpeCxOuEsZbOy8BAAAAgCsktFksS0BViRuLyzC2H7\n" +
// "X7Uonf+dr8e4Yn+RgR329KFh/ok28/KZndZHsUnhdmiIjPr+SplFZZMrV/uJDkGezUNWGf\n" +
// "8qn+eEglm7nYfVf2EXTVNhpg8yfPChx90ybc8GYlqpEqf7LiCuEBCPqPJgq6K7i6UKbwn2\n" +
// "SfqUOBcz5BAAAAgQDqszdiNv0cTvZ/Xg3qJPsHXqQuLBYoe2vhU+Pipt9HviruUD1y3Mso\n" +
// "rOL9QBwjE7szGnwVE00J0mLp+s309+kftADLXqMyqFYiy7S8GIWQw0YNB2m8yjq+phHbBm\n" +
// "/Gs2P4+s8yKTcVJvMTyWr02rpCHiLTKDHoXPJcJ8yVMTHFRwAAAIEA0dHB9fXiesEKfwcp\n" +
// "X11IHAV8pTd+7VN81oGwxtRg88U7H2rmQFCxSZah2O/OCCmYLH3PHT95qnMHHqzcsVvoIy\n" +
// "7AfnMpp4KYU0Ic3aFuRjZk2sDsYUniPcCpuCvs8Jb75sDwKDW2EM8MowiNylDnYMmfYj0l\n" +
// "gIhz1/p79hXEI+EAAAAbemhhbmdsaW4zM0B6aGFuZ2xpbjMzLmxvY2Fs\n" +
// "-----END OPENSSH PRIVATE KEY-----";
//
// byte[] Bytes2 = null;
// try {
// Bytes2 = new PemReader(new StringReader(str2)).readPemObject().getContent();
// } catch (IOException e1) {
// e1.printStackTrace();
// }
// assert Bytes2 != null;
// System.out.println(Hex.toHexString(Bytes2));
//
// String str3 = "-----BEGIN OPENSSH PRIVATE KEY-----\n" +
// "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn\n" +
// "NhAAAAAwEAAQAAAQEAvummQZm1FUFc/cV5nQBeowhjX4vIU4kBmyPmXHMViX4ORvWvD1yi\n" +
// "oxcaawPpP9QconpzjdCrNbmw0oZNt9UKlmrOU34YTRD5LFlEVOYjr/21/SO5yDGog8xJBU\n" +
// "HQYnXY5L2q9EXKOF45e5P6gSGUovrhePEsaniuQN48GIObPCOFkEN0ZV2DqRsn3It1vY+D\n" +
// "GiSb5EaZ2sNkudyzYfgFxcCbqBXmDa1WeyX5xYh8wldBJLUH+pO4gPoTXXX4UI4yNdDmPD\n" +
// "BWFvPVIOdpfdBnDbEp1AoE5Jx/+tbwFBIEvTPOECtOUKDGIlXXIH0I4waHbwf6EnHD5+BR\n" +
// "N0XwrzSkuwAAA9DYV/7H2Ff+xwAAAAdzc2gtcnNhAAABAQC+6aZBmbUVQVz9xXmdAF6jCG\n" +
// "Nfi8hTiQGbI+ZccxWJfg5G9a8PXKKjFxprA+k/1ByienON0Ks1ubDShk231QqWas5TfhhN\n" +
// "EPksWURU5iOv/bX9I7nIMaiDzEkFQdBiddjkvar0Rco4Xjl7k/qBIZSi+uF48SxqeK5A3j\n" +
// "wYg5s8I4WQQ3RlXYOpGyfci3W9j4MaJJvkRpnaw2S53LNh+AXFwJuoFeYNrVZ7JfnFiHzC\n" +
// "V0EktQf6k7iA+hNddfhQjjI10OY8MFYW89Ug52l90GcNsSnUCgTknH/61vAUEgS9M84QK0\n" +
// "5QoMYiVdcgfQjjBodvB/oSccPn4FE3RfCvNKS7AAAAAwEAAQAAAQArRruxUy6BSvfRbtpK\n" +
// "hLLvMg+UsRMQHJaInHKzskLHkBOcckTkrpMPdUU/zPsqxOJY0nkvRIYK/7TdhCRJ77ker8\n" +
// "dllcfccGSLcRDUTfb5BgIjB94tS1Rvy/chgfHC4APyliwSg197t6BAKyM18m7HIyfJSqJO\n" +
// "4FxfyADHbc3aq654tu+eaUtD7TEN1bH6PKMDvwSioMLgKU43GQeDJZbqamBE9y+KVhVx9y\n" +
// "3DEHrOPkRkZIG33y9j7B/i0vl+WnwUTzmLGRR0U6J9wrzyANL8ODYaAvk4FvUED8hQ72jh\n" +
// "NpAXsSgf6COUE1sUnO5DOwN1zHBNHaSo73Qu7aKZtL4BAAAAgDBW3ItiqU9Ip34KtLaayK\n" +
// "/BkRDDwFNvAxpOw9alpfbLGF5xbVjRN4wy7HJ4eA+7JJnx6A6xYrzykbPP+dnUnfzYuxH8\n" +
// "MrihOkYipw1VaR6/0XH+apmE1SmotuYbl+bpl9dlZYUI0pJ8wldqoDCNlSOcLy77HnKwu9\n" +
// "GpJx9KmW9WAAAAgQDdnrwfVv5trAuZZIcw2vLRWhoDT196k/Ty1GP4zFpDttb8OyZ8Ygpx\n" +
// "oA5PhYyl5M1g/2oR/Rpp3vfKDVThfn/bCnMtAbUHMfvYK3Oufvq5JmzT1rgGr3MEek+JBR\n" +
// "O17I87m4GE7iM1LzCUs2G/fKt2uoVXdniv0Vn0iCiZZc7JmwAAAIEA3IdsccarkUfFcQ2c\n" +
// "4TdHrx/RGmoTAO6k1xOHXZjWPmerinuOspIJL/ymWfqIxABCjub3UHyP7ap+1+AAnk+TMU\n" +
// "eR3tLEp9tRM6n0Td56DnQ9Q+RZhPqR486/teZ33cMBMHg52aIs/3AzMpK9xTFCRgqsKa6e\n" +
// "ednMB4Q1txvHU2EAAAAbemhhbmdsaW4zM0B6aGFuZ2xpbjMzLmxvY2Fs\n" +
// "-----END OPENSSH PRIVATE KEY-----";
//
// byte[] Bytes3 = null;
// try {
// Bytes3 = new PemReader(new StringReader(str3)).readPemObject().getContent();
// } catch (IOException e1) {
// e1.printStackTrace();
// }
// assert Bytes3 != null;
// System.out.println(Hex.toHexString(Bytes3));
//// System.out.println(Hex.toHexString(Base64.decode("oNE9iA4ZyuZLbpEL7B29NaxGi4puT2Y5RDaMoEkoAKI")));
//// String test = "1ac477fa";
//// byte[] testBytes = Hex.decode(test);
////
//// System.out.println(Base64.toBase64String(testBytes));
//
// byte[] AUTH_MAGIC = Strings.toByteArray("openssh-key-v1\0");
// System.out.println(Hex.toHexString(AUTH_MAGIC));
// System.out.println(Base64.toBase64String(AUTH_MAGIC));
// String privKeyStr = "-----BEGIN OPENSSH PRIVATE KEY-----\n" +
// "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn\n" +
// "NhAAAAAwEAAQAAAQEAmMCzeBF8u4NF7oL+JUH6Lo2wEYuPID0sVbqbRrEqBqrEtNHvawO7\n" +
// "9KsxSmvWYZ8NVpIwpxF0WADIggCWJDP5hiPJm96pHHTYRlmZj56KVfg+OgkxQdeMnkfZo6\n" +
// "Dj17OKY198xr3iseTcfI73aBXsG0wrXTdMdV1k4zU+W16j/+IF5CxDRFObS7FlQDrtDBPz\n" +
// "Xv/YDLowLQ6KJSdfNWvT9Om7xKSMOXC7VJ7JuQrbwboi+1gV8QyfyAEiayjRgXSvMYm9fi\n" +
// "m/LTSwE+g49uQcMpaokTYW+ZdTYuGiqxNhakhHOTcefnLEDBJfTASd6RLCxwTW6IQy/o28\n" +
// "C4LkVQ+giQAAA9AaxHf6GsR3+gAAAAdzc2gtcnNhAAABAQCYwLN4EXy7g0Xugv4lQfoujb\n" +
// "ARi48gPSxVuptGsSoGqsS00e9rA7v0qzFKa9Zhnw1WkjCnEXRYAMiCAJYkM/mGI8mb3qkc\n" +
// "dNhGWZmPnopV+D46CTFB14yeR9mjoOPXs4pjX3zGveKx5Nx8jvdoFewbTCtdN0x1XWTjNT\n" +
// "5bXqP/4gXkLENEU5tLsWVAOu0ME/Ne/9gMujAtDoolJ181a9P06bvEpIw5cLtUnsm5CtvB\n" +
// "uiL7WBXxDJ/IASJrKNGBdK8xib1+Kb8tNLAT6Dj25BwylqiRNhb5l1Ni4aKrE2FqSEc5Nx\n" +
// "5+csQMEl9MBJ3pEsLHBNbohDL+jbwLguRVD6CJAAAAAwEAAQAAAQARfhfPSylei9TpUGTs\n" +
// "PVb6F82u5K16QqceFiWL/ePTKaEnF9d0CNRwW15kqF6/hShQ3qLlrvEE1uofQRPwh2cuvl\n" +
// "BrIh95m8PcoowcT0qGN8xgdwcGBDodMhsxSs5suCnD4X53f+1C8/Nv7CtW5xPHuHxKy3dd\n" +
// "BVn1TvaaHgdn2PwJVKtZp+WVG3/UHr25nFHd8mYgpeHZqK9AW16N0UEMXMM1u8ZCubVOoS\n" +
// "IGuMAXpTug0xA+BXHo17FcDGKSzcXFzh+urIz5glRp5zFioHBqxNmkKfQkG6C7UxnPGyS/\n" +
// "/J+3lL2lvl0G8kO/5EDFMBhTMEy1NeR2b629S4G1qUxVAAAAgHDwE9kPiVETcxSzI4wotT\n" +
// "1Ee9nKVVD3oGdRqefvX7EUR8bvdv4nCqHPNBx8C6l8zo7fsQD81YL85F4eWbtrdxEijRHX\n" +
// "5m7J/muh/laY1Hq43WCkZGboO4fZ2HHi7oN096FqrKRpvbQGQi1FLbcISUdsitwrs6ywn3\n" +
// "fNx3q+X3V6AAAAgQDJRo9v+0QvldI33cpJKPKiaop5QvfIDzMatD3vLA1qqycgIi4KOtb5\n" +
// "+LP/jgIpCYah/sk+JpKNz/vsZmZmrfaVu9D3Le2LLBgMpEoSO8jOe9WGI4Ew75C7w7AZCa\n" +
// "SyUnHIVX/9D8Y5tx4cKx6Im9AGbNF35XZoKO4KCk5VMTXhnwAAAIEAwkjKIpTYdeAQVTRf\n" +
// "C13kg84Bu5n4WkiLnp1WOCg2GN5RekqprINtpjIMZoB9Fv292Np99La8yvmRoy5qzNHGdm\n" +
// "Q6AMku8jP123jF2J+wDvF714VtZHNvdCYBGJS+rZ81xtJfHhKtZqRAVtbPertOWZeuRm9V\n" +
// "o+/rEuEzgGYGXNcAAAAbemhhbmdsaW4zM0B6aGFuZ2xpbjMzLmxvY2Fs\n" +
// "-----END OPENSSH PRIVATE KEY-----";
//
// byte[] privKeyBytes = null;
// try {
// privKeyBytes = new PemReader(new StringReader(privKeyStr)).readPemObject().getContent();
// } catch (IOException e1) {
// e1.printStackTrace();
// }
//
// assert privKeyBytes != null;
// System.out.println(Hex.toHexString(privKeyBytes));
//
//
// OpenSSHPrivateKeySpec privKeySpec = new OpenSSHPrivateKeySpec(privKeyBytes);
//
// String privKeyFormat = privKeySpec.getFormat();
// System.out.println(privKeyFormat);
//
// RSAKeyParameters privKey = (RSAKeyParameters) OpenSSHPrivateKeyUtil.parsePrivateKeyBlob(privKeyBytes);
//
//// BigInteger e = privKey.getPublicExponent();
//// BigInteger n = privKey.getModulus();
////
//// BigInteger d = privKey.getExponent();
//// BigInteger p = privKey.getP();
//// BigInteger q = privKey.getQ();
//// BigInteger dP = privKey.getDP();
//// BigInteger dQ = privKey.getDQ();
//// BigInteger qInv = privKey.getQInv();
//
//// System.out.println(Hex.toHexString(e.toByteArray()));
//// System.out.println(Hex.toHexString(n.toByteArray()));
////
//// System.out.println(Hex.toHexString(d.toByteArray()));
//// System.out.println(Hex.toHexString(p.toByteArray()));
//// System.out.println(Hex.toHexString(q.toByteArray()));
//// System.out.println(Hex.toHexString(dP.toByteArray()));
//// System.out.println(Hex.toHexString(dQ.toByteArray()));
//// System.out.println(Hex.toHexString(qInv.toByteArray()));
//
//
//
// }
//
//}

+ 38
- 0
source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/Crypto.java View File

@@ -106,6 +106,44 @@ public final class Crypto {
private Crypto() {
}

public static CryptoProvider[] getProviders() {
Collection<Provider<CryptoService>> providers = pm.getAllProviders(CryptoService.class);
CryptoProvider[] infos = new CryptoProvider[providers.size()];

int i = 0;
for (Provider<CryptoService> pd : providers) {
CryptoProviderInfo info = getProviderInfo(pd);
infos[i] = info;
}

return infos;
}

private static CryptoProviderInfo getProviderInfo(Provider<CryptoService> pd) {
Collection<CryptoFunction> functions = pd.getService().getFunctions();
CryptoAlgorithm[] algorithms = new CryptoAlgorithm[functions.size()];
int i = 0;
for (CryptoFunction function : functions) {
algorithms[i] = function.getAlgorithm();
i++;
}
return new CryptoProviderInfo(pd.getFullName(), algorithms);
}

/**
* 返回指定名称的密码服务提供者;如果不存在,则返回 null ;
*
* @param providerFullName
* @return
*/
public static CryptoProvider getProvider(String providerFullName) {
Provider<CryptoService> pd = pm.getProvider(CryptoService.class, providerFullName);
if (pd == null) {
throw new CryptoException("Crypto service provider named [" + providerFullName + "] does not exist!");
}
return getProviderInfo(pd);
}

public static Collection<CryptoAlgorithm> getAllAlgorithms() {
return algorithms.values();
}


+ 8
- 2
source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoAlgorithm.java View File

@@ -9,7 +9,7 @@ import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consts.DataCodes;
import com.jd.blockchain.utils.io.BytesUtils;

//@DataContract(code = DataCodes.CRYPTO_ALGORITHM)
@DataContract(code = DataCodes.CRYPTO_ALGORITHM)
public interface CryptoAlgorithm {

/**
@@ -63,7 +63,7 @@ public interface CryptoAlgorithm {
* {@link #EXT_ALGORITHM}) 5 种); 接下来4位标识密钥类型(包括:{@link #SYMMETRIC_KEY},
* {@link #ASYMMETRIC_KEY}); 最后8位是算法唯一ID;
*/
// @DataField(primitiveType = PrimitiveType.INT16, order = 0)
@DataField(order = 0, primitiveType = PrimitiveType.INT16)
short code();

/**
@@ -75,7 +75,13 @@ public interface CryptoAlgorithm {
*
* @return
*/
@DataField(order = 1, primitiveType = PrimitiveType.TEXT)
String name();

public static String getString(CryptoAlgorithm algorithm) {
return String.format("%s[%s]", algorithm.name(), (algorithm.code() & 0xFFFF));
}

/**
*


+ 13
- 25
source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoAlgorithmDefinition.java View File

@@ -23,16 +23,14 @@ public final class CryptoAlgorithmDefinition implements CryptoAlgorithm {

@Override
public String toString() {
return name + "[" + (code & 0xFFFF) + "]";
return CryptoAlgorithm.getString(this);
}

/**
* 声明一项哈希算法;
*
* @param name
* 算法名称;
* @param uid
* 算法ID;需要在同类算法中保持唯一性;
* @param name 算法名称;
* @param uid 算法ID;需要在同类算法中保持唯一性;
* @return
*/
public static CryptoAlgorithm defineHash(String name, byte uid) {
@@ -43,10 +41,8 @@ public final class CryptoAlgorithmDefinition implements CryptoAlgorithm {
/**
* 声明一项非对称密码算法;
*
* @param name
* 算法名称;
* @param uid
* 算法ID;需要在同类算法中保持唯一性;
* @param name 算法名称;
* @param uid 算法ID;需要在同类算法中保持唯一性;
* @return
*/
public static CryptoAlgorithm defineSignature(String name, boolean encryptable, byte uid) {
@@ -62,10 +58,8 @@ public final class CryptoAlgorithmDefinition implements CryptoAlgorithm {
/**
* 声明一项非对称加密算法;
*
* @param name
* 算法名称;
* @param uid
* 算法ID;需要在同类算法中保持唯一性;
* @param name 算法名称;
* @param uid 算法ID;需要在同类算法中保持唯一性;
* @return
*/
public static CryptoAlgorithm defineAsymmetricEncryption(String name, byte uid) {
@@ -76,10 +70,8 @@ public final class CryptoAlgorithmDefinition implements CryptoAlgorithm {
/**
* 声明一项对称密码算法;
*
* @param name
* 算法名称;
* @param uid
* 算法ID;需要在同类算法中保持唯一性;
* @param name 算法名称;
* @param uid 算法ID;需要在同类算法中保持唯一性;
* @return
*/
public static CryptoAlgorithm defineSymmetricEncryption(String name, byte uid) {
@@ -90,10 +82,8 @@ public final class CryptoAlgorithmDefinition implements CryptoAlgorithm {
/**
* 声明一项随机数算法;
*
* @param name
* 算法名称;
* @param uid
* 算法ID;需要在同类算法中保持唯一性;
* @param name 算法名称;
* @param uid 算法ID;需要在同类算法中保持唯一性;
* @return
*/
public static CryptoAlgorithm defineRandom(String name, byte uid) {
@@ -104,10 +94,8 @@ public final class CryptoAlgorithmDefinition implements CryptoAlgorithm {
/**
* 声明一项扩展的密码算法;
*
* @param name
* 算法名称;
* @param uid
* 算法ID;需要在同类算法中保持唯一性;
* @param name 算法名称;
* @param uid 算法ID;需要在同类算法中保持唯一性;
* @return
*/
public static CryptoAlgorithm definExt(String name, byte uid) {


+ 17
- 0
source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoProvider.java View File

@@ -0,0 +1,17 @@
package com.jd.blockchain.crypto;

import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consts.DataCodes;

@DataContract(code = DataCodes.METADATA_CRYPTO_SETTING_PROVIDER)
public interface CryptoProvider {

@DataField(order = 0, primitiveType = PrimitiveType.TEXT)
String getName();

@DataField(order = 1, list = true, refContract = true)
CryptoAlgorithm[] getAlgorithms();

}

+ 24
- 0
source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoProviderInfo.java View File

@@ -0,0 +1,24 @@
package com.jd.blockchain.crypto;

class CryptoProviderInfo implements CryptoProvider {

private String name;

private CryptoAlgorithm[] algorithms;

public CryptoProviderInfo(String name, CryptoAlgorithm[] algorithms) {
this.name = name;
this.algorithms = algorithms;
}

@Override
public String getName() {
return name;
}

@Override
public CryptoAlgorithm[] getAlgorithms() {
return algorithms.clone();
}

}

+ 34
- 0
source/crypto/crypto-pki/pom.xml View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>crypto</artifactId>
<groupId>com.jd.blockchain</groupId>
<version>0.9.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>crypto-pki</artifactId>

<dependencies>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>crypto-framework</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.61</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.61</version>
</dependency>

</dependencies>

</project>

+ 26
- 0
source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/PKIAlgorithm.java View File

@@ -0,0 +1,26 @@
package com.jd.blockchain.crypto.service.pki;

import com.jd.blockchain.crypto.CryptoAlgorithm;
import com.jd.blockchain.crypto.CryptoAlgorithmDefinition;

/**
* @author zhanglin33
* @title: PKIAlgorithm
* @description: TODO
* @date 2019-05-15, 16:34
*/
public class PKIAlgorithm {

public static final CryptoAlgorithm SHA1WITHRSA2048 = CryptoAlgorithmDefinition.defineSignature("SHA1WITHRSA2048",
false, (byte) 31);

public static final CryptoAlgorithm SHA1WITHRSA4096 = CryptoAlgorithmDefinition.defineSignature("SHA1WITHRSA4096",
false, (byte) 32);

public static final CryptoAlgorithm SM3WITHSM2 = CryptoAlgorithmDefinition.defineSignature("SM3WITHSM2",
false, (byte) 33);

private PKIAlgorithm() {
}

}

+ 38
- 0
source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/PKICryptoService.java View File

@@ -0,0 +1,38 @@
package com.jd.blockchain.crypto.service.pki;

import com.jd.blockchain.crypto.CryptoFunction;
import com.jd.blockchain.crypto.CryptoService;
import com.jd.blockchain.provider.NamedProvider;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
* @author zhanglin33
* @title: PKICryptoService
* @description: TODO
* @date 2019-05-15, 16:35
*/
@NamedProvider("PKI-SOFTWARE")
public class PKICryptoService implements CryptoService {

public static final SHA1WITHRSA2048SignatureFunction SHA1WITHRSA2048 = new SHA1WITHRSA2048SignatureFunction();

public static final SHA1WITHRSA4096SignatureFunction SHA1WITHRSA4096 = new SHA1WITHRSA4096SignatureFunction();

public static final SM3WITHSM2SignatureFunction SM3WITHSM2 = new SM3WITHSM2SignatureFunction();

private static final Collection<CryptoFunction> FUNCTIONS;

static {
List<CryptoFunction> funcs = Arrays.asList(SHA1WITHRSA2048, SHA1WITHRSA4096, SM3WITHSM2);
FUNCTIONS = Collections.unmodifiableList(funcs);
}

@Override
public Collection<CryptoFunction> getFunctions() {
return FUNCTIONS;
}
}

+ 220
- 0
source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunction.java View File

@@ -0,0 +1,220 @@
package com.jd.blockchain.crypto.service.pki;

import com.jd.blockchain.crypto.*;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import static com.jd.blockchain.crypto.BaseCryptoKey.KEY_TYPE_BYTES;
import static com.jd.blockchain.crypto.CryptoBytes.ALGORYTHM_CODE_SIZE;
import static com.jd.blockchain.crypto.CryptoKeyType.PRIVATE;
import static com.jd.blockchain.crypto.CryptoKeyType.PUBLIC;
import static com.jd.blockchain.crypto.service.pki.PKIAlgorithm.SHA1WITHRSA2048;

/**
* @author zhanglin33
* @title: SHA1WITHRSA2048SignatureFunction
* @description: TODO
* @date 2019-05-15, 16:37
*/
public class SHA1WITHRSA2048SignatureFunction implements SignatureFunction {

private static final int RAW_PUBKEY_SIZE = 259;
private static final int RAW_PRIVKEY_SIZE = 1155;

private static final int RAW_SIGNATUREDIGEST_SIZE = 256;

private static final AlgorithmIdentifier RSA_ALGORITHM_IDENTIFIER =
new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE);

@Override
public SignatureDigest sign(PrivKey privKey, byte[] data) {

byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();

if (rawPrivKeyBytes.length < RAW_PRIVKEY_SIZE) {
throw new CryptoException("This key has wrong format!");
}

if (privKey.getAlgorithm() != SHA1WITHRSA2048.code()) {
throw new CryptoException("This key is not SHA1WITHRSA2048 private key!");
}

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(rawPrivKeyBytes);

KeyFactory keyFactory;
RSAPrivateCrtKey rawPrivKey;
Signature signer;
byte[] signature;

try {
keyFactory = KeyFactory.getInstance("RSA");
rawPrivKey = (RSAPrivateCrtKey) keyFactory.generatePrivate(keySpec);
signer = Signature.getInstance("SHA1withRSA");
signer.initSign(rawPrivKey);
signer.update(data);
signature = signer.sign();
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException | InvalidKeySpecException e) {
throw new CryptoException(e.getMessage(), e);
}

return new SignatureDigest(SHA1WITHRSA2048, signature);
}

@Override
public boolean verify(SignatureDigest digest, PubKey pubKey, byte[] data) {

byte[] rawPubKeyBytes = pubKey.getRawKeyBytes();
byte[] rawDigestBytes = digest.getRawDigest();

if (rawPubKeyBytes.length < RAW_PUBKEY_SIZE) {
throw new CryptoException("This key has wrong format!");
}

if (pubKey.getAlgorithm() != SHA1WITHRSA2048.code()) {
throw new CryptoException("This key is not SHA1WITHRSA2048 public key!");
}

if (digest.getAlgorithm() != SHA1WITHRSA2048.code() || rawDigestBytes.length != RAW_SIGNATUREDIGEST_SIZE) {
throw new CryptoException("This is not SHA1WITHRSA2048 signature digest!");
}

X509EncodedKeySpec keySpec = new X509EncodedKeySpec(rawPubKeyBytes);

KeyFactory keyFactory;
RSAPublicKey rawPubKey;
Signature verifier;
boolean isValid;

try {
keyFactory = KeyFactory.getInstance("RSA");
rawPubKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
verifier = Signature.getInstance("SHA1withRSA");
verifier.initVerify(rawPubKey);
verifier.update(data);
isValid = verifier.verify(rawDigestBytes);
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException | InvalidKeySpecException e) {
throw new CryptoException(e.getMessage(), e);
}

return isValid;
}

@Override
public boolean supportPubKey(byte[] pubKeyBytes) {
return pubKeyBytes.length > (ALGORYTHM_CODE_SIZE + KEY_TYPE_BYTES + RAW_PUBKEY_SIZE)
&& CryptoAlgorithm.match(SHA1WITHRSA2048, pubKeyBytes)
&& pubKeyBytes[ALGORYTHM_CODE_SIZE] == PUBLIC.CODE;
}

@Override
public PubKey resolvePubKey(byte[] pubKeyBytes) {
if (supportPubKey(pubKeyBytes)) {
return new PubKey(pubKeyBytes);
} else {
throw new CryptoException("pubKeyBytes are invalid!");
}
}

@Override
public boolean supportPrivKey(byte[] privKeyBytes) {
return privKeyBytes.length > (ALGORYTHM_CODE_SIZE + KEY_TYPE_BYTES + RAW_PRIVKEY_SIZE)
&& CryptoAlgorithm.match(SHA1WITHRSA2048, privKeyBytes)
&& privKeyBytes[ALGORYTHM_CODE_SIZE] == PRIVATE.CODE;
}

@Override
public PrivKey resolvePrivKey(byte[] privKeyBytes) {
if (supportPrivKey(privKeyBytes)) {
return new PrivKey(privKeyBytes);
} else {
throw new CryptoException("privKeyBytes are invalid!");
}
}

@Override
public PubKey retrievePubKey(PrivKey privKey) {

byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();

if (rawPrivKeyBytes.length < RAW_PRIVKEY_SIZE) {
throw new CryptoException("This key has wrong format!");
}

if (privKey.getAlgorithm() != SHA1WITHRSA2048.code()) {
throw new CryptoException("This key is not SHA1WITHRSA2048 private key!");
}

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(rawPrivKeyBytes);

KeyFactory keyFactory;
RSAPrivateCrtKey rawPrivKey;
byte[] rawPubKeyBytes;
try {
keyFactory = KeyFactory.getInstance("RSA");
rawPrivKey = (RSAPrivateCrtKey) keyFactory.generatePrivate(keySpec);
BigInteger modulus = rawPrivKey.getModulus();
BigInteger exponent = rawPrivKey.getPublicExponent();
rawPubKeyBytes = KeyUtil.getEncodedSubjectPublicKeyInfo(RSA_ALGORITHM_IDENTIFIER,
new org.bouncycastle.asn1.pkcs.RSAPublicKey(modulus, exponent));
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
throw new CryptoException(e.getMessage(), e);
}

return new PubKey(SHA1WITHRSA2048, rawPubKeyBytes);
}

@Override
public boolean supportDigest(byte[] digestBytes) {
return digestBytes.length == (RAW_SIGNATUREDIGEST_SIZE + ALGORYTHM_CODE_SIZE)
&& CryptoAlgorithm.match(SHA1WITHRSA2048, digestBytes);
}

@Override
public SignatureDigest resolveDigest(byte[] digestBytes) {
if (supportDigest(digestBytes)) {
return new SignatureDigest(digestBytes);
} else {
throw new CryptoException("digestBytes are invalid!");
}
}

@Override
public AsymmetricKeypair generateKeypair() {

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
KeyPairGenerator generator;
PublicKey pubKey;
PrivateKey privKey;
try {
generator = KeyPairGenerator.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME);
generator.initialize(2048);
KeyPair keyPair = generator.generateKeyPair();
pubKey = keyPair.getPublic();
privKey = keyPair.getPrivate();
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
throw new CryptoException(e.getMessage(), e);
}

byte[] pubKeyBytes = pubKey.getEncoded();
byte[] privKeyBytes = privKey.getEncoded();

return new AsymmetricKeypair(new PubKey(SHA1WITHRSA2048, pubKeyBytes),
new PrivKey(SHA1WITHRSA2048, privKeyBytes));
}

@Override
public CryptoAlgorithm getAlgorithm() {
return SHA1WITHRSA2048;
}
}

+ 220
- 0
source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunction.java View File

@@ -0,0 +1,220 @@
package com.jd.blockchain.crypto.service.pki;

import com.jd.blockchain.crypto.*;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import static com.jd.blockchain.crypto.BaseCryptoKey.KEY_TYPE_BYTES;
import static com.jd.blockchain.crypto.CryptoBytes.ALGORYTHM_CODE_SIZE;
import static com.jd.blockchain.crypto.CryptoKeyType.PRIVATE;
import static com.jd.blockchain.crypto.CryptoKeyType.PUBLIC;
import static com.jd.blockchain.crypto.service.pki.PKIAlgorithm.SHA1WITHRSA4096;

/**
* @author zhanglin33
* @title: SHA1WITHRSA4096SignatureFunction
* @description: TODO
* @date 2019-05-15, 17:13
*/
public class SHA1WITHRSA4096SignatureFunction implements SignatureFunction {
private static final int RAW_PUBKEY_SIZE = 515;
private static final int RAW_PRIVKEY_SIZE = 2307;

private static final int RAW_SIGNATUREDIGEST_SIZE = 512;

private static final AlgorithmIdentifier RSA_ALGORITHM_IDENTIFIER =
new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE);

@Override
public SignatureDigest sign(PrivKey privKey, byte[] data) {

byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();

if (rawPrivKeyBytes.length < RAW_PRIVKEY_SIZE) {
throw new CryptoException("This key has wrong format!");
}

if (privKey.getAlgorithm() != SHA1WITHRSA4096.code()) {
throw new CryptoException("This key is not SHA1WITHRSA4096 private key!");
}

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(rawPrivKeyBytes);

KeyFactory keyFactory;
RSAPrivateCrtKey rawPrivKey;
Signature signer;
byte[] signature;

try {
keyFactory = KeyFactory.getInstance("RSA");
rawPrivKey = (RSAPrivateCrtKey) keyFactory.generatePrivate(keySpec);
signer = Signature.getInstance("SHA1withRSA");
signer.initSign(rawPrivKey);
signer.update(data);
signature = signer.sign();
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException | InvalidKeySpecException e) {
throw new CryptoException(e.getMessage(), e);
}

return new SignatureDigest(SHA1WITHRSA4096, signature);
}

@Override
public boolean verify(SignatureDigest digest, PubKey pubKey, byte[] data) {

byte[] rawPubKeyBytes = pubKey.getRawKeyBytes();
byte[] rawDigestBytes = digest.getRawDigest();

if (rawPubKeyBytes.length < RAW_PUBKEY_SIZE) {
throw new CryptoException("This key has wrong format!");
}

if (pubKey.getAlgorithm() != SHA1WITHRSA4096.code()) {
throw new CryptoException("This key is not SHA1WITHRSA4096 public key!");
}

if (digest.getAlgorithm() != SHA1WITHRSA4096.code() || rawDigestBytes.length != RAW_SIGNATUREDIGEST_SIZE) {
throw new CryptoException("This is not SHA1WITHRSA4096 signature digest!");
}

X509EncodedKeySpec keySpec = new X509EncodedKeySpec(rawPubKeyBytes);

KeyFactory keyFactory;
RSAPublicKey rawPubKey;
Signature verifier;
boolean isValid;

try {
keyFactory = KeyFactory.getInstance("RSA");
rawPubKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
verifier = Signature.getInstance("SHA1withRSA");
verifier.initVerify(rawPubKey);
verifier.update(data);
isValid = verifier.verify(rawDigestBytes);
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException | InvalidKeySpecException e) {
throw new CryptoException(e.getMessage(), e);
}

return isValid;
}

@Override
public boolean supportPubKey(byte[] pubKeyBytes) {
return pubKeyBytes.length > (ALGORYTHM_CODE_SIZE + KEY_TYPE_BYTES + RAW_PUBKEY_SIZE)
&& CryptoAlgorithm.match(SHA1WITHRSA4096, pubKeyBytes)
&& pubKeyBytes[ALGORYTHM_CODE_SIZE] == PUBLIC.CODE;
}

@Override
public PubKey resolvePubKey(byte[] pubKeyBytes) {
if (supportPubKey(pubKeyBytes)) {
return new PubKey(pubKeyBytes);
} else {
throw new CryptoException("pubKeyBytes are invalid!");
}
}

@Override
public boolean supportPrivKey(byte[] privKeyBytes) {
return privKeyBytes.length > (ALGORYTHM_CODE_SIZE + KEY_TYPE_BYTES + RAW_PRIVKEY_SIZE)
&& CryptoAlgorithm.match(SHA1WITHRSA4096, privKeyBytes)
&& privKeyBytes[ALGORYTHM_CODE_SIZE] == PRIVATE.CODE;
}

@Override
public PrivKey resolvePrivKey(byte[] privKeyBytes) {
if (supportPrivKey(privKeyBytes)) {
return new PrivKey(privKeyBytes);
} else {
throw new CryptoException("privKeyBytes are invalid!");
}
}

@Override
public PubKey retrievePubKey(PrivKey privKey) {

byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();

if (rawPrivKeyBytes.length < RAW_PRIVKEY_SIZE) {
throw new CryptoException("This key has wrong format!");
}

if (privKey.getAlgorithm() != SHA1WITHRSA4096.code()) {
throw new CryptoException("This key is not SHA1WITHRSA4096 private key!");
}

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(rawPrivKeyBytes);

KeyFactory keyFactory;
RSAPrivateCrtKey rawPrivKey;
byte[] rawPubKeyBytes;
try {
keyFactory = KeyFactory.getInstance("RSA");
rawPrivKey = (RSAPrivateCrtKey) keyFactory.generatePrivate(keySpec);
BigInteger modulus = rawPrivKey.getModulus();
BigInteger exponent = rawPrivKey.getPublicExponent();
rawPubKeyBytes = KeyUtil.getEncodedSubjectPublicKeyInfo(RSA_ALGORITHM_IDENTIFIER,
new org.bouncycastle.asn1.pkcs.RSAPublicKey(modulus, exponent));
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
throw new CryptoException(e.getMessage(), e);
}

return new PubKey(SHA1WITHRSA4096, rawPubKeyBytes);
}

@Override
public boolean supportDigest(byte[] digestBytes) {
return digestBytes.length == (RAW_SIGNATUREDIGEST_SIZE + ALGORYTHM_CODE_SIZE)
&& CryptoAlgorithm.match(SHA1WITHRSA4096, digestBytes);
}

@Override
public SignatureDigest resolveDigest(byte[] digestBytes) {
if (supportDigest(digestBytes)) {
return new SignatureDigest(digestBytes);
} else {
throw new CryptoException("digestBytes are invalid!");
}
}

@Override
public AsymmetricKeypair generateKeypair() {

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
KeyPairGenerator generator;
PublicKey pubKey;
PrivateKey privKey;
try {
generator = KeyPairGenerator.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME);
generator.initialize(4096);
KeyPair keyPair = generator.generateKeyPair();
pubKey = keyPair.getPublic();
privKey = keyPair.getPrivate();
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
throw new CryptoException(e.getMessage(), e);
}

byte[] pubKeyBytes = pubKey.getEncoded();
byte[] privKeyBytes = privKey.getEncoded();

return new AsymmetricKeypair(new PubKey(SHA1WITHRSA4096, pubKeyBytes),
new PrivKey(SHA1WITHRSA4096, privKeyBytes));
}


@Override
public CryptoAlgorithm getAlgorithm() {
return SHA1WITHRSA4096;
}
}

+ 236
- 0
source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunction.java View File

@@ -0,0 +1,236 @@
package com.jd.blockchain.crypto.service.pki;

import com.jd.blockchain.crypto.*;
import org.bouncycastle.asn1.gm.GMObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.ec.custom.gm.SM2P256V1Curve;

import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import static com.jd.blockchain.crypto.BaseCryptoKey.KEY_TYPE_BYTES;
import static com.jd.blockchain.crypto.CryptoBytes.ALGORYTHM_CODE_SIZE;
import static com.jd.blockchain.crypto.CryptoKeyType.PRIVATE;
import static com.jd.blockchain.crypto.CryptoKeyType.PUBLIC;
import static com.jd.blockchain.crypto.service.pki.PKIAlgorithm.SM3WITHSM2;

/**
* @author zhanglin33
* @title: SM3WITHSM2SignatureFunction
* @description: TODO
* @date 2019-05-15, 16:39
*/
public class SM3WITHSM2SignatureFunction implements SignatureFunction {
private static final int RAW_PUBKEY_SIZE = 65;
private static final int RAW_PRIVKEY_SIZE = 32 + 65;

private static final int RAW_SIGNATUREDIGEST_SIZE = 64;

private static final SM2P256V1Curve CURVE = new SM2P256V1Curve();
private static final BigInteger GX = new BigInteger("32C4AE2C1F1981195F9904466A39C994" +
"8FE30BBFF2660BE1715A4589334C74C7", 16);
private static final BigInteger GY = new BigInteger("BC3736A2F4F6779C59BDCEE36B692153" +
"D0A9877CC62A474002DF32E52139F0A0", 16);
private static final ECPoint G = CURVE.createPoint(GX, GY);

private static final AlgorithmIdentifier SM2_ALGORITHM_IDENTIFIER = new AlgorithmIdentifier(
X9ObjectIdentifiers.id_ecPublicKey, GMObjectIdentifiers.sm2p256v1);


@Override
public SignatureDigest sign(PrivKey privKey, byte[] data) {

Security.addProvider(new BouncyCastleProvider());

byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();

if (rawPrivKeyBytes.length < RAW_PRIVKEY_SIZE) {
throw new CryptoException("This key has wrong format!");
}

if (privKey.getAlgorithm() != SM3WITHSM2.code()) {
throw new CryptoException("This key is not SM3WITHSM2 private key!");
}

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(rawPrivKeyBytes);

KeyFactory keyFactory;
ECPrivateKey rawPrivKey;
Signature signer;
byte[] signature;

try {
keyFactory = KeyFactory.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME);
rawPrivKey = (ECPrivateKey) keyFactory.generatePrivate(keySpec);
signer = Signature.getInstance("SM3withSM2", BouncyCastleProvider.PROVIDER_NAME);

signer.initSign(rawPrivKey);
signer.update(data);
signature = signer.sign();
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException |
InvalidKeySpecException | NoSuchProviderException e) {
throw new CryptoException(e.getMessage(), e);
}

return new SignatureDigest(SM3WITHSM2, signature);
}

@Override
public boolean verify(SignatureDigest digest, PubKey pubKey, byte[] data) {

Security.addProvider(new BouncyCastleProvider());

byte[] rawPubKeyBytes = pubKey.getRawKeyBytes();
byte[] rawDigestBytes = digest.getRawDigest();

if (rawPubKeyBytes.length < RAW_PUBKEY_SIZE) {
throw new CryptoException("This key has wrong format!");
}

if (pubKey.getAlgorithm() != SM3WITHSM2.code()) {
throw new CryptoException("This key is not SM3WITHSM2 public key!");
}

if (digest.getAlgorithm() != SM3WITHSM2.code() || rawDigestBytes.length < RAW_SIGNATUREDIGEST_SIZE) {
throw new CryptoException("This is not SM3WITHSM2 signature digest!");
}

X509EncodedKeySpec keySpec = new X509EncodedKeySpec(rawPubKeyBytes);

KeyFactory keyFactory;
ECPublicKey rawPubKey;
Signature verifier;
boolean isValid;

try {
keyFactory = KeyFactory.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME);
rawPubKey = (ECPublicKey) keyFactory.generatePublic(keySpec);
verifier = Signature.getInstance("SM3withSM2", BouncyCastleProvider.PROVIDER_NAME);
verifier.initVerify(rawPubKey);
verifier.update(data);
isValid = verifier.verify(rawDigestBytes);
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException | InvalidKeySpecException
| NoSuchProviderException e) {
throw new CryptoException(e.getMessage(), e);
}

return isValid;
}

@Override
public boolean supportPubKey(byte[] pubKeyBytes) {
return pubKeyBytes.length > (ALGORYTHM_CODE_SIZE + KEY_TYPE_BYTES + RAW_PUBKEY_SIZE)
&& CryptoAlgorithm.match(SM3WITHSM2, pubKeyBytes)
&& pubKeyBytes[ALGORYTHM_CODE_SIZE] == PUBLIC.CODE;
}

@Override
public PubKey resolvePubKey(byte[] pubKeyBytes) {
if (supportPubKey(pubKeyBytes)) {
return new PubKey(pubKeyBytes);
} else {
throw new CryptoException("pubKeyBytes are invalid!");
}
}

@Override
public boolean supportPrivKey(byte[] privKeyBytes) {
return privKeyBytes.length > (ALGORYTHM_CODE_SIZE + KEY_TYPE_BYTES + RAW_PRIVKEY_SIZE)
&& CryptoAlgorithm.match(SM3WITHSM2, privKeyBytes)
&& privKeyBytes[ALGORYTHM_CODE_SIZE] == PRIVATE.CODE;
}

@Override
public PrivKey resolvePrivKey(byte[] privKeyBytes) {
if (supportPrivKey(privKeyBytes)) {
return new PrivKey(privKeyBytes);
} else {
throw new CryptoException("privKeyBytes are invalid!");
}
}

@Override
public PubKey retrievePubKey(PrivKey privKey) {

byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();

if (rawPrivKeyBytes.length < RAW_PRIVKEY_SIZE) {
throw new CryptoException("This key has wrong format!");
}

if (privKey.getAlgorithm() != SM3WITHSM2.code()) {
throw new CryptoException("This key is not SM3WITHSM2 private key!");
}

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(rawPrivKeyBytes);

KeyFactory keyFactory;
ECPrivateKey rawPrivKey;
byte[] rawPubKeyBytes;
try {
keyFactory = KeyFactory.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME);
rawPrivKey = (ECPrivateKey) keyFactory.generatePrivate(keySpec);
BigInteger d = rawPrivKey.getS();
ECPoint Q = G.multiply(d).normalize();
rawPubKeyBytes = KeyUtil.getEncodedSubjectPublicKeyInfo(SM2_ALGORITHM_IDENTIFIER,
Q.getEncoded(false));
} catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchProviderException e) {
throw new CryptoException(e.getMessage(), e);
}

return new PubKey(SM3WITHSM2, rawPubKeyBytes);
}

@Override
public boolean supportDigest(byte[] digestBytes) {
return digestBytes.length > (RAW_SIGNATUREDIGEST_SIZE + ALGORYTHM_CODE_SIZE)
&& CryptoAlgorithm.match(SM3WITHSM2, digestBytes);
}

@Override
public SignatureDigest resolveDigest(byte[] digestBytes) {
if (supportDigest(digestBytes)) {
return new SignatureDigest(digestBytes);
} else {
throw new CryptoException("digestBytes are invalid!");
}
}

@Override
public AsymmetricKeypair generateKeypair() {

Security.addProvider(new BouncyCastleProvider());
KeyPairGenerator generator;
PublicKey pubKey;
PrivateKey privKey;
try {
generator = KeyPairGenerator.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME);
generator.initialize(new ECNamedCurveGenParameterSpec("sm2p256v1"));
KeyPair keyPair = generator.generateKeyPair();
pubKey = keyPair.getPublic();
privKey = keyPair.getPrivate();
} catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) {
throw new CryptoException(e.getMessage(), e);
}

byte[] pubKeyBytes = pubKey.getEncoded();
byte[] privKeyBytes = privKey.getEncoded();

return new AsymmetricKeypair(new PubKey(SM3WITHSM2, pubKeyBytes),
new PrivKey(SM3WITHSM2, privKeyBytes));
}
@Override
public CryptoAlgorithm getAlgorithm() {
return SM3WITHSM2;
}
}

+ 129
- 0
source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CSRBuilder.java View File

@@ -0,0 +1,129 @@
package com.jd.blockchain.crypto.utils;

import com.jd.blockchain.crypto.CryptoException;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.X500NameBuilder;
import org.bouncycastle.asn1.x500.style.BCStrictStyle;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder;
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder;
import org.bouncycastle.util.encoders.Base64;

import java.io.IOException;
import java.security.*;

/**
* @author zhanglin33
* @title: CSRBuilder
* @description: A builder for certificate signing request, supporting rsa and sm2
* @date 2019-05-10, 15:10
*/
public class CSRBuilder {

private String BC = BouncyCastleProvider.PROVIDER_NAME;

private PublicKey pubKey;
private PrivateKey privKey;

private String algoName;

public void init() {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
algoName = "SHA1withRSA";
KeyPairGenerator generator;
try {
generator = KeyPairGenerator.getInstance("RSA", BC);
generator.initialize(2048);
KeyPair keyPair = generator.generateKeyPair();
pubKey = keyPair.getPublic();
privKey = keyPair.getPrivate();
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
throw new CryptoException(e.getMessage(), e);
}
}

public void init(String algoName, int KeyLength) {

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
this.algoName = algoName;

KeyPairGenerator generator;
KeyPair keyPair;
String[] hashAndSignature = algoName.split("with");

try {
switch (hashAndSignature[1]) {
case "RSA": {
generator = KeyPairGenerator.getInstance("RSA", BC);
generator.initialize(KeyLength);
keyPair = generator.generateKeyPair();
pubKey = keyPair.getPublic();
privKey = keyPair.getPrivate();
break;
}

case "SM2": {
generator = KeyPairGenerator.getInstance("EC", BC);
if (KeyLength != 256) {
throw new CryptoException("SM3withSM2 with unsupported key length [" +
KeyLength +"] in CSR!");
}
generator.initialize(new ECNamedCurveGenParameterSpec("sm2p256v1"));
keyPair = generator.generateKeyPair();
pubKey = keyPair.getPublic();
privKey = keyPair.getPrivate();
break;
}

default: throw new CryptoException("Unsupported algorithm [" + algoName + "] with key length [" +
KeyLength +"] in CSR!");
}
} catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) {
throw new CryptoException(e.getMessage(), e);
}
}

public String buildRequest(String countryName, String stateName, String cityName,
String organizationName, String departmentName, String domainName,
String emailName) {

String result;
X500NameBuilder nameBuilder = new X500NameBuilder(BCStrictStyle.INSTANCE);

nameBuilder.addRDN(BCStyle.C, countryName); // a country name, and China is short as CN
nameBuilder.addRDN(BCStyle.ST, stateName); // a state or province name
nameBuilder.addRDN(BCStyle.L, cityName); // a city name
nameBuilder.addRDN(BCStyle.O, organizationName); // an organization or corporation name
nameBuilder.addRDN(BCStyle.OU, departmentName); // a division of your organization name
nameBuilder.addRDN(BCStyle.CN, domainName); // a fully qualified domain name
nameBuilder.addRDN(BCStyle.E, emailName); // an email address

try {
X500Name x500Name = nameBuilder.build();

PKCS10CertificationRequestBuilder requestBuilder
= new JcaPKCS10CertificationRequestBuilder(x500Name, pubKey);
PKCS10CertificationRequest request
= requestBuilder.build(new JcaContentSignerBuilder(algoName).setProvider(BC).build(privKey));
byte[] csrBytes = request.getEncoded();
result = Base64.toBase64String(csrBytes);
} catch (OperatorCreationException | IOException e) {
throw new CryptoException(e.getMessage(), e);
}

return result;
}

public PublicKey getPubKey() {
return pubKey;
}

public PrivateKey getPrivKey() {
return privKey;
}
}

+ 131
- 0
source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CertParser.java View File

@@ -0,0 +1,131 @@
package com.jd.blockchain.crypto.utils;

import com.jd.blockchain.crypto.CryptoException;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.io.pem.PemReader;

import javax.security.auth.x500.X500Principal;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringReader;
import java.security.*;
import java.security.cert.*;
import java.util.Date;

/**
* @author zhanglin33
* @title: CertParser
* @description: A parser for standard certificate, along with validation process
* @date 2019-05-10, 15:17
*/
public class CertParser {

private PublicKey pubKey;
private String sigAlgName;
private String userName;
private String issuerName;

private Date startTime;
private Date endTime;

public void parse(String userCertificate, String issuerCertificate) {

X509Certificate issuerCert = parseWithoutValidationProcess(issuerCertificate);

// ensure that the certificate is within the validity period
try {
issuerCert.checkValidity();
} catch (CertificateExpiredException | CertificateNotYetValidException e) {
throw new CryptoException(e.getMessage(), e);
}
PublicKey issuerPubKey = issuerCert.getPublicKey();
X500Principal issuerPrincipal = issuerCert.getSubjectX500Principal();

X509Certificate userCert = parseWithoutValidationProcess(userCertificate);

// check consistency between issuer's names in userCertificate and issuerCertificate
if (!userCert.getIssuerX500Principal().equals(issuerPrincipal)) {
throw new CryptoException("Issuer in the targeted certificate is not " +
"compliance with the parent certificate!");
}

try {
userCert.checkValidity();
} catch (CertificateExpiredException | CertificateNotYetValidException e) {
throw new CryptoException(e.getMessage(), e);
}

// verify the signature in certificate with issuer's public key
try {
userCert.verify(issuerPubKey);
} catch (CertificateException | NoSuchAlgorithmException
| InvalidKeyException | NoSuchProviderException | SignatureException e) {
throw new CryptoException(e.getMessage(), e);
}

startTime = userCert.getNotBefore();
endTime = userCert.getNotAfter();

pubKey = userCert.getPublicKey();
sigAlgName = userCert.getSigAlgName();
issuerName = userCert.getIssuerX500Principal().getName();
userName = userCert.getSubjectX500Principal().getName();
}

// certificate string in Base64 format
public X509Certificate parseWithoutValidationProcess(String certificate) {

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

byte[] certificateBytes;
String BEGIN = "-----BEGIN CERTIFICATE-----";
String END = "-----END CERTIFICATE-----";
if (!certificate.startsWith(BEGIN)) {
certificate = certificate.replaceAll("\\n", "");
certificate = certificate.replaceAll(END, "");
certificateBytes = Base64.decode(certificate);
} else {
try {
certificateBytes = new PemReader(new StringReader(certificate)).readPemObject().getContent();
} catch (IOException e) {
throw new CryptoException(e.getMessage(), e);
}
}

ByteArrayInputStream bytesIn = new ByteArrayInputStream(certificateBytes);
CertificateFactory factory;
X509Certificate cert;
try {
factory = CertificateFactory.getInstance("X509", BouncyCastleProvider.PROVIDER_NAME);
cert = (X509Certificate) factory.generateCertificate(bytesIn);
} catch (CertificateException | NoSuchProviderException e) {
throw new CryptoException(e.getMessage(), e);
}
return cert;
}

public PublicKey getPubKey() {
return pubKey;
}

public String getSigAlgName() {
return sigAlgName;
}

public String getUserName() {
return userName;
}

public String getIssuerName() {
return issuerName;
}

public Date getStartTime() {
return startTime;
}

public Date getEndTime() {
return endTime;
}
}

+ 1
- 0
source/crypto/crypto-pki/src/main/resources/META-INF/services/com.jd.blockchain.crypto.CryptoService View File

@@ -0,0 +1 @@
com.jd.blockchain.crypto.service.pki.PKICryptoService

+ 128
- 0
source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunctionTest.java View File

@@ -0,0 +1,128 @@
package com.jd.blockchain.crypto.service.pki;

import com.jd.blockchain.crypto.*;
import com.jd.blockchain.utils.io.BytesUtils;
import org.junit.Test;

import java.util.Random;

import static com.jd.blockchain.crypto.CryptoAlgorithm.*;
import static com.jd.blockchain.crypto.CryptoKeyType.PRIVATE;
import static com.jd.blockchain.crypto.CryptoKeyType.PUBLIC;
import static org.junit.Assert.*;

/**
* @author zhanglin33
* @title: SHA1WITHRSA2048SignatureFunctionTest
* @description: TODO
* @date 2019-05-16, 10:49
*/
public class SHA1WITHRSA2048SignatureFunctionTest {

@Test
public void getAlgorithmTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

assertEquals(signatureFunction.getAlgorithm().name(), algorithm.name());
assertEquals(signatureFunction.getAlgorithm().code(), algorithm.code());

algorithm = Crypto.getAlgorithm("SHA1withRsa2048");
assertNotNull(algorithm);

assertEquals(signatureFunction.getAlgorithm().name(), algorithm.name());
assertEquals(signatureFunction.getAlgorithm().code(), algorithm.code());

algorithm = Crypto.getAlgorithm("rsa2048");
assertNull(algorithm);
}

@Test
public void test() {

// generateKeyPairTest
CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048");
assertNotNull(algorithm);
SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);
AsymmetricKeypair keyPair = signatureFunction.generateKeypair();
PubKey pubKey = keyPair.getPubKey();
PrivKey privKey = keyPair.getPrivKey();
assertEquals(PUBLIC.CODE, pubKey.getKeyType().CODE);
assertTrue(pubKey.getRawKeyBytes().length > 259);
assertEquals(PRIVATE.CODE, privKey.getKeyType().CODE);
assertTrue(privKey.getRawKeyBytes().length > 1155);
assertEquals(algorithm.code(), pubKey.getAlgorithm());
assertEquals(algorithm.code(), privKey.getAlgorithm());
byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm);
byte[] pubKeyTypeBytes = new byte[] { PUBLIC.CODE };
byte[] privKeyTypeBytes = new byte[] { PRIVATE.CODE };
byte[] rawPubKeyBytes = pubKey.getRawKeyBytes();
byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();
assertArrayEquals(BytesUtils.concat(algoBytes, pubKeyTypeBytes, rawPubKeyBytes), pubKey.toBytes());
assertArrayEquals(BytesUtils.concat(algoBytes, privKeyTypeBytes, rawPrivKeyBytes), privKey.toBytes());

// retrievePubKeyTest
PubKey retrievedPubKey = signatureFunction.retrievePubKey(privKey);
assertEquals(pubKey.getKeyType(), retrievedPubKey.getKeyType());
assertEquals(pubKey.getRawKeyBytes().length, retrievedPubKey.getRawKeyBytes().length);
assertEquals(pubKey.getAlgorithm(), retrievedPubKey.getAlgorithm());
assertArrayEquals(pubKey.toBytes(), retrievedPubKey.toBytes());

// signTest
byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);
SignatureDigest signatureDigest = signatureFunction.sign(privKey, data);
byte[] signatureBytes = signatureDigest.toBytes();
assertEquals(2 + 256, signatureBytes.length);
assertEquals(algorithm.code(), signatureDigest.getAlgorithm());
assertEquals(PKIAlgorithm.SHA1WITHRSA2048.code(), signatureDigest.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 31 & 0x00FF)),
signatureDigest.getAlgorithm());

byte[] rawSinatureBytes = signatureDigest.getRawDigest();
assertArrayEquals(BytesUtils.concat(algoBytes, rawSinatureBytes), signatureBytes);

// verifyTest
assertTrue(signatureFunction.verify(signatureDigest, pubKey, data));

// supportPrivKeyTest
byte[] privKeyBytes = privKey.toBytes();
assertTrue(signatureFunction.supportPrivKey(privKeyBytes));

// resolvePrivKeyTest
PrivKey resolvedPrivKey = signatureFunction.resolvePrivKey(privKeyBytes);
assertEquals(PRIVATE.CODE, resolvedPrivKey.getKeyType().CODE);
assertEquals(PKIAlgorithm.SHA1WITHRSA2048.code(), resolvedPrivKey.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 31 & 0x00FF)),
resolvedPrivKey.getAlgorithm());
assertArrayEquals(privKeyBytes, resolvedPrivKey.toBytes());

// supportPubKeyTest
byte[] pubKeyBytes = pubKey.toBytes();
assertTrue(signatureFunction.supportPubKey(pubKeyBytes));

// resolvedPubKeyTest
PubKey resolvedPubKey = signatureFunction.resolvePubKey(pubKeyBytes);
assertEquals(PUBLIC.CODE, resolvedPubKey.getKeyType().CODE);
assertEquals(PKIAlgorithm.SHA1WITHRSA2048.code(), resolvedPubKey.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 31 & 0x00FF)),
resolvedPubKey.getAlgorithm());
assertArrayEquals(pubKeyBytes, resolvedPubKey.toBytes());

//supportDigestTest
byte[] signatureDigestBytes = signatureDigest.toBytes();
assertTrue(signatureFunction.supportDigest(signatureDigestBytes));

// resolveDigestTest
SignatureDigest resolvedSignatureDigest = signatureFunction.resolveDigest(signatureDigestBytes);
assertEquals(256, resolvedSignatureDigest.getRawDigest().length);
assertEquals(PKIAlgorithm.SHA1WITHRSA2048.code(), resolvedSignatureDigest.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 31 & 0x00FF)),
resolvedSignatureDigest.getAlgorithm());
assertArrayEquals(signatureDigestBytes, resolvedSignatureDigest.toBytes());
}
}

+ 128
- 0
source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunctionTest.java View File

@@ -0,0 +1,128 @@
package com.jd.blockchain.crypto.service.pki;

import com.jd.blockchain.crypto.*;
import com.jd.blockchain.utils.io.BytesUtils;
import org.junit.Test;

import java.util.Random;

import static com.jd.blockchain.crypto.CryptoAlgorithm.ASYMMETRIC_KEY;
import static com.jd.blockchain.crypto.CryptoAlgorithm.SIGNATURE_ALGORITHM;
import static com.jd.blockchain.crypto.CryptoKeyType.PRIVATE;
import static com.jd.blockchain.crypto.CryptoKeyType.PUBLIC;
import static org.junit.Assert.*;

/**
* @author zhanglin33
* @title: SHA1WITHRSA4096SignatureFunctionTest
* @description: TODO
* @date 2019-05-16, 10:49
*/
public class SHA1WITHRSA4096SignatureFunctionTest {

@Test
public void getAlgorithmTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA4096");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

assertEquals(signatureFunction.getAlgorithm().name(), algorithm.name());
assertEquals(signatureFunction.getAlgorithm().code(), algorithm.code());

algorithm = Crypto.getAlgorithm("SHA1withRsa4096");
assertNotNull(algorithm);

assertEquals(signatureFunction.getAlgorithm().name(), algorithm.name());
assertEquals(signatureFunction.getAlgorithm().code(), algorithm.code());

algorithm = Crypto.getAlgorithm("rsa2048");
assertNull(algorithm);
}

//@Test
public void generateKeyPairTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA4096");
assertNotNull(algorithm);

AsymmetricKeypair keyPair = Crypto.getSignatureFunction(algorithm).generateKeypair();

PubKey pubKey = keyPair.getPubKey();
PrivKey privKey = keyPair.getPrivKey();

assertEquals(PUBLIC.CODE, pubKey.getKeyType().CODE);
assertTrue(pubKey.getRawKeyBytes().length > 515);
assertEquals(PRIVATE.CODE, privKey.getKeyType().CODE);
assertTrue(privKey.getRawKeyBytes().length > 2307);

assertEquals(algorithm.code(), pubKey.getAlgorithm());
assertEquals(algorithm.code(), privKey.getAlgorithm());

byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm);
byte[] pubKeyTypeBytes = new byte[] { PUBLIC.CODE };
byte[] privKeyTypeBytes = new byte[] { PRIVATE.CODE };
byte[] rawPubKeyBytes = pubKey.getRawKeyBytes();
byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();
assertArrayEquals(BytesUtils.concat(algoBytes, pubKeyTypeBytes, rawPubKeyBytes), pubKey.toBytes());
assertArrayEquals(BytesUtils.concat(algoBytes, privKeyTypeBytes, rawPrivKeyBytes), privKey.toBytes());

// retrievePubKeyTest
SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);
PubKey retrievedPubKey = signatureFunction.retrievePubKey(privKey);
assertEquals(pubKey.getKeyType(), retrievedPubKey.getKeyType());
assertEquals(pubKey.getRawKeyBytes().length, retrievedPubKey.getRawKeyBytes().length);
assertEquals(pubKey.getAlgorithm(), retrievedPubKey.getAlgorithm());
assertArrayEquals(pubKey.toBytes(), retrievedPubKey.toBytes());


// signAndVerifyTest
byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);

SignatureDigest signatureDigest = signatureFunction.sign(privKey, data);
byte[] signatureBytes = signatureDigest.toBytes();
assertEquals(2 + 512, signatureBytes.length);
assertEquals(algorithm.code(), signatureDigest.getAlgorithm());
assertEquals(PKIAlgorithm.SHA1WITHRSA4096.code(), signatureDigest.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 32 & 0x00FF)),
signatureDigest.getAlgorithm());
algoBytes = BytesUtils.toBytes(signatureDigest.getAlgorithm());
byte[] rawSinatureBytes = signatureDigest.getRawDigest();
assertArrayEquals(BytesUtils.concat(algoBytes, rawSinatureBytes), signatureBytes);
assertTrue(signatureFunction.verify(signatureDigest, pubKey, data));

// supportAndResolvePrivKeyTest
byte[] privKeyBytes = privKey.toBytes();
assertTrue(signatureFunction.supportPrivKey(privKeyBytes));
PrivKey resolvedPrivKey = signatureFunction.resolvePrivKey(privKeyBytes);
assertEquals(PRIVATE.CODE, resolvedPrivKey.getKeyType().CODE);
assertEquals(PKIAlgorithm.SHA1WITHRSA4096.code(), resolvedPrivKey.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 32 & 0x00FF)),
resolvedPrivKey.getAlgorithm());
assertArrayEquals(privKeyBytes, resolvedPrivKey.toBytes());

// supportAndResolvePubKeyTest
byte[] pubKeyBytes = pubKey.toBytes();
assertTrue(signatureFunction.supportPubKey(pubKeyBytes));
PubKey resolvedPubKey = signatureFunction.resolvePubKey(pubKeyBytes);
assertEquals(PUBLIC.CODE, resolvedPubKey.getKeyType().CODE);
assertEquals(PKIAlgorithm.SHA1WITHRSA4096.code(), resolvedPubKey.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 32 & 0x00FF)),
resolvedPubKey.getAlgorithm());
assertArrayEquals(pubKeyBytes, resolvedPubKey.toBytes());


// supportAndResolveDigestTest
byte[] signatureDigestBytes = signatureDigest.toBytes();
assertTrue(signatureFunction.supportDigest(signatureDigestBytes));
SignatureDigest resolvedSignatureDigest = signatureFunction.resolveDigest(signatureDigestBytes);
assertEquals(512, resolvedSignatureDigest.getRawDigest().length);
assertEquals(PKIAlgorithm.SHA1WITHRSA4096.code(), resolvedSignatureDigest.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 32 & 0x00FF)),
resolvedSignatureDigest.getAlgorithm());
assertArrayEquals(signatureDigestBytes, resolvedSignatureDigest.toBytes());
}
}

+ 273
- 0
source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunctionTest.java View File

@@ -0,0 +1,273 @@
package com.jd.blockchain.crypto.service.pki;

import com.jd.blockchain.crypto.*;
import com.jd.blockchain.utils.io.BytesUtils;
import org.junit.Test;

import java.util.Random;

import static com.jd.blockchain.crypto.CryptoAlgorithm.ASYMMETRIC_KEY;
import static com.jd.blockchain.crypto.CryptoAlgorithm.SIGNATURE_ALGORITHM;
import static com.jd.blockchain.crypto.CryptoKeyType.PRIVATE;
import static com.jd.blockchain.crypto.CryptoKeyType.PUBLIC;
import static org.junit.Assert.*;

/**
* @author zhanglin33
* @title: SM3WITHSM2SignatureFunctionTest
* @description: TODO
* @date 2019-05-16, 17:04
*/
public class SM3WITHSM2SignatureFunctionTest {

@Test
public void getAlgorithmTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("SM3WITHSM2");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

assertEquals(signatureFunction.getAlgorithm().name(), algorithm.name());
assertEquals(signatureFunction.getAlgorithm().code(), algorithm.code());

algorithm = Crypto.getAlgorithm("sm3withsm2");
assertNotNull(algorithm);

assertEquals(signatureFunction.getAlgorithm().name(), algorithm.name());
assertEquals(signatureFunction.getAlgorithm().code(), algorithm.code());

algorithm = Crypto.getAlgorithm("sm3withs");
assertNull(algorithm);
}

@Test
public void generateKeyPairTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("SM3WITHSM2");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();
PrivKey privKey = keyPair.getPrivKey();

assertEquals(PUBLIC.CODE, pubKey.getKeyType().CODE);
assertTrue(pubKey.getRawKeyBytes().length > 32);
assertEquals(PRIVATE.CODE, privKey.getKeyType().CODE);
assertTrue(privKey.getRawKeyBytes().length > 65 + 32);

assertEquals(algorithm.code(), pubKey.getAlgorithm());
assertEquals(algorithm.code(), privKey.getAlgorithm());

byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm);
byte[] pubKeyTypeBytes = new byte[] { PUBLIC.CODE };
byte[] privKeyTypeBytes = new byte[] { PRIVATE.CODE };
byte[] rawPubKeyBytes = pubKey.getRawKeyBytes();
byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();
assertArrayEquals(BytesUtils.concat(algoBytes, pubKeyTypeBytes, rawPubKeyBytes), pubKey.toBytes());
assertArrayEquals(BytesUtils.concat(algoBytes, privKeyTypeBytes, rawPrivKeyBytes), privKey.toBytes());
}

@Test
public void retrievePubKeyTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("SM3WITHSM2");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();
PrivKey privKey = keyPair.getPrivKey();

PubKey retrievedPubKey = signatureFunction.retrievePubKey(privKey);

assertEquals(pubKey.getKeyType(), retrievedPubKey.getKeyType());
assertEquals(pubKey.getRawKeyBytes().length, retrievedPubKey.getRawKeyBytes().length);
assertEquals(pubKey.getAlgorithm(), retrievedPubKey.getAlgorithm());
assertArrayEquals(pubKey.toBytes(), retrievedPubKey.toBytes());
}

@Test
public void signTest() {

byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("SM3WITHSM2");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PrivKey privKey = keyPair.getPrivKey();
SignatureDigest signatureDigest = signatureFunction.sign(privKey, data);

byte[] signatureBytes = signatureDigest.toBytes();

assertTrue(signatureBytes.length > 2 + 64);
assertEquals(algorithm.code(), signatureDigest.getAlgorithm());

assertEquals(PKIAlgorithm.SM3WITHSM2.code(), signatureDigest.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 33 & 0x00FF)),
signatureDigest.getAlgorithm());

byte[] algoBytes = BytesUtils.toBytes(signatureDigest.getAlgorithm());
byte[] rawSinatureBytes = signatureDigest.getRawDigest();
assertArrayEquals(BytesUtils.concat(algoBytes, rawSinatureBytes), signatureBytes);
}

@Test
public void verifyTest() {
byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("SM3WITHSM2");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();
PrivKey privKey = keyPair.getPrivKey();
SignatureDigest signatureDigest = signatureFunction.sign(privKey, data);

System.out.println(signatureDigest.getRawDigest().length);
assertTrue(signatureFunction.verify(signatureDigest, pubKey, data));
}

@Test
public void supportPrivKeyTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("SM3WITHSM2");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PrivKey privKey = keyPair.getPrivKey();
byte[] privKeyBytes = privKey.toBytes();

assertTrue(signatureFunction.supportPrivKey(privKeyBytes));
}

@Test
public void resolvePrivKeyTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("SM3WITHSM2");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PrivKey privKey = keyPair.getPrivKey();
byte[] privKeyBytes = privKey.toBytes();

PrivKey resolvedPrivKey = signatureFunction.resolvePrivKey(privKeyBytes);

assertEquals(PRIVATE.CODE, resolvedPrivKey.getKeyType().CODE);
assertEquals(PKIAlgorithm.SM3WITHSM2.code(), resolvedPrivKey.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 33 & 0x00FF)),
resolvedPrivKey.getAlgorithm());
assertArrayEquals(privKeyBytes, resolvedPrivKey.toBytes());
}

@Test
public void supportPubKeyTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("SM3WITHSM2");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();
byte[] pubKeyBytes = pubKey.toBytes();

assertTrue(signatureFunction.supportPubKey(pubKeyBytes));
}

@Test
public void resolvePubKeyTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("SM3WITHSM2");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();
byte[] pubKeyBytes = pubKey.toBytes();

PubKey resolvedPubKey = signatureFunction.resolvePubKey(pubKeyBytes);

assertEquals(PUBLIC.CODE, resolvedPubKey.getKeyType().CODE);
assertEquals(PKIAlgorithm.SM3WITHSM2.code(), resolvedPubKey.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 33 & 0x00FF)),
resolvedPubKey.getAlgorithm());
assertArrayEquals(pubKeyBytes, resolvedPubKey.toBytes());
}

@Test
public void supportDigestTest() {

byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("SM3WITHSM2");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PrivKey privKey = keyPair.getPrivKey();

SignatureDigest signatureDigest = signatureFunction.sign(privKey, data);

byte[] signatureDigestBytes = signatureDigest.toBytes();
assertTrue(signatureFunction.supportDigest(signatureDigestBytes));
}

@Test
public void resolveDigestTest() {

byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("SM3WITHSM2");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PrivKey privKey = keyPair.getPrivKey();

SignatureDigest signatureDigest = signatureFunction.sign(privKey, data);

byte[] signatureDigestBytes = signatureDigest.toBytes();

SignatureDigest resolvedSignatureDigest = signatureFunction.resolveDigest(signatureDigestBytes);

assertTrue(resolvedSignatureDigest.getRawDigest().length > 64);
assertEquals(PKIAlgorithm.SM3WITHSM2.code(), resolvedSignatureDigest.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 33 & 0x00FF)),
resolvedSignatureDigest.getAlgorithm());
assertArrayEquals(signatureDigestBytes, resolvedSignatureDigest.toBytes());
}
}

+ 396
- 0
source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CSRBuilderTest.java View File

@@ -0,0 +1,396 @@
package com.jd.blockchain.crypto.utils;

import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.asn1.pkcs.CertificationRequestInfo;
import org.bouncycastle.asn1.x500.RDN;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.bouncycastle.util.encoders.Base64;
import org.junit.Test;

import java.io.IOException;
import java.security.*;

import static org.junit.Assert.*;

/**
* @author zhanglin33
* @title: CSRBuilderTest
* @description: TODO
* @date 2019-05-10, 17:22
*/
public class CSRBuilderTest {

@Test
public void defaultCSRTest(){

String countryName = "CN";
String stateName = "Beijing";
String cityName = "Beijing";
String organizationName = "JD.com";
String departmentName = "Blockchain Department";
String domainName = "ledger.jd.com";
String emailName = "zhanglin33@jd.com";

CSRBuilder builder = new CSRBuilder();

builder.init();
String csr = builder.buildRequest(countryName,stateName,cityName,
organizationName,departmentName,domainName,
emailName);

PublicKey pubKey = builder.getPubKey();
PrivateKey privKey = builder.getPrivKey();

byte[] crsBytes = Base64.decode(csr);
PKCS10CertificationRequest request = null;
try {
request = new PKCS10CertificationRequest(crsBytes);
} catch (IOException e) {
e.printStackTrace();
}
assertNotNull(request);
assertEquals("1.2.840.113549.1.1.5",request.getSignatureAlgorithm().getAlgorithm().getId());
byte[] pubKeyBytes = new byte[0];
try {
pubKeyBytes = request.getSubjectPublicKeyInfo().getEncoded();
} catch (IOException e) {
e.printStackTrace();
}
assertArrayEquals(pubKeyBytes,pubKey.getEncoded());

RDN[] rdns = request.getSubject().getRDNs();
assertEquals(BCStyle.C, rdns[0].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.ST, rdns[1].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.L, rdns[2].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.O, rdns[3].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.OU, rdns[4].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.CN, rdns[5].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.E, rdns[6].getFirst().getType().toASN1Primitive());

assertEquals("CN", rdns[0].getFirst().getValue().toASN1Primitive().toString());
assertEquals("Beijing", rdns[1].getFirst().getValue().toASN1Primitive().toString());
assertEquals("Beijing", rdns[2].getFirst().getValue().toASN1Primitive().toString());
assertEquals("JD.com", rdns[3].getFirst().getValue().toASN1Primitive().toString());
assertEquals("Blockchain Department", rdns[4].getFirst().getValue().toASN1Primitive().toString());
assertEquals("ledger.jd.com", rdns[5].getFirst().getValue().toASN1Primitive().toString());
assertEquals("zhanglin33@jd.com", rdns[6].getFirst().getValue().toASN1Primitive().toString());

byte[] signature = request.getSignature();

CertificationRequestInfo requestInfo = new CertificationRequestInfo(request.getSubject(),request.getSubjectPublicKeyInfo(),new DERSet());
byte[] message = new byte[0];
try {
message = requestInfo.getEncoded(ASN1Encoding.DER);
} catch (IOException e) {
e.printStackTrace();
}

Signature signer;
byte[] result = new byte[0];
try {
signer = Signature.getInstance("SHA1withRSA");
signer.initSign(privKey);
signer.update(message);
result = signer.sign();
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
e.printStackTrace();
}
assertArrayEquals(result,signature);

Signature verifier;
boolean isValid = false;
try {
verifier = Signature.getInstance("SHA1withRSA");
verifier.initVerify(pubKey);
verifier.update(message);
isValid = verifier.verify(signature);
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
e.printStackTrace();
}
assertTrue(isValid);
}

@Test
public void SHA1withRSA2048CSRTest(){

String countryName = "CN";
String stateName = "Beijing";
String cityName = "Beijing";
String organizationName = "JD.com";
String departmentName = "Blockchain Department";
String domainName = "ledger.jd.com";
String emailName = "zhanglin33@jd.com";

CSRBuilder builder = new CSRBuilder();

builder.init("SHA1withRSA",2048);
String csr = builder.buildRequest(countryName,stateName,cityName,
organizationName,departmentName,domainName,
emailName);

PublicKey pubKey = builder.getPubKey();
PrivateKey privKey = builder.getPrivKey();

byte[] crsBytes = Base64.decode(csr);
PKCS10CertificationRequest request = null;
try {
request = new PKCS10CertificationRequest(crsBytes);
} catch (IOException e) {
e.printStackTrace();
}
assertNotNull(request);
assertEquals("1.2.840.113549.1.1.5",request.getSignatureAlgorithm().getAlgorithm().getId());
byte[] pubKeyBytes = new byte[0];
try {
pubKeyBytes = request.getSubjectPublicKeyInfo().getEncoded();
} catch (IOException e) {
e.printStackTrace();
}
assertArrayEquals(pubKeyBytes,pubKey.getEncoded());

RDN[] rdns = request.getSubject().getRDNs();
assertEquals(BCStyle.C, rdns[0].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.ST, rdns[1].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.L, rdns[2].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.O, rdns[3].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.OU, rdns[4].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.CN, rdns[5].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.E, rdns[6].getFirst().getType().toASN1Primitive());

assertEquals("CN", rdns[0].getFirst().getValue().toASN1Primitive().toString());
assertEquals("Beijing", rdns[1].getFirst().getValue().toASN1Primitive().toString());
assertEquals("Beijing", rdns[2].getFirst().getValue().toASN1Primitive().toString());
assertEquals("JD.com", rdns[3].getFirst().getValue().toASN1Primitive().toString());
assertEquals("Blockchain Department", rdns[4].getFirst().getValue().toASN1Primitive().toString());
assertEquals("ledger.jd.com", rdns[5].getFirst().getValue().toASN1Primitive().toString());
assertEquals("zhanglin33@jd.com", rdns[6].getFirst().getValue().toASN1Primitive().toString());

byte[] signature = request.getSignature();

CertificationRequestInfo requestInfo = new CertificationRequestInfo(request.getSubject(),request.getSubjectPublicKeyInfo(),new DERSet());
byte[] message = new byte[0];
try {
message = requestInfo.getEncoded(ASN1Encoding.DER);
} catch (IOException e) {
e.printStackTrace();
}

Signature signer;
byte[] result = new byte[0];
try {
signer = Signature.getInstance("SHA1withRSA");
signer.initSign(privKey);
signer.update(message);
result = signer.sign();
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
e.printStackTrace();
}
assertArrayEquals(result,signature);

Signature verifier;
boolean isValid = false;
try {
verifier = Signature.getInstance("SHA1withRSA");
verifier.initVerify(pubKey);
verifier.update(message);
isValid = verifier.verify(signature);
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
e.printStackTrace();
}
assertTrue(isValid);
}


// @Test
public void SHA1withRSA4096CSRTest(){

String countryName = "CN";
String stateName = "Beijing";
String cityName = "Beijing";
String organizationName = "JD.com";
String departmentName = "Blockchain Department";
String domainName = "ledger.jd.com";
String emailName = "zhanglin33@jd.com";

CSRBuilder builder = new CSRBuilder();

builder.init("SHA1withRSA",4096);
String csr = builder.buildRequest(countryName,stateName,cityName,
organizationName,departmentName,domainName,
emailName);

PublicKey pubKey = builder.getPubKey();
PrivateKey privKey = builder.getPrivKey();

byte[] crsBytes = Base64.decode(csr);
PKCS10CertificationRequest request = null;
try {
request = new PKCS10CertificationRequest(crsBytes);
} catch (IOException e) {
e.printStackTrace();
}
assertNotNull(request);
assertEquals("1.2.840.113549.1.1.5",request.getSignatureAlgorithm().getAlgorithm().getId());
byte[] pubKeyBytes = new byte[0];
try {
pubKeyBytes = request.getSubjectPublicKeyInfo().getEncoded();
} catch (IOException e) {
e.printStackTrace();
}
assertArrayEquals(pubKeyBytes,pubKey.getEncoded());

RDN[] rdns = request.getSubject().getRDNs();
assertEquals(BCStyle.C, rdns[0].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.ST, rdns[1].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.L, rdns[2].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.O, rdns[3].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.OU, rdns[4].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.CN, rdns[5].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.E, rdns[6].getFirst().getType().toASN1Primitive());

assertEquals("CN", rdns[0].getFirst().getValue().toASN1Primitive().toString());
assertEquals("Beijing", rdns[1].getFirst().getValue().toASN1Primitive().toString());
assertEquals("Beijing", rdns[2].getFirst().getValue().toASN1Primitive().toString());
assertEquals("JD.com", rdns[3].getFirst().getValue().toASN1Primitive().toString());
assertEquals("Blockchain Department", rdns[4].getFirst().getValue().toASN1Primitive().toString());
assertEquals("ledger.jd.com", rdns[5].getFirst().getValue().toASN1Primitive().toString());
assertEquals("zhanglin33@jd.com", rdns[6].getFirst().getValue().toASN1Primitive().toString());

byte[] signature = request.getSignature();

CertificationRequestInfo requestInfo = new CertificationRequestInfo(request.getSubject(),request.getSubjectPublicKeyInfo(),new DERSet());
byte[] message = new byte[0];
try {
message = requestInfo.getEncoded(ASN1Encoding.DER);
} catch (IOException e) {
e.printStackTrace();
}

Signature signer;
byte[] result = new byte[0];
try {
signer = Signature.getInstance("SHA1withRSA");
signer.initSign(privKey);
signer.update(message);
result = signer.sign();
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
e.printStackTrace();
}
assertArrayEquals(result,signature);

Signature verifier;
boolean isValid = false;
try {
verifier = Signature.getInstance("SHA1withRSA");
verifier.initVerify(pubKey);
verifier.update(message);
isValid = verifier.verify(signature);
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
e.printStackTrace();
}
assertTrue(isValid);
}


@Test
public void SM3withSM2CSRTest(){

String countryName = "CN";
String stateName = "Beijing";
String cityName = "Beijing";
String organizationName = "JD.com";
String departmentName = "Blockchain Department";
String domainName = "ledger.jd.com";
String emailName = "zhanglin33@jd.com";

CSRBuilder builder = new CSRBuilder();

builder.init("SM3withSM2",256);
String csr = builder.buildRequest(countryName,stateName,cityName,
organizationName,departmentName,domainName,
emailName);

System.out.println(csr);
PublicKey pubKey = builder.getPubKey();
PrivateKey privKey = builder.getPrivKey();

byte[] crsBytes = Base64.decode(csr);
PKCS10CertificationRequest request = null;
try {
request = new PKCS10CertificationRequest(crsBytes);
} catch (IOException e) {
e.printStackTrace();
}
assertNotNull(request);
assertEquals("1.2.156.10197.1.501",request.getSignatureAlgorithm().getAlgorithm().getId());
byte[] pubKeyBytes = new byte[0];
try {
pubKeyBytes = request.getSubjectPublicKeyInfo().getEncoded();
} catch (IOException e) {
e.printStackTrace();
}
assertArrayEquals(pubKeyBytes,pubKey.getEncoded());

RDN[] rdns = request.getSubject().getRDNs();
assertEquals(BCStyle.C, rdns[0].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.ST, rdns[1].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.L, rdns[2].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.O, rdns[3].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.OU, rdns[4].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.CN, rdns[5].getFirst().getType().toASN1Primitive());
assertEquals(BCStyle.E, rdns[6].getFirst().getType().toASN1Primitive());

assertEquals("CN", rdns[0].getFirst().getValue().toASN1Primitive().toString());
assertEquals("Beijing", rdns[1].getFirst().getValue().toASN1Primitive().toString());
assertEquals("Beijing", rdns[2].getFirst().getValue().toASN1Primitive().toString());
assertEquals("JD.com", rdns[3].getFirst().getValue().toASN1Primitive().toString());
assertEquals("Blockchain Department", rdns[4].getFirst().getValue().toASN1Primitive().toString());
assertEquals("ledger.jd.com", rdns[5].getFirst().getValue().toASN1Primitive().toString());
assertEquals("zhanglin33@jd.com", rdns[6].getFirst().getValue().toASN1Primitive().toString());

byte[] signature = request.getSignature();

CertificationRequestInfo requestInfo = new CertificationRequestInfo(request.getSubject(),request.getSubjectPublicKeyInfo(),new DERSet());
byte[] message = new byte[0];
try {
message = requestInfo.getEncoded(ASN1Encoding.DER);
} catch (IOException e) {
e.printStackTrace();
}

Signature signer;
byte[] result = new byte[0];
try {
signer = Signature.getInstance("SM3withSM2");
signer.initSign(privKey);
signer.update(message);
result = signer.sign();
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
e.printStackTrace();
}

Signature verifier;
boolean isValid = false;
try {
verifier = Signature.getInstance("SM3withSM2");
verifier.initVerify(pubKey);
verifier.update(message);
isValid = verifier.verify(signature);
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
e.printStackTrace();
}
assertTrue(isValid);

try {
verifier = Signature.getInstance("SM3withSM2");
verifier.initVerify(pubKey);
verifier.update(message);
isValid = verifier.verify(result);
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
e.printStackTrace();
}
assertTrue(isValid);
}
}

+ 146
- 0
source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CertParserTest.java View File

@@ -0,0 +1,146 @@
package com.jd.blockchain.crypto.utils;

import org.junit.Test;

import static org.junit.Assert.assertEquals;

/**
* @author zhanglin33
* @title: CertParserTest
* @description: TODO
* @date 2019-05-13, 10:05
*/
public class CertParserTest {

@Test
public void parseSHA1WITHRSA2048Test() {
CertParser parser = new CertParser();
String issuerCert =
"-----BEGIN CERTIFICATE-----\n" +
"MIIDzzCCAregAwIBAgIKUalCR1Mt5ZSK8jANBgkqhkiG9w0BAQUFADBZMQswCQYD\n" +
"VQQGEwJDTjEwMC4GA1UEChMnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24g\n" +
"QXV0aG9yaXR5MRgwFgYDVQQDEw9DRkNBIFRFU1QgQ1MgQ0EwHhcNMTIwODI5MDU1\n" +
"NDM2WhcNMzIwODI0MDU1NDM2WjBZMQswCQYDVQQGEwJDTjEwMC4GA1UEChMnQ2hp\n" +
"bmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRgwFgYDVQQDEw9D\n" +
"RkNBIFRFU1QgT0NBMTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC8\n" +
"jn0n8Fp6hcRdACdn1+Y6GAkC6KGgNdKyHPrmsdmhCjnd/i4qUFwnG8cp3D4lFw1G\n" +
"jmjSO5yVYbik/NbS6lbNpRgTK3fDfMFvLJpRIC+IFhG9SdAC2hwjsH9qTpL9cK2M\n" +
"bSdrC6pBdDgnbzaM9AGBF4Y6vXhj5nah4ZMsBvDp19LzXjlGuTPLuAgv9ZlWknsd\n" +
"RN70PIAmvomd10uqX4GIJ4Jq/FdKXOLZ2DNK/NhRyN6Yq71L3ham6tutXeZow5t5\n" +
"0254AnUlo1u6SeH9F8itER653o/oMLFwp+63qXAcqrHUlOQPX+JI8fkumSqZ4F2F\n" +
"t/HfVMnqdtFNCnh5+eIBAgMBAAGjgZgwgZUwHwYDVR0jBBgwFoAUdN7FjQp9EBqq\n" +
"aYNbTSHOhpvMcTgwDAYDVR0TBAUwAwEB/zA4BgNVHR8EMTAvMC2gK6AphidodHRw\n" +
"Oi8vMjEwLjc0LjQyLjMvdGVzdHJjYS9SU0EvY3JsMS5jcmwwCwYDVR0PBAQDAgEG\n" +
"MB0GA1UdDgQWBBT8C7xEmg4xoYOpgYcnHgVCxr9W+DANBgkqhkiG9w0BAQUFAAOC\n" +
"AQEAb7W0K9fZPA+JPw6lRiMDaUJ0oh052yEXreMBfoPulxkBj439qombDiFggRLc\n" +
"3g8wIEKzMOzOKXTWtnzYwN3y/JQSuJb/M1QqOEEM2PZwCxI4AkBuH6jg03RjlkHg\n" +
"/kTtuIFp9ItBCC2/KkKlp0ENfn4XgVg2KtAjZ7lpyVU0LPnhEqqUVY/xthjlCSa7\n" +
"/XHNStRxsfCTIBUWJ8n2FZyQhfV/UkMNHDBIiJR0v6C4Ai0/290WvbPEIAq+03Si\n" +
"fsHzBeA0C8lP5VzfAr6wWePaZMCpStpLaoXNcAqReKxQllElOqAhRxC5VKH+rnIQ\n" +
"OMRZvB7FRyE9IfwKApngcZbA5g==\n" +
"-----END CERTIFICATE-----";

String userCert = "MIIEQDCCAyigAwIBAgIFICdVYzEwDQYJKoZIhvcNAQEFBQAwWTELMAkGA1UEBhMCQ04xMDAuBgNVBAoTJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEYMBYGA1UEAxMPQ0ZDQSBURVNUIE9DQTExMB4XDTE5MDUxMDExMjAyNFoXDTIxMDUxMDExMjAyNFowcjELMAkGA1UEBhMCQ04xGDAWBgNVBAoTD0NGQ0EgVEVTVCBPQ0ExMTERMA8GA1UECxMITG9jYWwgUkExFTATBgNVBAsTDEluZGl2aWR1YWwtMTEfMB0GA1UEAxQWMDUxQGFhYWFhQFpIMDkzNTgwMjhAMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJx3F2WD1dJPzK/nRHO7d1TJ1hTjzGTmv0PQ7ECsJAh3U3BtnGTpCB+b4+JMI4LO8nHkKIBQ3P9XnF+Bf1iXdWNAQ4aWCxa2nV7lCp4w0GliPu/EMgIfmsSDUtgqbM3cr8sR8r9m1xG3gt2TIQJ+jT7sAiguU/kyNzpjaccOUIgUFa8IDFq9UeB76MXtCuhlERRZQCl47e+9w7ZoxmE7e6IZORxPp7rQWVBHlR9ntWjJfNDTm3gMP5ehP+yIZnKx1LudxkBLQxpMmspzOyH1zqx5nkKe49AfWWpDxxRvYkriyYC3aE81qLsU/bhLwNEKOju7BGDF/mhJLZUedojM0gMCAwEAAaOB9TCB8jAfBgNVHSMEGDAWgBT8C7xEmg4xoYOpgYcnHgVCxr9W+DBIBgNVHSAEQTA/MD0GCGCBHIbvKgECMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2ZjYS5jb20uY24vdXMvdXMtMTUuaHRtMDoGA1UdHwQzMDEwL6AtoCuGKWh0dHA6Ly8yMTAuNzQuNDIuMy9PQ0ExMS9SU0EvY3JsMjU2OTMuY3JsMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQU5oKGaQs7Jt5Gfbt1XhFTWAySEKswHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBBQUAA4IBAQAlmPRaImZV51iKjtpMKuyLMw7dX8L0lY3tl+pVZZSxHuwsN4GCCtV0Ej50up+/6EbfL4NUTiuHVAjCroKKvb+94CrdEwdnQGM5IbGSjT78nQpeASXbIWuUwA+ImjvZOzvq/0b56AzonNzBxOMGko/bj5smM6X8jrgJ0NQppo2KNSVNC4JbuoNWI4FM94SE4DUi9H7EYl4JdOtDaDtCsq49o/A1CZyYrmoOPCgxpQQXmuB3lGq/jyoOlW2aW8uee/hYG1JJcSHLBjF0WBwdxssgbBotA5f1PebiIMSbFgjk57bd4M80hhU/rI4Hkn9pcp5R7NsX95TtyDIg90LboBnW";

parser.parse(userCert, issuerCert);
assertEquals("SHA1WITHRSA",parser.getSigAlgName());
}

@Test
public void parseSHA1WITHRSA4096Test() {
CertParser parser = new CertParser();
String issuerCert =
"-----BEGIN CERTIFICATE-----\n" +
"MIIDzzCCAregAwIBAgIKUalCR1Mt5ZSK8jANBgkqhkiG9w0BAQUFADBZMQswCQYD\n" +
"VQQGEwJDTjEwMC4GA1UEChMnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24g\n" +
"QXV0aG9yaXR5MRgwFgYDVQQDEw9DRkNBIFRFU1QgQ1MgQ0EwHhcNMTIwODI5MDU1\n" +
"NDM2WhcNMzIwODI0MDU1NDM2WjBZMQswCQYDVQQGEwJDTjEwMC4GA1UEChMnQ2hp\n" +
"bmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRgwFgYDVQQDEw9D\n" +
"RkNBIFRFU1QgT0NBMTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC8\n" +
"jn0n8Fp6hcRdACdn1+Y6GAkC6KGgNdKyHPrmsdmhCjnd/i4qUFwnG8cp3D4lFw1G\n" +
"jmjSO5yVYbik/NbS6lbNpRgTK3fDfMFvLJpRIC+IFhG9SdAC2hwjsH9qTpL9cK2M\n" +
"bSdrC6pBdDgnbzaM9AGBF4Y6vXhj5nah4ZMsBvDp19LzXjlGuTPLuAgv9ZlWknsd\n" +
"RN70PIAmvomd10uqX4GIJ4Jq/FdKXOLZ2DNK/NhRyN6Yq71L3ham6tutXeZow5t5\n" +
"0254AnUlo1u6SeH9F8itER653o/oMLFwp+63qXAcqrHUlOQPX+JI8fkumSqZ4F2F\n" +
"t/HfVMnqdtFNCnh5+eIBAgMBAAGjgZgwgZUwHwYDVR0jBBgwFoAUdN7FjQp9EBqq\n" +
"aYNbTSHOhpvMcTgwDAYDVR0TBAUwAwEB/zA4BgNVHR8EMTAvMC2gK6AphidodHRw\n" +
"Oi8vMjEwLjc0LjQyLjMvdGVzdHJjYS9SU0EvY3JsMS5jcmwwCwYDVR0PBAQDAgEG\n" +
"MB0GA1UdDgQWBBT8C7xEmg4xoYOpgYcnHgVCxr9W+DANBgkqhkiG9w0BAQUFAAOC\n" +
"AQEAb7W0K9fZPA+JPw6lRiMDaUJ0oh052yEXreMBfoPulxkBj439qombDiFggRLc\n" +
"3g8wIEKzMOzOKXTWtnzYwN3y/JQSuJb/M1QqOEEM2PZwCxI4AkBuH6jg03RjlkHg\n" +
"/kTtuIFp9ItBCC2/KkKlp0ENfn4XgVg2KtAjZ7lpyVU0LPnhEqqUVY/xthjlCSa7\n" +
"/XHNStRxsfCTIBUWJ8n2FZyQhfV/UkMNHDBIiJR0v6C4Ai0/290WvbPEIAq+03Si\n" +
"fsHzBeA0C8lP5VzfAr6wWePaZMCpStpLaoXNcAqReKxQllElOqAhRxC5VKH+rnIQ\n" +
"OMRZvB7FRyE9IfwKApngcZbA5g==\n" +
"-----END CERTIFICATE-----";

String userCert = "MIIFRjCCBC6gAwIBAgIFICdWiDMwDQYJKoZIhvcNAQEFBQAwWTELMAkGA1UEBhMCQ04xMDAuBgNVBAoTJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEYMBYGA1UEAxMPQ0ZDQSBURVNUIE9DQTExMB4XDTE5MDUxNjA3MDcyMloXDTIxMDUxNjA3MDcyMloweDELMAkGA1UEBhMCQ04xGDAWBgNVBAoTD0NGQ0EgVEVTVCBPQ0ExMTERMA8GA1UECxMITG9jYWwgUkExFTATBgNVBAsTDEluZGl2aWR1YWwtMTElMCMGA1UEAxQcMDUxQHpoYW5nbGluIUBaMTg2MTIyMjkyOTVAMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL0rTOxd8rsjPtFJ0aGVh9bZPy5Xo0SADaP7BbJsG4+ykLQMZHg9hTf/6fv1OsD2HEKFoMpIkW2gwCJW2nvicHcVql/shCoktc6ZBW6Dr/DxOgbO9tpoGxZ50xdI4Q0NsrxqtbCldW4ozPHdjgRJ83i1KSFh7evNrVByN/mB+jchrVGLWyJ1uIRgUUgpRZmZPoOHaizVJqrqWJGGk6xbDLR2gUQ1hTzetQaz1OeKtelHDk9FY08XSmNGssSMpuSjrxn78S888VW5WIxyo4cwrXSXFk3J7LNTy70Oga16HZjJD/vLTM6a4riPa8+uivPinKxK38/++nlBPNwhx6n46uYkd9Zvw+SJiJgpnuPJLtMZpKpJx7V1BDVEydKPUthilTdsmJtkBFSlFw0G1aKfuciBGzzJ3SKngJF/JqJAWIonVAFBGb6Gokp1Sw+T4KqXrdbjxYxiyyjZ++8O1vydgFAkx/NjsuwJnpKETiRKFJmY7YawcUvC4ixF7XQc0luFWRDYcbxOppir+ieMqhGXyaFhLUuB4WXv+rFxfa3NmkBW8q5TPzt/PwWcXpITsYTZYla/E/grB+OeZLYgjigT5YlgytPHG6Gt1ySCCd8WXFWpkBbQfXzqcvtU27RCcAUgfXk5NLb7NZCQg7heGjgzOdYJCPsa1d3m7l04+VIKGCZdAgMBAAGjgfUwgfIwHwYDVR0jBBgwFoAU/Au8RJoOMaGDqYGHJx4FQsa/VvgwSAYDVR0gBEEwPzA9BghggRyG7yoBAjAxMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmNmY2EuY29tLmNuL3VzL3VzLTE1Lmh0bTA6BgNVHR8EMzAxMC+gLaArhilodHRwOi8vMjEwLjc0LjQyLjMvT0NBMTEvUlNBL2NybDI1NzE3LmNybDALBgNVHQ8EBAMCA+gwHQYDVR0OBBYEFMjh6AzDCuNkD+pqQfiS6bqPGpI4MB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDANBgkqhkiG9w0BAQUFAAOCAQEApZaLXS6/6FudPA3l2xom5U7nJUOpQ1E6DO/ic9dFGtLE0WgyAqB3JVPvXEntppX55x/dAV7rvvz9NaEdiAe8DAj7qyoPDvC8ZWQK8U4n9l8N78QwALOURxzQNs+CBatJQzbu2w1RKVwkfE6xEIVnu+wjiAtymfwdLHMagHxDIC/eOPbTnbbtITJk2ukFfoc0WJ6Awg5lW+x7nGokEn/XAjKyRHCpkRUFGQm4ww41zlrqCqQqnVGVABJtjbdtFf7nh33QHl0fkj19nfMox9eGuntPyM0bNA0XqPMA+FWSCqeDT6uLbyaOKWxlhv53U/NCJl76U3tssMEWsm9amEDDQg==";

parser.parse(userCert, issuerCert);
assertEquals("SHA1WITHRSA",parser.getSigAlgName());
}

@Test
public void parseSM3WITHSM2Test() {
CertParser parser = new CertParser();
String issuerCert =
"-----BEGIN CERTIFICATE-----\n" +
"MIICTzCCAfOgAwIBAgIKJFSZ4SRVDndYUTAMBggqgRzPVQGDdQUAMF0xCzAJBgNV\n" +
"BAYTAkNOMTAwLgYDVQQKDCdDaGluYSBGaW5hbmNpYWwgQ2VydGlmaWNhdGlvbiBB\n" +
"dXRob3JpdHkxHDAaBgNVBAMME0NGQ0EgVEVTVCBDUyBTTTIgQ0EwHhcNMTIwODI5\n" +
"MDU0ODQ3WhcNMzIwODI0MDU0ODQ3WjBdMQswCQYDVQQGEwJDTjEwMC4GA1UECgwn\n" +
"Q2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRwwGgYDVQQD\n" +
"DBNDRkNBIFRFU1QgU00yIE9DQTExMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE\n" +
"L1mx4wriQUojGsIkNL14kslv9nwiqsiVpELOZauzghrbccNlPYKNYKZOCvXwIIqU\n" +
"9QY02d4weqKqo/JMcNsKEaOBmDCBlTAfBgNVHSMEGDAWgBS12JBvXPDYM9JjvX6y\n" +
"w43GTxJ6YTAMBgNVHRMEBTADAQH/MDgGA1UdHwQxMC8wLaAroCmGJ2h0dHA6Ly8y\n" +
"MTAuNzQuNDIuMy90ZXN0cmNhL1NNMi9jcmwxLmNybDALBgNVHQ8EBAMCAQYwHQYD\n" +
"VR0OBBYEFL6mfk09fI+gVebBLwkuLCBDs0J/MAwGCCqBHM9VAYN1BQADSAAwRQIh\n" +
"AKuk7s3eYCZDck5NWU0eNQmLhBN/1zmKs517qFrDrkJWAiAP4cVfLtdza/OkwU9P\n" +
"PrIDl+E4aL3FypntFXHG3T+Keg==\n" +
"-----END CERTIFICATE-----";

String userCert = "MIICwDCCAmWgAwIBAgIFICdWkWgwDAYIKoEcz1UBg3UFADBdMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRwwGgYDVQQDDBNDRkNBIFRFU1QgU00yIE9DQTExMB4XDTE5MDUxNjA4MTA1MVoXDTIxMDUxNjA4MTA1MVoweDELMAkGA1UEBhMCQ04xGDAWBgNVBAoMD0NGQ0EgVEVTVCBPQ0ExMTERMA8GA1UECwwITG9jYWwgUkExFTATBgNVBAsMDEluZGl2aWR1YWwtMTElMCMGA1UEAwwcMDUxQHpoYW5nbGluIUBaMTg2MTIyMjkyOTVAMzBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABPvNXpdZ4/4g+wx5qKS94CPkMqpEDhlnXYYW7ZzsbNI4d28sVBz5Ji6dTT1Zx627Kvw4tdUaUt7BVMvZsu3BFlyjgfQwgfEwHwYDVR0jBBgwFoAUvqZ+TT18j6BV5sEvCS4sIEOzQn8wSAYDVR0gBEEwPzA9BghggRyG7yoBAjAxMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmNmY2EuY29tLmNuL3VzL3VzLTE1Lmh0bTA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vMjEwLjc0LjQyLjMvT0NBMTEvU00yL2NybDIxMDkuY3JsMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQUxR5C/VjASus5zrAAFS4ulMpRjKgwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMAwGCCqBHM9VAYN1BQADRwAwRAIgVBzVi/fgkknr+2BH2wXeGMXC+Pa6p7rbldUsYMOYoyUCIAmQ4KEk2U1xJZSBpOPy5jN9kmRb+0YH6x04O/2tqCgq";

parser.parse(userCert, issuerCert);
assertEquals("SM3WITHSM2",parser.getSigAlgName());
}

@Test
public void authenticateIssuerByCATest() {
CertParser parser = new CertParser();
String CACert =
"-----BEGIN CERTIFICATE-----\n" +
"MIICFDCCAbegAwIBAgIKPYozwkCO86Nd9TAMBggqgRzPVQGDdQUAMF0xCzAJBgNV\n" +
"BAYTAkNOMTAwLgYDVQQKDCdDaGluYSBGaW5hbmNpYWwgQ2VydGlmaWNhdGlvbiBB\n" +
"dXRob3JpdHkxHDAaBgNVBAMME0NGQ0EgVEVTVCBDUyBTTTIgQ0EwHhcNMTIwODI5\n" +
"MDMyOTQ2WhcNMzIwODI5MDMyOTQ2WjBdMQswCQYDVQQGEwJDTjEwMC4GA1UECgwn\n" +
"Q2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRwwGgYDVQQD\n" +
"DBNDRkNBIFRFU1QgQ1MgU00yIENBMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE\n" +
"tTjB3O4JueYFDDOtxH678HBZbEmrsgd3BDIdGf0BekyA26n9S0/pKPnjBh/zLouS\n" +
"8+GB5EEnjbn4An24yo1Gv6NdMFswHwYDVR0jBBgwFoAUtdiQb1zw2DPSY71+ssON\n" +
"xk8SemEwDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFLXYkG9c\n" +
"8Ngz0mO9frLDjcZPEnphMAwGCCqBHM9VAYN1BQADSQAwRgIhAKwuuqoBS1bwDowW\n" +
"a4IU//UsvudswJYSlltqrd/PQ9q+AiEAyTUAjFdaGI+8yPdr3A93UiA38wtGPf9e\n" +
"6B6O/6abyWE=\n" +
"-----END CERTIFICATE-----";

String issuerCert = "-----BEGIN CERTIFICATE-----\n" +
"MIICTzCCAfOgAwIBAgIKJFSZ4SRVDndYUTAMBggqgRzPVQGDdQUAMF0xCzAJBgNV\n" +
"BAYTAkNOMTAwLgYDVQQKDCdDaGluYSBGaW5hbmNpYWwgQ2VydGlmaWNhdGlvbiBB\n" +
"dXRob3JpdHkxHDAaBgNVBAMME0NGQ0EgVEVTVCBDUyBTTTIgQ0EwHhcNMTIwODI5\n" +
"MDU0ODQ3WhcNMzIwODI0MDU0ODQ3WjBdMQswCQYDVQQGEwJDTjEwMC4GA1UECgwn\n" +
"Q2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRwwGgYDVQQD\n" +
"DBNDRkNBIFRFU1QgU00yIE9DQTExMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE\n" +
"L1mx4wriQUojGsIkNL14kslv9nwiqsiVpELOZauzghrbccNlPYKNYKZOCvXwIIqU\n" +
"9QY02d4weqKqo/JMcNsKEaOBmDCBlTAfBgNVHSMEGDAWgBS12JBvXPDYM9JjvX6y\n" +
"w43GTxJ6YTAMBgNVHRMEBTADAQH/MDgGA1UdHwQxMC8wLaAroCmGJ2h0dHA6Ly8y\n" +
"MTAuNzQuNDIuMy90ZXN0cmNhL1NNMi9jcmwxLmNybDALBgNVHQ8EBAMCAQYwHQYD\n" +
"VR0OBBYEFL6mfk09fI+gVebBLwkuLCBDs0J/MAwGCCqBHM9VAYN1BQADSAAwRQIh\n" +
"AKuk7s3eYCZDck5NWU0eNQmLhBN/1zmKs517qFrDrkJWAiAP4cVfLtdza/OkwU9P\n" +
"PrIDl+E4aL3FypntFXHG3T+Keg==\n" +
"-----END CERTIFICATE-----";
parser.parse(issuerCert, CACert);
assertEquals("SM3WITHSM2",parser.getSigAlgName());
}
}

+ 1
- 0
source/crypto/pom.xml View File

@@ -16,6 +16,7 @@
<module>crypto-sm</module>
<!-- <module>crypto-jni-clib</module> -->
<module>crypto-adv</module>
<module>crypto-pki</module>
</modules>

</project>

+ 0
- 67
source/deployment/deployment-peer/src/main/resources/config/init/ledger-init.conf View File

@@ -1,67 +0,0 @@
#账本的种子;一段16进制字符,最长可以包含64个字符;可以用字符“-”分隔,以便更容易读取;
#不同的账本,种子不能相同
ledger.seed=932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323ffe

#账本的描述名称;此属性不参与共识,仅仅在当前参与方的本地节点用于描述用途;
#ledger.name=

#参与方的个数,后续以cons_parti.id分别标识每一个参与方的配置;
cons_parti.count=4


#第0个参与方的名称(不同参与方名称不能相同)
cons_parti.0.name=
#第0个参与方的公钥文件路径
cons_parti.0.pubkey-path=
#第0个参与方的公钥内容(由keygen工具生成),此参数优先于 pubkey-path 参数
cons_parti.0.pubkey=
#第0个参与方的账本初始服务的主机
cons_parti.0.initializer.host=127.0.0.1
#第0个参与方的账本初始服务的端口
cons_parti.0.initializer.port=17000
#第0个参与方的账本初始服务是否开启安全连接
cons_parti.0.initializer.secure=false


#第1个参与方的名称
cons_parti.1.name=
#第1个参与方的公钥文件路径
cons_parti.1.pubkey-path=
#第1个参与方的公钥内容(由keygen工具生成),此参数优先于 pubkey-path 参数
cons_parti.1.pubkey=
#第1个参与方的账本初始服务的主机
cons_parti.1.initializer.host=127.0.0.1
#第1个参与方的账本初始服务的端口
cons_parti.1.initializer.port=17010
#第1个参与方的账本初始服务是否开启安全连接
cons_parti.1.initializer.secure=false


#第2个参与方的名称
cons_parti.2.name=
#第2个参与方的公钥文件路径
cons_parti.2.pubkey-path=
#第2个参与方的公钥内容(由keygen工具生成),此参数优先于 pubkey-path 参数
cons_parti.2.pubkey=
#第2个参与方的账本初始服务的主机
cons_parti.2.initializer.host=127.0.0.1
#第2个参与方的账本初始服务的端口
cons_parti.2.initializer.port=17020
#第2个参与方的账本初始服务是否开启安全连接
cons_parti.2.initializer.secure=false


#第3个参与方的名称
cons_parti.3.name=
#第3个参与方的公钥文件路径
cons_parti.3.pubkey-path=
#第3个参与方的公钥内容(由keygen工具生成),此参数优先于 pubkey-path 参数
cons_parti.3.pubkey=
#第3个参与方的账本初始服务的主机
cons_parti.3.initializer.host=127.0.0.1
#第3个参与方的账本初始服务的端口
cons_parti.3.initializer.port=17030
#第3个参与方的账本初始服务是否开启安全连接
cons_parti.3.initializer.secure=false



+ 97
- 0
source/deployment/deployment-peer/src/main/resources/config/init/ledger.init View File

@@ -0,0 +1,97 @@

#账本的种子;一段16进制字符,最长可以包含64个字符;可以用字符“-”分隔,以便更容易读取;
ledger.seed=932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323ffe

#账本的描述名称;此属性不参与共识,仅仅在当前参与方的本地节点用于描述用途;
ledger.name=


#共识服务提供者;必须;
consensus.service-provider=com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider

#共识服务的参数配置;必须;
consensus.conf=classpath:bftsmart.config

#密码服务提供者列表,以英文逗点“,”分隔;必须;
crypto.service-providers=com.jd.blockchain.crypto.service.classic.ClassicCryptoService, \
com.jd.blockchain.crypto.service.sm.SMCryptoService


#参与方的个数,后续以 cons_parti.id 分别标识每一个参与方的配置;
cons_parti.count=4

#第0个参与方的名称;
cons_parti.0.name=jd.com
#第0个参与方的公钥文件路径;
cons_parti.0.pubkey-path=keys/jd-com.pub
#第0个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
cons_parti.0.pubkey=3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9
#第0个参与方的共识服务的主机地址;
cons_parti.0.consensus.host=127.0.0.1
#第0个参与方的共识服务的端口;
cons_parti.0.consensus.port=8900
#第0个参与方的共识服务是否开启安全连接;
cons_parti.0.consensus.secure=true
#第0个参与方的账本初始服务的主机;
cons_parti.0.initializer.host=127.0.0.1
#第0个参与方的账本初始服务的端口;
cons_parti.0.initializer.port=8800
#第0个参与方的账本初始服务是否开启安全连接;
cons_parti.0.initializer.secure=true

#第1个参与方的名称;
cons_parti.1.name=at.com
#第1个参与方的公钥文件路径;
cons_parti.1.pubkey-path=keys/at-com.pub
#第1个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
cons_parti.1.pubkey=3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX
#第1个参与方的共识服务的主机地址;
cons_parti.1.consensus.host=127.0.0.1
#第1个参与方的共识服务的端口;
cons_parti.1.consensus.port=8910
#第1个参与方的共识服务是否开启安全连接;
cons_parti.1.consensus.secure=false
#第1个参与方的账本初始服务的主机;
cons_parti.1.initializer.host=127.0.0.1
#第1个参与方的账本初始服务的端口;
cons_parti.1.initializer.port=8810
#第1个参与方的账本初始服务是否开启安全连接;
cons_parti.1.initializer.secure=false

#第2个参与方的名称;
cons_parti.2.name=bt.com
#第2个参与方的公钥文件路径;
cons_parti.2.pubkey-path=classpath:keys/parti2.pub
#第2个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
cons_parti.2.pubkey=
#第2个参与方的共识服务的主机地址;
cons_parti.2.consensus.host=127.0.0.1
#第2个参与方的共识服务的端口;
cons_parti.2.consensus.port=8920
#第2个参与方的共识服务是否开启安全连接;
cons_parti.2.consensus.secure=false
#第2个参与方的账本初始服务的主机;
cons_parti.2.initializer.host=127.0.0.1
#第2个参与方的账本初始服务的端口;
cons_parti.2.initializer.port=8820
#第2个参与方的账本初始服务是否开启安全连接;
cons_parti.2.initializer.secure=true

#第3个参与方的名称;
cons_parti.3.name=xt.com
#第3个参与方的公钥文件路径;
cons_parti.3.pubkey-path=keys/xt-com.pub
#第3个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
cons_parti.3.pubkey=3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk
#第3个参与方的共识服务的主机地址;
cons_parti.3.consensus.host=127.0.0.1
#第3个参与方的共识服务的端口;
cons_parti.3.consensus.port=8930
#第3个参与方的共识服务是否开启安全连接;
cons_parti.3.consensus.secure=false
#第3个参与方的账本初始服务的主机;
cons_parti.3.initializer.host=127.0.0.1
#第3个参与方的账本初始服务的端口;
cons_parti.3.initializer.port=8830
#第3个参与方的账本初始服务是否开启安全连接;
cons_parti.3.initializer.secure=false

+ 0
- 8
source/deployment/deployment-peer/src/main/resources/config/init/local.conf View File

@@ -22,11 +22,3 @@ ledger.db.uri=
#账本数据库的连接口令
ledger.db.pwd=

#共识配置文件路径
#推荐使用绝对路径,相对路径以当前文件(local.conf)所在目录为基准
consensus.conf=bftsmart.config

#共识Providers配置
#BftSmart共识Provider:com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider
#简单消息共识Provider:com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider
consensus.service-provider=com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider

+ 1
- 19
source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceHandler.java View File

@@ -81,7 +81,7 @@ public class GatewayQueryServiceHandler implements GatewayQueryService {
ledgerInitSettings.setSeed(initSeed(ledgerMetadata.getSeed()));

// 设置共识协议
ledgerInitSettings.setConsensusProtocol(consensusProtocol(ledgerMetadata.getSetting().getConsensusProvider()));
ledgerInitSettings.setConsensusProtocol(ledgerMetadata.getSetting().getConsensusProvider());

return ledgerInitSettings;
}
@@ -110,24 +110,6 @@ public class GatewayQueryServiceHandler implements GatewayQueryService {
return seed.toString();
}

/**
* 生成共识协议
*
* @param consensusProvider
* 共识协议提提供者
* @return
*/
private int consensusProtocol(String consensusProvider) {

if (consensusProvider.equals(BftsmartConsensusProvider.NAME)) {
return LedgerInitSettings.CONSENSUS_PROTOCOL.BFTSMART.code();
} else if (consensusProvider.equals(MsgQueueConsensusProvider.NAME)) {
return LedgerInitSettings.CONSENSUS_PROTOCOL.MSGQUEUE.code();
}

return LedgerInitSettings.CONSENSUS_PROTOCOL.UNKNOWN.code();
}

/**
* 初始化共识配置
*


+ 7
- 0
source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java View File

@@ -239,6 +239,13 @@ public class BlockBrowserController implements BlockchainExtendQueryService {
return peerService.getQueryService().getDataEntries(ledgerHash, address, keys);
}

@RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, path = "ledgers/{ledgerHash}/accounts/{address}/entries-version")
public KVDataEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash,
@PathVariable("address") String address,
@RequestBody KVInfoVO kvInfoVO) {
return peerService.getQueryService().getDataEntries(ledgerHash, address, kvInfoVO);
}

@RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries")
@Override
public KVDataEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash,


+ 53
- 2
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/CryptoConfig.java View File

@@ -1,22 +1,37 @@
package com.jd.blockchain.ledger.core;

import java.util.HashMap;

import com.jd.blockchain.crypto.CryptoAlgorithm;
import com.jd.blockchain.crypto.CryptoProvider;
import com.jd.blockchain.ledger.CryptoSetting;

public class CryptoConfig implements CryptoSetting {

private CryptoProvider[] cryptoProviders;

private short hashAlgorithm;

private boolean autoVerifyHash;

HashMap<String, CryptoProvider> providers;
HashMap<String, CryptoAlgorithm> nameAlgorithms;
HashMap<Short, CryptoAlgorithm> codeAlgorithms;

public CryptoConfig() {
}

public CryptoConfig(CryptoSetting setting) {
this.hashAlgorithm = setting.getHashAlgorithm();
setSupportedProviders(setting.getSupportedProviders());
setHashAlgorithm(setting.getHashAlgorithm());
this.autoVerifyHash = setting.getAutoVerifyHash();
}

@Override
public CryptoProvider[] getSupportedProviders() {
return cryptoProviders == null ? null : cryptoProviders.clone();
}

@Override
public short getHashAlgorithm() {
return hashAlgorithm;
@@ -27,11 +42,47 @@ public class CryptoConfig implements CryptoSetting {
return autoVerifyHash;
}

public void setSupportedProviders(CryptoProvider[] supportedProviders) {
HashMap<String, CryptoProvider> providers = new HashMap<String, CryptoProvider>();
HashMap<String, CryptoAlgorithm> nameAlgorithms = new HashMap<String, CryptoAlgorithm>();
HashMap<Short, CryptoAlgorithm> codeAlgorithms = new HashMap<Short, CryptoAlgorithm>();
if (supportedProviders != null) {
// 检查是否存在重复的提供者以及算法;
for (CryptoProvider cryptoProvider : supportedProviders) {
if (providers.containsKey(cryptoProvider.getName())) {
throw new LedgerException("Duplicate crypto providers [" + cryptoProvider.getName() + "]!");
}
CryptoAlgorithm[] algorithms = cryptoProvider.getAlgorithms();
for (CryptoAlgorithm alg : algorithms) {
if (nameAlgorithms.containsKey(alg.name())) {
throw new LedgerException("Duplicate crypto algorithms [" + alg.toString() + "] from provider "
+ cryptoProvider.getName() + "!");
}
if (codeAlgorithms.containsKey(alg.code())) {
throw new LedgerException("Duplicate crypto algorithms [" + alg.toString() + "] from provider"
+ cryptoProvider.getName() + "!");
}
nameAlgorithms.put(alg.name(), alg);
codeAlgorithms.put(alg.code(), alg);
}
providers.put(cryptoProvider.getName(), cryptoProvider);
}
}
this.providers = providers;
this.nameAlgorithms = nameAlgorithms;
this.codeAlgorithms = codeAlgorithms;

this.cryptoProviders = supportedProviders;
}

public void setHashAlgorithm(CryptoAlgorithm hashAlgorithm) {
this.hashAlgorithm = hashAlgorithm.code();
setHashAlgorithm(hashAlgorithm.code());
}

public void setHashAlgorithm(short hashAlgorithm) {
if (codeAlgorithms == null || !codeAlgorithms.containsKey(hashAlgorithm)) {
throw new LedgerException("The specified algorithm[" + hashAlgorithm + "] has no provider!");
}
this.hashAlgorithm = hashAlgorithm;
}



+ 3
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java View File

@@ -157,6 +157,9 @@ public class DataAccount implements AccountHeader, MerkleProvable {
* @return return total count;
*/
public long getDataEntriesTotalCount() {
if(baseAccount == null){
return 0;
}
return baseAccount.dataset.getDataCount();
}

+ 77
- 21
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerManager.java View File

@@ -3,10 +3,15 @@ package com.jd.blockchain.ledger.core.impl;
import java.util.HashMap;
import java.util.Map;

import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.CryptoAlgorithm;
import com.jd.blockchain.crypto.CryptoProvider;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerInitSetting;
import com.jd.blockchain.ledger.core.LedgerConsts;
import com.jd.blockchain.ledger.core.LedgerEditor;
import com.jd.blockchain.ledger.core.LedgerException;
import com.jd.blockchain.ledger.core.LedgerManage;
import com.jd.blockchain.ledger.core.LedgerRepository;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
@@ -57,26 +62,83 @@ public class LedgerManager implements LedgerManage {

@Override
public LedgerRepository register(HashDigest ledgerHash, KVStorageService storageService) {
// 加载账本数据库;
VersioningKVStorage ledgerVersioningStorage = storageService.getVersioningKVStorage();
ExPolicyKVStorage ledgerExPolicyStorage = storageService.getExPolicyKVStorage();
LedgerRepository ledgerRepo = new LedgerRepositoryImpl(ledgerHash, LEDGER_PREFIX, ledgerExPolicyStorage,
ledgerVersioningStorage);

LedgerRepositoryContext ledgerCtx = new LedgerRepositoryContext();
ledgerCtx.ledgerRepo = ledgerRepo;
ledgerCtx.storageService = storageService;
// 校验 crypto service provider ;
CryptoSetting cryptoSetting = ledgerRepo.getAdminAccount().getSetting().getCryptoSetting();
checkCryptoSetting(cryptoSetting, ledgerHash);

// 创建账本上下文;
LedgerRepositoryContext ledgerCtx = new LedgerRepositoryContext(ledgerRepo, storageService);
ledgers.put(ledgerHash, ledgerCtx);
return ledgerRepo;
}

/**
* 检查账本的密码参数设置与本地节点的运行时环境是否匹配;
*
* @param cryptoSetting
* @param ledgerHash
*/
private void checkCryptoSetting(CryptoSetting cryptoSetting, HashDigest ledgerHash) {
CryptoProvider[] cryptoProviders = cryptoSetting.getSupportedProviders();
if (cryptoProviders == null || cryptoProviders.length == 0) {
throw new LedgerException("No supported crypto service providers has been setted in the ledger["
+ ledgerHash.toBase58() + "]!");
}
for (CryptoProvider cp : cryptoProviders) {
CryptoProvider regCp = Crypto.getProvider(cp.getName());
checkCryptoProviderConsistency(regCp, cp);
}
}

/**
* 检查密码服务提供者的信息是否匹配;
*
* @param registeredProvider
* @param settingProvider
*/
private void checkCryptoProviderConsistency(CryptoProvider registeredProvider, CryptoProvider settingProvider) {
if (registeredProvider == null) {
throw new LedgerException("Crypto service provider[" + settingProvider.getName()
+ "] has not registered in the runtime environment of current peer!");
}

CryptoAlgorithm[] runtimeAlgothms = registeredProvider.getAlgorithms();
CryptoAlgorithm[] settingAlgothms = settingProvider.getAlgorithms();
if (runtimeAlgothms.length != settingAlgothms.length) {
throw new LedgerException("Crypto service provider[" + settingProvider.getName()
+ "] has not registered in runtime of current peer!");
}
HashMap<Short, CryptoAlgorithm> runtimeAlgothmMap = new HashMap<Short, CryptoAlgorithm>();
for (CryptoAlgorithm alg : runtimeAlgothms) {
runtimeAlgothmMap.put(alg.code(), alg);
}
for (CryptoAlgorithm alg : settingAlgothms) {
CryptoAlgorithm regAlg = runtimeAlgothmMap.get(alg.code());
if (regAlg == null) {
throw new LedgerException(
String.format("Crypto algorithm[%s] is not defined by provider[%s] in runtime of current peer!",
alg.toString(), registeredProvider.getName()));
}
if (!regAlg.name().equals(alg.name())) {
throw new LedgerException(String.format(
"Crypto algorithm[%s] do not match the same code algorithm[%s] defined by provider[%s] in runtime of current peer!",
CryptoAlgorithm.getString(alg), CryptoAlgorithm.getString(regAlg),
registeredProvider.getName()));
}
}
}

@Override
public void unregister(HashDigest ledgerHash) {
LedgerRepositoryContext ledgerCtx = ledgers.get(ledgerHash);
LedgerRepositoryContext ledgerCtx = ledgers.remove(ledgerHash);
if (ledgerCtx != null) {
ledgerCtx.ledgerRepo.close();
ledgers.remove(ledgerHash);
ledgerCtx.ledgerRepo = null;
ledgerCtx.storageService = null;
}
}

@@ -88,18 +150,6 @@ public class LedgerManager implements LedgerManage {
*/
@Override
public LedgerEditor newLedger(LedgerInitSetting initSetting, KVStorageService storageService) {
// GenesisLedgerStorageProxy genesisStorageProxy = new
// GenesisLedgerStorageProxy();
// BufferedKVStorage bufferedStorage = new
// BufferedKVStorage(genesisStorageProxy, genesisStorageProxy, false);

// LedgerEditor genesisBlockEditor =
// LedgerTransactionalEditor.createEditor(initSetting,
// bufferedStorage, bufferedStorage);

// return new LedgerInitializer(genesisBlockEditor, bufferedStorage,
// genesisStorageProxy, storageService, this);

LedgerEditor genesisBlockEditor = LedgerTransactionalEditor.createEditor(initSetting, LEDGER_PREFIX,
storageService.getExPolicyKVStorage(), storageService.getVersioningKVStorage());
return genesisBlockEditor;
@@ -110,10 +160,16 @@ public class LedgerManager implements LedgerManage {
return LEDGER_PREFIX + base58LedgerHash + LedgerConsts.KEY_SEPERATOR;
}

private static class LedgerRepositoryContext {

private LedgerRepository ledgerRepo;
public final LedgerRepository ledgerRepo;

private KVStorageService storageService;
public final KVStorageService storageService;

public LedgerRepositoryContext(LedgerRepository ledgerRepo, KVStorageService storageService) {
this.ledgerRepo = ledgerRepo;
this.storageService = storageService;
}
}
}

+ 62
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java View File

@@ -2,6 +2,7 @@ package com.jd.blockchain.ledger.core.impl;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.contract.ContractException;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.*;
import com.jd.blockchain.ledger.core.ContractAccountSet;
@@ -15,6 +16,10 @@ import com.jd.blockchain.ledger.core.UserAccountSet;
import com.jd.blockchain.transaction.BlockchainQueryService;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.QueryUtil;
import com.jd.blockchain.utils.StringUtils;
import java.util.ArrayList;
import java.util.List;
public class LedgerQueryService implements BlockchainQueryService {
@@ -263,6 +268,9 @@ public class LedgerQueryService implements BlockchainQueryService {
long ver;
for (int i = 0; i < entries.length; i++) {
ver = dataAccount.getDataVersion(Bytes.fromString(keys[i]));
dataAccount.getBytes(Bytes.fromString(keys[i]),1);
if (ver < 0) {
entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null);
}else {
@@ -275,6 +283,60 @@ public class LedgerQueryService implements BlockchainQueryService {
return entries;
}
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) {
//parse kvInfoVO;
List<String> keyList = new ArrayList<>();
List<Long> versionList = new ArrayList<>();
if(kvInfoVO != null){
for(KVDataVO kvDataVO : kvInfoVO.getData()){
for(Long version : kvDataVO.getVersion()){
keyList.add(kvDataVO.getKey());
versionList.add(version);
}
}
}
String[] keys = keyList.toArray(new String[keyList.size()]);
Long[] versions = versionList.toArray(new Long[versionList.size()]);
if (keys == null || keys.length == 0) {
return null;
}
if (versions == null || versions.length == 0) {
return null;
}
if(keys.length != versions.length){
throw new ContractException("keys.length!=versions.length!");
}
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address));
KVDataEntry[] entries = new KVDataEntry[keys.length];
long ver = -1;
for (int i = 0; i < entries.length; i++) {
// ver = dataAccount.getDataVersion(Bytes.fromString(keys[i]));
// dataAccount.getBytes(Bytes.fromString(keys[i]),1);
ver = versions[i];
if (ver < 0) {
entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null);
}else {
if(dataAccount.getDataEntriesTotalCount()==0 ||
dataAccount.getBytes(Bytes.fromString(keys[i]), ver) == null){
//is the address is not exist; the result is null;
entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null);
} else {
byte[] value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver);
BytesValue decodeData = BinaryProtocol.decode(value);
entries[i] = new KVDataObject(keys[i], ver, PrimitiveType.valueOf(decodeData.getType().CODE), decodeData.getValue().toBytes());
}
}
}
return entries;
}
@Override
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) {


+ 5
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java View File

@@ -156,6 +156,11 @@ public class ContractLedgerContext implements LedgerContext {
return innerQueryService.getDataEntries(ledgerHash, address, keys);
}

@Override
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) {
return innerQueryService.getDataEntries(ledgerHash, address, kvInfoVO);
}

@Override
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) {
return innerQueryService.getDataEntries(ledgerHash, address, fromIndex, count);


+ 14
- 0
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/AccountSetTest.java View File

@@ -6,8 +6,12 @@ import static org.junit.Assert.assertTrue;

import org.junit.Test;

import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.CryptoProvider;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
import com.jd.blockchain.crypto.service.sm.SMCryptoService;
import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.ledger.core.AccountSet;
@@ -17,6 +21,11 @@ import com.jd.blockchain.ledger.core.impl.OpeningAccessPolicy;
import com.jd.blockchain.storage.service.utils.MemoryKVStorage;

public class AccountSetTest {

private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(),
SMCryptoService.class.getName() };


@Test
public void test() {
@@ -24,7 +33,12 @@ public class AccountSetTest {

MemoryKVStorage storage = new MemoryKVStorage();

CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length];
for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) {
supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]);
}
CryptoConfig cryptoConf = new CryptoConfig();
cryptoConf.setSupportedProviders(supportedProviders);
cryptoConf.setAutoVerifyHash(true);
cryptoConf.setHashAlgorithm(ClassicAlgorithm.SHA256);



+ 13
- 0
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/BaseAccountTest.java View File

@@ -5,7 +5,11 @@ import static org.junit.Assert.assertFalse;

import org.junit.Test;

import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.CryptoProvider;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
import com.jd.blockchain.crypto.service.sm.SMCryptoService;
import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.ledger.core.BaseAccount;
@@ -22,12 +26,21 @@ import com.jd.blockchain.utils.io.BytesUtils;
*/
public class BaseAccountTest {

public static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(),
SMCryptoService.class.getName() };

@Test
public void basicTest() {
String keyPrefix = "";
MemoryKVStorage testStorage = new MemoryKVStorage();

CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length];
for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) {
supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]);
}

CryptoConfig cryptoConf = new CryptoConfig();
cryptoConf.setSupportedProviders(supportedProviders);
cryptoConf.setAutoVerifyHash(true);
cryptoConf.setHashAlgorithm(ClassicAlgorithm.SHA256);



+ 13
- 0
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerAdminAccountTest.java View File

@@ -13,8 +13,12 @@ import com.jd.blockchain.ledger.LedgerMetadata;
import org.junit.Test;

import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.CryptoProvider;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
import com.jd.blockchain.crypto.service.sm.SMCryptoService;
import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.ledger.ParticipantNode;
@@ -30,6 +34,9 @@ import com.jd.blockchain.utils.net.NetworkAddress;

public class LedgerAdminAccountTest {

private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(),
SMCryptoService.class.getName() };

private Random rand = new Random();

@Test
@@ -55,7 +62,13 @@ public class LedgerAdminAccountTest {
initSetting.setConsensusSettings(new Bytes(csSysSettingBytes));
initSetting.setConsensusProvider("consensus-provider");

CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length];
for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) {
supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]);
}

CryptoConfig cryptoSetting = new CryptoConfig();
cryptoSetting.setSupportedProviders(supportedProviders);
cryptoSetting.setAutoVerifyHash(true);
cryptoSetting.setHashAlgorithm(ClassicAlgorithm.SHA256);
initSetting.setCryptoSetting(cryptoSetting);


+ 13
- 0
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerEditerTest.java View File

@@ -11,8 +11,11 @@ import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.crypto.AsymmetricKeypair;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.CryptoProvider;
import com.jd.blockchain.crypto.SignatureFunction;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
import com.jd.blockchain.crypto.service.sm.SMCryptoService;
import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerInitSetting;
@@ -34,6 +37,10 @@ import com.jd.blockchain.utils.io.BytesUtils;
import com.jd.blockchain.utils.net.NetworkAddress;

public class LedgerEditerTest {
private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(),
SMCryptoService.class.getName() };


static {
DataContractRegistry.register(com.jd.blockchain.ledger.TransactionContent.class);
@@ -109,8 +116,14 @@ public class LedgerEditerTest {

private LedgerInitSetting createLedgerInitSetting() {
SignatureFunction signFunc = Crypto.getSignatureFunction("ED25519");
CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length];
for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) {
supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]);
}

CryptoConfig defCryptoSetting = new CryptoConfig();
defCryptoSetting.setSupportedProviders(supportedProviders);
defCryptoSetting.setAutoVerifyHash(true);
defCryptoSetting.setHashAlgorithm(ClassicAlgorithm.SHA256);



+ 12
- 0
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitOperationTest.java View File

@@ -12,7 +12,11 @@ import org.junit.Test;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.CryptoProvider;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
import com.jd.blockchain.crypto.service.sm.SMCryptoService;
import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.ledger.LedgerInitOperation;
@@ -27,6 +31,9 @@ import com.jd.blockchain.utils.net.NetworkAddress;

public class LedgerInitOperationTest {

private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(),
SMCryptoService.class.getName() };

byte[] seed = null;
byte[] csSysSettingBytes = null;
LedgerInitSettingData ledgerInitSettingData = new LedgerInitSettingData();
@@ -44,7 +51,12 @@ public class LedgerInitOperationTest {
csSysSettingBytes = new byte[64];
rand.nextBytes(csSysSettingBytes);

CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length];
for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) {
supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]);
}
CryptoConfig cryptoConfig = new CryptoConfig();
cryptoConfig.setSupportedProviders(supportedProviders);
cryptoConfig.setAutoVerifyHash(true);
cryptoConfig.setHashAlgorithm(ClassicAlgorithm.SHA256);



source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitSettingTest.java → source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitSettingSerializeTest.java View File

@@ -12,7 +12,11 @@ import org.junit.Test;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.CryptoProvider;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
import com.jd.blockchain.crypto.service.sm.SMCryptoService;
import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.ledger.LedgerInitSetting;
@@ -24,12 +28,15 @@ import com.jd.blockchain.transaction.LedgerInitSettingData;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.net.NetworkAddress;

public class LedgerInitSettingTest {
public class LedgerInitSettingSerializeTest {
byte[] seed = null;
byte[] csSysSettingBytes = null;
LedgerInitSettingData ledgerInitSettingData = new LedgerInitSettingData();
LedgerInitOpTemplate template = new LedgerInitOpTemplate();

private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(),
SMCryptoService.class.getName() };

@Before
public void initCfg() {

@@ -41,7 +48,13 @@ public class LedgerInitSettingTest {
csSysSettingBytes = new byte[64];
rand.nextBytes(csSysSettingBytes);

CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length];
for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) {
supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]);
}

CryptoConfig cryptoConfig = new CryptoConfig();
cryptoConfig.setSupportedProviders(supportedProviders);
cryptoConfig.setAutoVerifyHash(true);
cryptoConfig.setHashAlgorithm(ClassicAlgorithm.SHA256);

@@ -71,7 +84,7 @@ public class LedgerInitSettingTest {
ConsensusParticipantData[] parties1 = Arrays.copyOf(parties, 4);

ledgerInitSettingData.setConsensusParticipants(parties1);
byte[] encode = BinaryProtocol.encode(ledgerInitSettingData, LedgerInitSetting.class);

LedgerInitSetting decode = BinaryProtocol.decode(encode);

+ 16
- 0
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java View File

@@ -13,9 +13,12 @@ import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.crypto.AsymmetricKeypair;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.CryptoProvider;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.SignatureFunction;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
import com.jd.blockchain.crypto.service.sm.SMCryptoService;
import com.jd.blockchain.ledger.BlockBody;
import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
@@ -54,8 +57,12 @@ public class LedgerManagerTest {
DataContractRegistry.register(UserRegisterOperation.class);
DataContractRegistry.register(DataAccountRegisterOperation.class);
DataContractRegistry.register(BlockBody.class);
DataContractRegistry.register(CryptoProvider.class);
}

public static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(),
SMCryptoService.class.getName() };

private SignatureFunction signatureFunction;

@Before
@@ -170,7 +177,16 @@ public class LedgerManagerTest {
}

private LedgerInitSetting createLedgerInitSetting() {

CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length];
for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) {
supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]);
}

CryptoConfig defCryptoSetting = new CryptoConfig();

defCryptoSetting.setSupportedProviders(supportedProviders);

defCryptoSetting.setAutoVerifyHash(true);
defCryptoSetting.setHashAlgorithm(ClassicAlgorithm.SHA256);



+ 27
- 0
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerMetaDataTest.java View File

@@ -15,9 +15,13 @@ import org.junit.Test;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.CryptoProvider;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
import com.jd.blockchain.crypto.service.sm.SMCryptoService;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.ledger.core.CryptoConfig;
@@ -30,6 +34,10 @@ import com.jd.blockchain.utils.Bytes;
* Created by zhangshuang3 on 2018/8/31.
*/
public class LedgerMetaDataTest {

private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(),
SMCryptoService.class.getName() };

byte[] seed = null;
String consensusProvider = "test-provider";
byte[] consensusSettingBytes = null;
@@ -56,7 +64,13 @@ public class LedgerMetaDataTest {
// ConsensusConfig consensusConfig = new ConsensusConfig();
// consensusConfig.setValue(settingValue);ClassicCryptoService.ED25519_ALGORITHM

CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length];
for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) {
supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]);
}

CryptoConfig cryptoConfig = new CryptoConfig();
cryptoConfig.setSupportedProviders(supportedProviders);
cryptoConfig.setAutoVerifyHash(true);
cryptoConfig.setHashAlgorithm(ClassicAlgorithm.SHA256);

@@ -93,7 +107,13 @@ public class LedgerMetaDataTest {
// ConsensusConfig consensusConfig = new ConsensusConfig();
// consensusConfig.setValue(settingValue);

CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length];
for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) {
supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]);
}

CryptoConfig cryptoConfig = new CryptoConfig();
cryptoConfig.setSupportedProviders(supportedProviders);
cryptoConfig.setAutoVerifyHash(true);
cryptoConfig.setHashAlgorithm(ClassicAlgorithm.SHA256);

@@ -133,7 +153,14 @@ public class LedgerMetaDataTest {
@Test
public void testSerialize_CryptoSetting() {
// LedgerCodes.METADATA_LEDGER_SETTING_CRYPTO

CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length];
for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) {
supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]);
}

CryptoConfig cryptoConfig = new CryptoConfig();
cryptoConfig.setSupportedProviders(supportedProviders);
cryptoConfig.setAutoVerifyHash(true);
cryptoConfig.setHashAlgorithm(ClassicAlgorithm.SHA256);
byte[] encodeBytes = BinaryProtocol.encode(cryptoConfig, CryptoSetting.class);


+ 13
- 0
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTestUtils.java View File

@@ -4,10 +4,13 @@ import java.util.Random;

import com.jd.blockchain.crypto.AsymmetricKeypair;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.CryptoProvider;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.crypto.SignatureFunction;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
import com.jd.blockchain.crypto.service.sm.SMCryptoService;
import com.jd.blockchain.ledger.BlockchainIdentityData;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.PreparedTransaction;
@@ -22,6 +25,9 @@ public class LedgerTestUtils {

// private static ThreadLocalRandom rand = ThreadLocalRandom.current();

private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(),
SMCryptoService.class.getName() };

private static Random rand = new Random();

public static TransactionRequest createTxRequest(HashDigest ledgerHash) {
@@ -76,7 +82,14 @@ public class LedgerTestUtils {
}

public static CryptoSetting createDefaultCryptoSetting() {

CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length];
for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) {
supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]);
}

CryptoConfig cryptoSetting = new CryptoConfig();
cryptoSetting.setSupportedProviders(supportedProviders);
cryptoSetting.setAutoVerifyHash(true);
cryptoSetting.setHashAlgorithm(ClassicAlgorithm.SHA256);
return cryptoSetting;


+ 26
- 0
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/MerkleDataSetTest.java View File

@@ -14,8 +14,12 @@ import java.util.Set;

import org.junit.Test;

import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.CryptoProvider;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
import com.jd.blockchain.crypto.service.sm.SMCryptoService;
import com.jd.blockchain.ledger.core.CryptoConfig;
import com.jd.blockchain.ledger.core.MerkleDataSet;
import com.jd.blockchain.ledger.core.MerkleProof;
@@ -26,13 +30,23 @@ import com.jd.blockchain.utils.io.BytesUtils;

public class MerkleDataSetTest {

private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(),
SMCryptoService.class.getName() };

/**
* 测试存储的增长;
*/
@Test
public void testStorageIncreasement() {

CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length];
for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) {
supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]);
}

String keyPrefix = "";
CryptoConfig cryptoConfig = new CryptoConfig();
cryptoConfig.setSupportedProviders(supportedProviders);
cryptoConfig.setHashAlgorithm(ClassicAlgorithm.SHA256);
cryptoConfig.setAutoVerifyHash(true);

@@ -116,7 +130,13 @@ public class MerkleDataSetTest {
String keyPrefix = "";
Random rand = new Random();

CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length];
for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) {
supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]);
}

CryptoConfig cryptoConfig = new CryptoConfig();
cryptoConfig.setSupportedProviders(supportedProviders);
cryptoConfig.setHashAlgorithm(ClassicAlgorithm.SHA256);
cryptoConfig.setAutoVerifyHash(true);

@@ -281,7 +301,13 @@ public class MerkleDataSetTest {
String keyPrefix = "";
Random rand = new Random();

CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length];
for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) {
supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]);
}

CryptoConfig cryptoConfig = new CryptoConfig();
cryptoConfig.setSupportedProviders(supportedProviders);
cryptoConfig.setHashAlgorithm(ClassicAlgorithm.SHA256);
cryptoConfig.setAutoVerifyHash(true);



+ 48
- 26
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractEventSendOperation.java View File

@@ -1,26 +1,48 @@
package com.jd.blockchain.ledger;
import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consts.DataCodes;
import com.jd.blockchain.utils.Bytes;
/**
* @author huanghaiquan
*
*/
@DataContract(code= DataCodes.TX_OP_CONTRACT_EVENT_SEND)
public interface ContractEventSendOperation extends Operation {
@DataField(order=2, primitiveType=PrimitiveType.BYTES)
Bytes getContractAddress();
@DataField(order=3, primitiveType=PrimitiveType.TEXT)
String getEvent();
@DataField(order=4, primitiveType=PrimitiveType.BYTES)
byte[] getArgs();
}
package com.jd.blockchain.ledger;

import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consts.DataCodes;
import com.jd.blockchain.utils.Bytes;

/**
* @author huanghaiquan
*
*/
@DataContract(code = DataCodes.TX_OP_CONTRACT_EVENT_SEND)
public interface ContractEventSendOperation extends Operation {

/**
* 响应事件的合约地址;
*
* @return
*/
@DataField(order = 2, primitiveType = PrimitiveType.BYTES)
Bytes getContractAddress();

/**
* 事件名;
*
* @return
*/
@DataField(order = 3, primitiveType = PrimitiveType.TEXT)
String getEvent();

/**
* 事件参数;
*
* @return
*/
@DataField(order = 4, primitiveType = PrimitiveType.BYTES)
byte[] getArgs();

/**
* 时间戳;
*
* @return
*/
@DataField(order = 5, primitiveType = PrimitiveType.INT64)
long getTs();

}

+ 0
- 12
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/CryptoProviderInfo.java View File

@@ -1,12 +0,0 @@
package com.jd.blockchain.ledger;

import com.jd.blockchain.crypto.CryptoAlgorithm;

public interface CryptoProviderInfo {
String getName();
CryptoAlgorithm[] getAlgorithms();
}

+ 13
- 1
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/CryptoSetting.java View File

@@ -4,6 +4,7 @@ import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consts.DataCodes;
import com.jd.blockchain.crypto.CryptoProvider;

/**
* 默克尔树算法相关的配置;
@@ -14,6 +15,16 @@ import com.jd.blockchain.consts.DataCodes;
@DataContract(code = DataCodes.METADATA_CRYPTO_SETTING)
public interface CryptoSetting {

/**
* 系统支持的密码服务提供者;
*
* @return
*/
@DataField(order = 0, refContract = true, list = true)
public CryptoProvider[] getSupportedProviders();

/**
* 系统中使用的 Hash 算法; <br>
*
@@ -27,7 +38,7 @@ public interface CryptoSetting {
public short getHashAlgorithm();

/**
* 当有完整性证明的数据被从持久化介质中加载时,是否对其进行完整性校验(重新计算 hash 比对是否一致); <br>
* 当有加载附带哈希摘要的数据时,是否重新计算哈希摘要进行完整性校验; <br>
*
* 如果为 true ,则自动进行校验,如果校验失败,会引发异常; <br>
*
@@ -37,5 +48,6 @@ public interface CryptoSetting {
*/
@DataField(order = 2, primitiveType = PrimitiveType.BOOLEAN)
public boolean getAutoVerifyHash();

}

+ 26
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataVO.java View File

@@ -0,0 +1,26 @@
package com.jd.blockchain.ledger;

/**
* @author zhaogw
* date 2019/5/14 14:17
*/
public class KVDataVO {
private String key;
private long[] version;

public String getKey() {
return key;
}

public void setKey(String key) {
this.key = key;
}

public long[] getVersion() {
return version;
}

public void setVersion(long[] version) {
this.version = version;
}
}

+ 18
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVInfoVO.java View File

@@ -0,0 +1,18 @@
package com.jd.blockchain.ledger;

/**
* for BlockBrowserController.java, param is json ,then match it;
* @author zhaogw
* date 2019/5/14 14:19
*/
public class KVInfoVO {
private KVDataVO[] data;

public KVDataVO[] getData() {
return data;
}

public void setData(KVDataVO[] data) {
this.data = data;
}
}

+ 1
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantNode.java View File

@@ -22,6 +22,7 @@ public interface ParticipantNode {// extends ConsensusNode, ParticipantInfo {
*
* @return
*/
@DataField(order = 0, primitiveType = PrimitiveType.INT32)
int getId();

/**


+ 21
- 21
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContent.java View File

@@ -1,21 +1,21 @@
package com.jd.blockchain.ledger;
import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consts.DataCodes;
import com.jd.blockchain.crypto.HashDigest;
/**
* 交易内容;
*
* @author huanghaiquan
*
*/
@DataContract(code= DataCodes.TX_CONTENT)
public interface TransactionContent extends TransactionContentBody, HashObject {
@Override
@DataField(order=1, primitiveType = PrimitiveType.BYTES)
HashDigest getHash();
}
package com.jd.blockchain.ledger;
import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consts.DataCodes;
import com.jd.blockchain.crypto.HashDigest;
/**
* 交易内容;
*
* @author huanghaiquan
*
*/
@DataContract(code= DataCodes.TX_CONTENT)
public interface TransactionContent extends TransactionContentBody, HashObject {
@Override
@DataField(order=1, primitiveType = PrimitiveType.BYTES)
HashDigest getHash();
}

+ 36
- 36
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContentBody.java View File

@@ -1,36 +1,36 @@
package com.jd.blockchain.ledger;
import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consts.DataCodes;
import com.jd.blockchain.crypto.HashDigest;
/**
* 交易内容;
*
* @author huanghaiquan
*
*/
@DataContract(code = DataCodes.TX_CONTENT_BODY)
public interface TransactionContentBody {
/**
* 执行交易的账本地址;
*
* 注:除了账本的创世交易之外,任何交易的账本地址都不允许为 null;
*
* @return
*/
@DataField(order = 1, primitiveType = PrimitiveType.BYTES)
HashDigest getLedgerHash();
/**
* 操作列表;
*
* @return
*/
@DataField(order = 2, list = true, refContract = true, genericContract = true)
Operation[] getOperations();
}
package com.jd.blockchain.ledger;
import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consts.DataCodes;
import com.jd.blockchain.crypto.HashDigest;
/**
* 交易内容;
*
* @author huanghaiquan
*
*/
@DataContract(code = DataCodes.TX_CONTENT_BODY)
public interface TransactionContentBody {
/**
* 执行交易的账本地址;
*
* 注:除了账本的创世交易之外,任何交易的账本地址都不允许为 null;
*
* @return
*/
@DataField(order = 1, primitiveType = PrimitiveType.BYTES)
HashDigest getLedgerHash();
/**
* 操作列表;
*
* @return
*/
@DataField(order = 2, list = true, refContract = true, genericContract = true)
Operation[] getOperations();
}

+ 5
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionState.java View File

@@ -29,6 +29,11 @@ public enum TransactionState {
*/
LEDGER_ERROR((byte) 2),
/**
* 数据序列更新错误;
*/
DATA_SEQUENCE_UPDATE_ERROR((byte) 3),
/**
* 系统错误;
*/


+ 2
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java View File

@@ -261,6 +261,8 @@ public interface BlockchainQueryService {
*/
KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys);
KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO);
/**
* 返回指定数据账户中KV数据的总数; <br>
*


+ 50
- 40
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractEventSendOpTemplate.java View File

@@ -1,40 +1,50 @@
package com.jd.blockchain.transaction;
import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.ledger.ContractEventSendOperation;
import com.jd.blockchain.utils.Bytes;
public class ContractEventSendOpTemplate implements ContractEventSendOperation {
static {
DataContractRegistry.register(ContractEventSendOperation.class);
}
private Bytes contractAddress;
private byte[] args;
private String event;
public ContractEventSendOpTemplate() {
}
public ContractEventSendOpTemplate(Bytes contractAddress, String event, byte[] args) {
this.contractAddress = contractAddress;
this.event = event;
this.args = args;
}
@Override
public Bytes getContractAddress() {
return contractAddress;
}
@Override
public String getEvent() {
return event;
}
@Override
public byte[] getArgs() {
return args;
}
}
package com.jd.blockchain.transaction;

import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.ledger.ContractEventSendOperation;
import com.jd.blockchain.utils.Bytes;

public class ContractEventSendOpTemplate implements ContractEventSendOperation {
static {
DataContractRegistry.register(ContractEventSendOperation.class);
}

private Bytes contractAddress;
private byte[] args;
private String event;
private long ts;

public ContractEventSendOpTemplate() {
}

public ContractEventSendOpTemplate(Bytes contractAddress, String event, byte[] args) {
this.contractAddress = contractAddress;
this.event = event;
this.args = args;
}

@Override
public Bytes getContractAddress() {
return contractAddress;
}

@Override
public String getEvent() {
return event;
}

@Override
public byte[] getArgs() {
return args;
}

@Override
public long getTs() {
return ts;
}

public void setTs(long ts) {
this.ts = ts;
}
}

+ 4
- 3
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractEventSendOperationBuilderImpl.java View File

@@ -4,18 +4,19 @@ import com.jd.blockchain.ledger.ContractEventSendOperation;
import com.jd.blockchain.utils.Bytes;
@Deprecated
class ContractEventSendOperationBuilderImpl implements ContractEventSendOperationBuilder{
class ContractEventSendOperationBuilderImpl implements ContractEventSendOperationBuilder {
@Override
public ContractEventSendOperation send(String address, String event, byte[] args) {
ContractEventSendOpTemplate op = new ContractEventSendOpTemplate(Bytes.fromBase58(address), event, args);
op.setTs(System.currentTimeMillis());
return op;
}
@Override
public ContractEventSendOperation send(Bytes address, String event, byte[] args) {
ContractEventSendOpTemplate op = new ContractEventSendOpTemplate(address, event, args);
op.setTs(System.currentTimeMillis());
return op;
}


+ 2
- 2
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOpTemplate.java View File

@@ -49,7 +49,7 @@ public class DataAccountKVSetOpTemplate implements DataAccountKVSetOperation {
public void set(String key, BytesValue value, long expVersion) {
if (kvset.containsKey(key)) {
throw new IllegalArgumentException("Cann't set the same key repeatly!");
throw new IllegalArgumentException("Cann't set the same key repeatedly!");
}
KVData kvdata = new KVData(key, value, expVersion);
kvset.put(key, kvdata);
@@ -57,7 +57,7 @@ public class DataAccountKVSetOpTemplate implements DataAccountKVSetOperation {
public void set(KVData kvData) {
if (kvset.containsKey(kvData.getKey())) {
throw new IllegalArgumentException("Cann't set the same key repeatly!");
throw new IllegalArgumentException("Cann't set the same key repeatedly!");
}
kvset.put(kvData.getKey(), kvData);
}


+ 96
- 96
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxBuilder.java View File

@@ -1,96 +1,96 @@
package com.jd.blockchain.transaction;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.TransactionBuilder;
import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.ledger.TransactionContentBody;
import com.jd.blockchain.ledger.TransactionRequestBuilder;
import com.jd.blockchain.utils.Bytes;
public class TxBuilder implements TransactionBuilder {
static {
DataContractRegistry.register(TransactionContentBody.class);
}
private BlockchainOperationFactory opFactory = new BlockchainOperationFactory();
private static final String DEFAULT_HASH_ALGORITHM = "SHA256";
private HashDigest ledgerHash;
public TxBuilder(HashDigest ledgerHash) {
this.ledgerHash = ledgerHash;
}
@Override
public HashDigest getLedgerHash() {
return ledgerHash;
}
@Override
public TransactionRequestBuilder prepareRequest() {
TransactionContent txContent = prepareContent();
return new TxRequestBuilder(txContent);
}
@Override
public TransactionContent prepareContent() {
TxContentBlob txContent = new TxContentBlob(ledgerHash);
txContent.addOperations(opFactory.getOperations());
byte[] contentBodyBytes = BinaryProtocol.encode(txContent, TransactionContentBody.class);
HashDigest contentHash = Crypto.getHashFunction(DEFAULT_HASH_ALGORITHM).hash(contentBodyBytes);
txContent.setHash(contentHash);
return txContent;
}
@Override
public LedgerInitOperationBuilder ledgers() {
return opFactory.ledgers();
}
@Override
public UserRegisterOperationBuilder users() {
return opFactory.users();
}
@Override
public DataAccountRegisterOperationBuilder dataAccounts() {
return opFactory.dataAccounts();
}
@Override
public DataAccountKVSetOperationBuilder dataAccount(String accountAddress) {
return opFactory.dataAccount(accountAddress);
}
@Override
public DataAccountKVSetOperationBuilder dataAccount(Bytes accountAddress) {
return opFactory.dataAccount(accountAddress);
}
@Override
public ContractCodeDeployOperationBuilder contracts() {
return opFactory.contracts();
}
public ContractEventSendOperationBuilder contractEvents() {
return opFactory.contractEvents();
}
@Override
public <T> T contract(Bytes address, Class<T> contractIntf) {
return opFactory.contract(address, contractIntf);
}
@Override
public <T> T contract(String address, Class<T> contractIntf) {
return opFactory.contract(address, contractIntf);
}
}
package com.jd.blockchain.transaction;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.TransactionBuilder;
import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.ledger.TransactionContentBody;
import com.jd.blockchain.ledger.TransactionRequestBuilder;
import com.jd.blockchain.utils.Bytes;
public class TxBuilder implements TransactionBuilder {
static {
DataContractRegistry.register(TransactionContentBody.class);
}
private BlockchainOperationFactory opFactory = new BlockchainOperationFactory();
private static final String DEFAULT_HASH_ALGORITHM = "SHA256";
private HashDigest ledgerHash;
public TxBuilder(HashDigest ledgerHash) {
this.ledgerHash = ledgerHash;
}
@Override
public HashDigest getLedgerHash() {
return ledgerHash;
}
@Override
public TransactionRequestBuilder prepareRequest() {
TransactionContent txContent = prepareContent();
return new TxRequestBuilder(txContent);
}
@Override
public TransactionContent prepareContent() {
TxContentBlob txContent = new TxContentBlob(ledgerHash);
txContent.addOperations(opFactory.getOperations());
byte[] contentBodyBytes = BinaryProtocol.encode(txContent, TransactionContentBody.class);
HashDigest contentHash = Crypto.getHashFunction(DEFAULT_HASH_ALGORITHM).hash(contentBodyBytes);
txContent.setHash(contentHash);
return txContent;
}
@Override
public LedgerInitOperationBuilder ledgers() {
return opFactory.ledgers();
}
@Override
public UserRegisterOperationBuilder users() {
return opFactory.users();
}
@Override
public DataAccountRegisterOperationBuilder dataAccounts() {
return opFactory.dataAccounts();
}
@Override
public DataAccountKVSetOperationBuilder dataAccount(String accountAddress) {
return opFactory.dataAccount(accountAddress);
}
@Override
public DataAccountKVSetOperationBuilder dataAccount(Bytes accountAddress) {
return opFactory.dataAccount(accountAddress);
}
@Override
public ContractCodeDeployOperationBuilder contracts() {
return opFactory.contracts();
}
public ContractEventSendOperationBuilder contractEvents() {
return opFactory.contractEvents();
}
@Override
public <T> T contract(Bytes address, Class<T> contractIntf) {
return opFactory.contract(address, contractIntf);
}
@Override
public <T> T contract(String address, Class<T> contractIntf) {
return opFactory.contract(address, contractIntf);
}
}

+ 91
- 91
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxContentBlob.java View File

@@ -1,91 +1,91 @@
package com.jd.blockchain.transaction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.utils.io.NumberMask;
/**
* 交易内容的数据块;
* <p>
*
* 包含原始交易请求的数据块;
*
* @author huanghaiquan
*
*/
public class TxContentBlob implements TransactionContent {
/**
* 操作数量的最大值;
*/
public static final int MAX_OP_COUNT = NumberMask.SHORT.MAX_BOUNDARY_SIZE;
private List<Operation> operationList = new ArrayList<Operation>();
private HashDigest hash;
private HashDigest ledgerHash;
public TxContentBlob(HashDigest ledgerHash) {
this.ledgerHash = ledgerHash;
}
/**
* 交易内容的哈希值;
*/
@Override
public HashDigest getHash() {
return this.hash;
}
/**
* 更新交易内容的哈希值;
* <p>
* 注:当前对象只充当值对象,不校验指定哈希值的完整性,调用者应该在外部实施完整性校验;
*
* @param hash
*/
public void setHash(HashDigest hash) {
this.hash = hash;
}
/**
* 交易请求链的hash
*
* @return
*/
@Override
public HashDigest getLedgerHash() {
return ledgerHash;
}
public void setLedgerHash(HashDigest ledgerHash) {
this.ledgerHash = ledgerHash;
}
@Override
public Operation[] getOperations() {
return operationList.toArray(new Operation[operationList.size()]);
}
public void setOperations(Object[] operations) {
// in array's case ,cast will failed!
for (Object operation : operations) {
Operation op = (Operation) operation;
addOperation(op);
}
}
public void addOperation(Operation operation) {
operationList.add(operation);
}
public void addOperations(Collection<Operation> operations) {
operationList.addAll(operations);
}
}
package com.jd.blockchain.transaction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.utils.io.NumberMask;
/**
* 交易内容的数据块;
* <p>
*
* 包含原始交易请求的数据块;
*
* @author huanghaiquan
*
*/
public class TxContentBlob implements TransactionContent {
/**
* 操作数量的最大值;
*/
public static final int MAX_OP_COUNT = NumberMask.SHORT.MAX_BOUNDARY_SIZE;
private List<Operation> operationList = new ArrayList<Operation>();
private HashDigest hash;
private HashDigest ledgerHash;
public TxContentBlob(HashDigest ledgerHash) {
this.ledgerHash = ledgerHash;
}
/**
* 交易内容的哈希值;
*/
@Override
public HashDigest getHash() {
return this.hash;
}
/**
* 更新交易内容的哈希值;
* <p>
* 注:当前对象只充当值对象,不校验指定哈希值的完整性,调用者应该在外部实施完整性校验;
*
* @param hash
*/
public void setHash(HashDigest hash) {
this.hash = hash;
}
/**
* 交易请求链的hash
*
* @return
*/
@Override
public HashDigest getLedgerHash() {
return ledgerHash;
}
public void setLedgerHash(HashDigest ledgerHash) {
this.ledgerHash = ledgerHash;
}
@Override
public Operation[] getOperations() {
return operationList.toArray(new Operation[operationList.size()]);
}
public void setOperations(Object[] operations) {
// in array's case ,cast will failed!
for (Object operation : operations) {
Operation op = (Operation) operation;
addOperation(op);
}
}
public void addOperation(Operation operation) {
operationList.add(operation);
}
public void addOperations(Collection<Operation> operations) {
operationList.addAll(operations);
}
}

+ 132
- 0
source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java View File

@@ -0,0 +1,132 @@
//package com.jd.blockchain.peer.statetransfer;
//
//import com.jd.blockchain.binaryproto.BinaryEncodingUtils;
//import com.jd.blockchain.crypto.hash.HashDigest;
//import com.jd.blockchain.ledger.LedgerBlock;
//import com.jd.blockchain.ledger.LedgerTransaction;
//import com.jd.blockchain.ledger.core.LedgerManage;
//import com.jd.blockchain.ledger.core.LedgerRepository;
//import com.jd.blockchain.ledger.core.TransactionSet;
//import com.jd.blockchain.statetransfer.DataSequenceElement;
//import com.jd.blockchain.statetransfer.DataSequenceInfo;
//import com.jd.blockchain.statetransfer.callback.DataSequenceReader;
//import com.jd.blockchain.storage.service.DbConnection;
//import com.jd.blockchain.storage.service.DbConnectionFactory;
//import com.jd.blockchain.tools.initializer.LedgerBindingConfig;
//import com.jd.blockchain.utils.codec.Base58Utils;
//import com.jd.blockchain.utils.codec.HexUtils;
//import org.springframework.beans.factory.annotation.Autowired;
//
///**
// *数据序列差异的提供者需要使用的回调接口实现类
// * @author zhangshuang
// * @create 2019/4/11
// * @since 1.0.0
// */
//public class DataSequenceReaderImpl implements DataSequenceReader {
//
// private LedgerManage ledgerManager;
//
// private DbConnectionFactory connFactory;
//
// private LedgerBindingConfig config;
//
// public DataSequenceReaderImpl(LedgerBindingConfig config, LedgerManage ledgerManager, DbConnectionFactory connFactory) {
// this.config = config;
// this.ledgerManager = ledgerManager;
// this.connFactory = connFactory;
// }
//
//
// /**
// * @param id 账本哈希的Base58编码
// * @return DataSequenceInfo 数据序列信息
// */
// @Override
// public DataSequenceInfo getDSInfo(String id) {
//
// byte[] hashBytes = Base58Utils.decode(id);
//
// HashDigest ledgerHash = new HashDigest(hashBytes);
//
// LedgerBindingConfig.BindingConfig bindingConfig = config.getLedger(ledgerHash);
// DbConnection dbConnNew = connFactory.connect(bindingConfig.getDbConnection().getUri(),
// bindingConfig.getDbConnection().getPassword());
// LedgerRepository ledgerRepository = ledgerManager.register(ledgerHash, dbConnNew.getStorageService());
//
// return new DataSequenceInfo(id, ledgerRepository.getLatestBlockHeight());
// }
//
// /**
// *
// * @param id 账本哈希的Base58编码
// * @param from 数据序列复制的起始高度
// * @param to 数据序列复制的结束高度
// * @return DataSequenceElement【】数据序列差异数据元素的数组
// */
// @Override
// public DataSequenceElement[] getDSDiffContent(String id, long from, long to) {
//
// DataSequenceElement[] dataSequenceElements = new DataSequenceElement[(int)(to - from + 1)];
// for (long i = from; i < to + 1; i++) {
// dataSequenceElements[(int)(i - from)] = getDSDiffContent(id, i);
// }
//
// return dataSequenceElements;
// }
//
// /**
// * 账本交易序列化
// * @param transaction 账本交易
// * @return byte[] 对账本交易进行序列化的结果
// */
// private byte[] serialize(LedgerTransaction transaction) {
// return BinaryEncodingUtils.encode(transaction, LedgerTransaction.class);
// }
//
// /**
// * 获得账本某一高度区块上的所有交易
// * @param id 账本哈希的Base58编码
// * @param height 账本的某个区块高度
// * @return DataSequenceElement 数据序列差异数据元素
// */
// @Override
// public DataSequenceElement getDSDiffContent(String id, long height) {
//
// int lastHeightTxTotalNums = 0;
//
// byte[][] transacionDatas = null;
//
// byte[] hashBytes = Base58Utils.decode(id);
//
// HashDigest ledgerHash = new HashDigest(hashBytes);
//
// LedgerBindingConfig.BindingConfig bindingConfig = config.getLedger(ledgerHash);
// DbConnection dbConnNew = connFactory.connect(bindingConfig.getDbConnection().getUri(),
// bindingConfig.getDbConnection().getPassword());
// LedgerRepository ledgerRepository = ledgerManager.register(ledgerHash, dbConnNew.getStorageService());
//
// LedgerBlock ledgerBlock = ledgerRepository.getBlock(height);
// TransactionSet transactionSet = ledgerRepository.getTransactionSet(ledgerBlock);
//
// if (height > 0) {
// lastHeightTxTotalNums = (int) ledgerRepository.getTransactionSet(ledgerRepository.getBlock(height - 1)).getTotalCount();
// }
//
// int currentHeightTxTotalNums = (int)ledgerRepository.getTransactionSet(ledgerRepository.getBlock(height)).getTotalCount();
//
// // get all transactions from current height block
// int currentHeightTxNums = currentHeightTxTotalNums - lastHeightTxTotalNums;
//
// LedgerTransaction[] transactions = transactionSet.getTxs(lastHeightTxTotalNums , currentHeightTxNums);
//
// for (int i = 0; i < transactions.length; i++) {
// byte[] transactionData = serialize(transactions[i]);
// transacionDatas[i] = transactionData;
// }
//
// return new DataSequenceElement(id, height, transacionDatas);
// }
//
//
//}

+ 170
- 0
source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java View File

@@ -0,0 +1,170 @@
//package com.jd.blockchain.peer.statetransfer;
//
//import com.jd.blockchain.consensus.service.MessageHandle;
//import com.jd.blockchain.ledger.TransactionState;
//import com.jd.blockchain.statetransfer.DataSequenceElement;
//import com.jd.blockchain.statetransfer.DataSequenceInfo;
//import com.jd.blockchain.statetransfer.callback.DataSequenceWriter;
//import com.jd.blockchain.statetransfer.comparator.DataSequenceComparator;
//
//import java.util.ArrayList;
//import java.util.Collections;
//
///**
// *数据序列差异的请求者需要使用的回调接口实现类
// * @author zhangshuang
// * @create 2019/4/11
// * @since 1.0.0
// */
//public class DataSequenceWriterImpl implements DataSequenceWriter {
//
// private long currHeight;
// private ArrayList<DataSequenceElement> deceidedElements = new ArrayList<DataSequenceElement>();
//
// private MessageHandle batchMessageHandle;
//
//
// public DataSequenceWriterImpl(MessageHandle batchMessageHandle) {
// this.batchMessageHandle = batchMessageHandle;
// }
//
// /**
// * 检查数据序列差异元素中的高度是否合理;
// * @param currHeight 当前结点的账本高度
// * @param dsUpdateElements 需要更新到本地结点的数据序列元素List
// * @return
// */
// private int checkElementsHeight(long currHeight, ArrayList<DataSequenceElement> dsUpdateElements) {
// boolean lossMiddleElements = false;
//
// // lose first element
// if (currHeight + 1 < dsUpdateElements.get(0).getHeight()){
// System.out.println("Diff response loss first element error!");
// return DataSequenceErrorType.DATA_SEQUENCE_LOSS_FIRST_ELEMENT.CODE;
// }
// else {
// for (int i = 0; i < dsUpdateElements.size(); i++) {
// if (dsUpdateElements.get(i).getHeight() == currHeight + 1 + i) {
// deceidedElements.add(dsUpdateElements.get(i));
// }
// // lose middle elements
// else {
// lossMiddleElements = true;
// break;
// }
// }
//
// if (lossMiddleElements) {
// System.out.println("Diff response loss middle elements error!");
// return DataSequenceErrorType.DATA_SEQUENCE_LOSS_MIDDLE_ELEMENT.CODE;
// }
//
// System.out.println("Diff response elements height normal!");
// return DataSequenceErrorType.DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL.CODE;
// }
//
// }
//
// /**
// * 对本地结点执行账本更新
// * @param realmName 账本哈希的Base58编码
// * @return void
// */
// private void exeUpdate(String realmName) {
//
// for (int i = 0; i < deceidedElements.size(); i++) {
// byte[][] element = deceidedElements.get(i).getData();
//
// String batchId = batchMessageHandle.beginBatch(realmName);
// try {
// int msgId = 0;
// for (byte[] txContent : element) {
// batchMessageHandle.processOrdered(msgId++, txContent, realmName, batchId);
// }
// // 结块
// batchMessageHandle.completeBatch(realmName, batchId);
// batchMessageHandle.commitBatch(realmName, batchId);
// } catch (Exception e) {
// // todo 需要处理应答码 404
// batchMessageHandle.rollbackBatch(realmName, batchId, TransactionState.DATA_SEQUENCE_UPDATE_ERROR.CODE);
// }
// }
//
// }
//
// /**
// * @param dsInfo 当前结点的数据序列信息
// * @param diffContents 数据序列差异的数据元素数组
// * @return int 更新结果码
// */
// @Override
// public int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement[] diffContents) {
// int result = 0;
//
// try {
// ArrayList<DataSequenceElement> dsUpdateElements = new ArrayList<DataSequenceElement>();
// //remove unexpected elements
// for (int i = 0 ; i < diffContents.length; i++) {
// if (diffContents[i].getId().equals(dsInfo.getId())) {
// dsUpdateElements.add(diffContents[i]);
// }
// }
//
// // sort elements by height
// Collections.sort(dsUpdateElements, new DataSequenceComparator());
//
// currHeight = dsInfo.getHeight();
//
// // check element's height
// result = checkElementsHeight(currHeight, dsUpdateElements);
//
// // cann't exe update
// if (result == DataSequenceErrorType.DATA_SEQUENCE_LOSS_FIRST_ELEMENT.CODE) {
// return result;
// }
// // exe elements update
// else {
// exeUpdate(dsInfo.getId());
// return result;
// }
// } catch (Exception e) {
// System.out.println(e.getMessage());
// e.printStackTrace();
// }
//
// return result;
// }
//
// @Override
// public int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement diffContents) {
// return 0;
// }
//
//
// /**
// * 数据序列更新错误码
// * @param
// * @return
// */
// public enum DataSequenceErrorType {
// DATA_SEQUENCE_LOSS_FIRST_ELEMENT((byte) 0x1),
// DATA_SEQUENCE_LOSS_MIDDLE_ELEMENT((byte) 0x2),
// DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL((byte) 0x3),
// ;
// public final int CODE;
//
// private DataSequenceErrorType(byte code) {
// this.CODE = code;
// }
//
// public static DataSequenceErrorType valueOf(byte code) {
// for (DataSequenceErrorType errorType : DataSequenceErrorType.values()) {
// if (errorType.CODE == code) {
// return errorType;
// }
// }
// throw new IllegalArgumentException("Unsupported code[" + code + "] of errorType!");
// }
// }
//
//}

+ 72
- 6
source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java View File

@@ -1,21 +1,30 @@
package com.jd.blockchain.peer.web;
import com.jd.blockchain.contract.ContractException;
import com.jd.blockchain.ledger.*;
import com.jd.blockchain.ledger.core.*;
import com.jd.blockchain.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.core.ContractAccountSet;
import com.jd.blockchain.ledger.core.DataAccount;
import com.jd.blockchain.ledger.core.DataAccountSet;
import com.jd.blockchain.ledger.core.LedgerAdministration;
import com.jd.blockchain.ledger.core.LedgerRepository;
import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.ParticipantCertData;
import com.jd.blockchain.ledger.core.TransactionSet;
import com.jd.blockchain.ledger.core.UserAccountSet;
import com.jd.blockchain.transaction.BlockchainQueryService;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.QueryUtil;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping(path = "/")
public class LedgerQueryController implements BlockchainQueryService {
@@ -342,6 +351,63 @@ public class LedgerQueryController implements BlockchainQueryService {
return entries;
}
@RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, path = "ledgers/{ledgerHash}/accounts/{address}/entries-version")
@Override
public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "address") String address,
@RequestBody KVInfoVO kvInfoVO) {
//parse kvInfoVO;
List<String> keyList = new ArrayList<>();
List<Long> versionList = new ArrayList<>();
if(kvInfoVO != null){
for(KVDataVO kvDataVO : kvInfoVO.getData()){
for(Long version : kvDataVO.getVersion()){
keyList.add(kvDataVO.getKey());
versionList.add(version);
}
}
}
String[] keys = keyList.toArray(new String[keyList.size()]);
Long[] versions = versionList.toArray(new Long[versionList.size()]);
if (keys == null || keys.length == 0) {
return null;
}
if (versions == null || versions.length == 0) {
return null;
}
if(keys.length != versions.length){
throw new ContractException("keys.length!=versions.length!");
}
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address));
KVDataEntry[] entries = new KVDataEntry[keys.length];
long ver = -1;
for (int i = 0; i < entries.length; i++) {
// ver = dataAccount.getDataVersion(Bytes.fromString(keys[i]));
ver = versions[i];
if (ver < 0) {
entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null);
}else {
if(dataAccount.getDataEntriesTotalCount()==0 ||
dataAccount.getBytes(Bytes.fromString(keys[i]), ver) == null){
//is the address is not exist; the result is null;
entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null);
} else {
byte[] value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver);
BytesValue decodeData = BinaryProtocol.decode(value);
entries[i] = new KVDataObject(keys[i], ver, PrimitiveType.valueOf(decodeData.getType().CODE), decodeData.getValue().toBytes());
}
}
}
return entries;
}
@RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries")
@Override
public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,


+ 15
- 156
source/peer/src/main/java/com/jd/blockchain/peer/web/ManagementController.java View File

@@ -5,10 +5,6 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import com.jd.blockchain.ledger.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -35,6 +31,21 @@ import com.jd.blockchain.consensus.service.NodeServer;
import com.jd.blockchain.consensus.service.ServerSettings;
import com.jd.blockchain.consensus.service.StateMachineReplicate;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.ContractCodeDeployOperation;
import com.jd.blockchain.ledger.ContractEventSendOperation;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.ledger.DataAccountRegisterOperation;
import com.jd.blockchain.ledger.EndpointRequest;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerInitOperation;
import com.jd.blockchain.ledger.NodeRequest;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.ledger.TransactionContentBody;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionResponse;
import com.jd.blockchain.ledger.UserRegisterOperation;
import com.jd.blockchain.ledger.core.LedgerAdminAccount;
import com.jd.blockchain.ledger.core.LedgerManage;
import com.jd.blockchain.ledger.core.LedgerRepository;
@@ -68,35 +79,17 @@ public class ManagementController implements LedgerBindingConfigAware, PeerManag
public static final int MIN_GATEWAY_ID = 10000;
// @Autowired
// private PeerSettings peerSetting;
// @Autowired
// private ConsensusTransactionService consensusService;
// private ConsensusPeer consensusReplica;
@Autowired
private LedgerManage ledgerManager;
@Autowired
private DbConnectionFactory connFactory;
// private Map<HashDigest, DbConnection> ledgerConns = new
// ConcurrentHashMap<>();
private Map<HashDigest, MsgQueueMessageDispatcher> ledgerTxConverters = new ConcurrentHashMap<>();
private Map<HashDigest, NodeServer> ledgerPeers = new ConcurrentHashMap<>();
private Map<HashDigest, CryptoSetting> ledgerCryptoSettings = new ConcurrentHashMap<>();
// private Map<ConsensusNode, ConsensusRealm> nodeRealms = new
// ConcurrentHashMap<>();
// private Map<HashDigest, ConsensusRealm> ledgerRealms = new
// ConcurrentHashMap<>();
// private Map<HashDigest, ConsensusRealm> ledgerRealmsNoConflict = new
// ConcurrentHashMap<>();
private LedgerBindingConfig config;
@@ -106,9 +99,6 @@ public class ManagementController implements LedgerBindingConfigAware, PeerManag
@Autowired
private StateMachineReplicate consensusStateManager;
// private static int step = 0;
// private static int temp = 0;
static {
DataContractRegistry.register(LedgerInitOperation.class);
DataContractRegistry.register(LedgerBlock.class);
@@ -134,24 +124,6 @@ public class ManagementController implements LedgerBindingConfigAware, PeerManag
}
@PostConstruct
private void init() {
}
@PreDestroy
private void destroy() {
// DbConnection[] conns = ledgerConns.values().toArray(new DbConnection[ledgerConns.size()]);
// ledgerConns.clear();
// for (DbConnection conn : conns) {
// try {
// conn.close();
// } catch (Exception e) {
// // Ignore;
// }
// }
}
/**
* 接入认证;
*
@@ -234,42 +206,8 @@ public class ManagementController implements LedgerBindingConfigAware, PeerManag
HashDigest[] ledgerHashs = config.getLedgerHashs();
for (HashDigest ledgerHash : ledgerHashs) {
setConfig(config,ledgerHash);
// LedgerBindingConfig.BindingConfig bindingConfig = config.getLedger(ledgerHash);
// DbConnection dbConnNew = connFactory.connect(bindingConfig.getDbConnection().getUri(),
// bindingConfig.getDbConnection().getPassword());
// LedgerRepository ledgerRepository = ledgerManager.register(ledgerHash, dbConnNew.getStorageService());
//
// // load provider;
// LedgerAdminAccount ledgerAdminAccount = ledgerRepository.getAdminAccount();
// String consensusProvider = ledgerAdminAccount.getSetting().getConsensusProvider();
// ConsensusProvider provider = ConsensusProviders.getProvider(consensusProvider);
// // find current node;
// Bytes csSettingBytes = ledgerAdminAccount.getSetting().getConsensusSetting();
// ConsensusSettings csSettings = provider.getSettingsFactory().getConsensusSettingsEncoder()
// .decode(csSettingBytes.toBytes());
// NodeSettings currentNode = null;
// for (NodeSettings nodeSettings : csSettings.getNodes()) {
// if (nodeSettings.getAddress().equals(bindingConfig.getParticipant().getAddress())) {
// currentNode = nodeSettings;
// }
// }
// if (currentNode == null) {
// throw new IllegalArgumentException(
// "Current node is not found from the consensus settings of ledger[" + ledgerHash.toBase58()
// + "]!");
// }
// ServerSettings serverSettings = provider.getServerFactory().buildServerSettings(ledgerHash.toBase58(), csSettings, currentNode.getAddress());
//
// NodeServer server = provider.getServerFactory().setupServer(serverSettings, consensusMessageHandler,
// consensusStateManager);
// ledgerPeers.put(ledgerHash, server);
// ledgerCryptoSettings.put(ledgerHash, ledgerAdminAccount.getSetting().getCryptoSetting());
}
// remove duplicate consensus realm,and establish consensus peer and consensus
// realm corresponding relationship
// initBindingConfig(config);
this.config = config;
} catch (Exception e) {
@@ -314,46 +252,6 @@ public class ManagementController implements LedgerBindingConfigAware, PeerManag
return server;
}
// private void initBindingConfig(LedgerBindingConfig config) {
// boolean intersection = false;
// // to remove intersection consensus realm
// for (HashDigest hashDigest : ledgerRealms.keySet()) {
// ConsensusRealm consensusRealm1i = ledgerRealms.get(hashDigest);
// for (ConsensusRealm consensusRealm1j : ledgerRealms.values()) {
// // avoid compare with myself
// if (consensusRealm1i.equals(consensusRealm1j)) {
// continue;
// }
// if (consensusRealm1i.hasIntersection(consensusRealm1j)) {
// intersection = true;
// break;
// }
// }
// // prompt consensus realm conflict info
// if (intersection == true) {
// ConsoleUtils.info("\r\nconsensus realm intersection with other consensus
// realm\r\n");
// continue;
// }
// if (intersection == false) {
// // add consensus realm without conflict to ledgerRealmsNoConflict
// ledgerRealmsNoConflict.put(hashDigest, consensusRealm1i);
//
// // String consensusSystemFile =
// config.getLedger(hashDigest).getCsConfigFile();
// int currentId = config.getLedger(hashDigest).getParticipant().getId();
// // init consensusSystemConfig;
// ConsensusProperties csProps =
// ConsensusProperties.resolve(consensusRealm1i.getSetting());
// ConsensusPeer consensusPeer = new ConsensusPeer(consensusRealm1i, currentId,
// consensusService,
// csProps.getProperties());
// ledgerPeers.put(hashDigest, consensusPeer);
// }
// } // END OF FOR:get ledgerRealmsNoConflict and ledgerPeers
//
// }
@Override
public ConsensusRealm[] getRealms() {
throw new IllegalStateException("Not implemented!");
@@ -364,45 +262,6 @@ public class ManagementController implements LedgerBindingConfigAware, PeerManag
for (NodeServer peer : ledgerPeers.values()) {
runRealm(peer);
}
// try {
//
// // for (ConsensusPeer peer : ledgerPeers.values()) {
// for (Map.Entry<HashDigest, ConsensusPeer> entry : ledgerPeers.entrySet()) {
// HashDigest ledgerHash = entry.getKey();
// ConsensusPeer peer = entry.getValue();
// // TODO: 多线程启动;
// ConsensusNode[] nodes = peer.getConsensusRealm().getNodes();
// StringBuilder consensusInfo = new StringBuilder();
// for (ConsensusNode node : nodes) {
// consensusInfo.append(
// String.format("[%s]-%s; ", node.getAddress(),
// node.getConsensusAddress().toString()));
// }
// LOGGER.debug(String.format("-------- start consensus peer[Id=%s] --Nodes=%s
// -------------",
// peer.getCurrentId(), consensusInfo.toString()));
// peer.start();
// // 设置消息队列
// MsgQueueMessageDispatcher messageDispatcher = ledgerTxConverters.get(ledgerHash);
//
// if (messageDispatcher == null) {
// LedgerBindingConfig.BindingConfig bindingConfig =
// this.config.getLedger(ledgerHash);
// MQConnectionConfig mqConnection = bindingConfig.getMqConnection();
// if (mqConnection != null && mqConnection.getServer() != null) {
// MessageQueueConfig mqConfig = new
// MessageQueueConfig(mqConnection.getServer(),
// mqConnection.getTopic());
// messageDispatcher = MessageDispatcherFactory.newInstance(mqConfig, peer);
// Executors.newSingleThreadExecutor().execute(messageDispatcher); // 启动监听
// }
// }
// }
// } catch (Exception e) {
// LOGGER.error("Error occurred on starting all consensus realms! --" +
// e.getMessage(), e);
// throw new IllegalStateException(e.getMessage(), e);
// }
}
@Override


+ 14
- 8
source/peer/src/main/java/com/jd/blockchain/peer/web/PeerTimeTasks.java View File

@@ -15,11 +15,11 @@ import com.jd.blockchain.peer.ConsensusManage;
import com.jd.blockchain.peer.LedgerBindingConfigAware;
import com.jd.blockchain.peer.PeerServerBooter;
import com.jd.blockchain.tools.initializer.LedgerBindingConfig;
import com.jd.blockchain.utils.ArgumentSet;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.io.ClassPathResource;
@@ -38,9 +38,11 @@ import java.util.*;
* @since 1.0.0
*/
@Component
//@EnableScheduling
@EnableScheduling
public class PeerTimeTasks implements ApplicationContextAware {

private static Logger LOGGER = LoggerFactory.getLogger(PeerTimeTasks.class);

private ApplicationContext applicationContext;

@Autowired
@@ -51,7 +53,9 @@ public class PeerTimeTasks implements ApplicationContextAware {
//每1分钟执行一次
@Scheduled(cron = "0 */5 * * * * ")
public void updateLedger(){
System.out.println ("Update Ledger Tasks Start " + new Date());

LOGGER.debug("Time Task Update Ledger Tasks Start {}", new Date());

try {
LedgerBindingConfig ledgerBindingConfig = loadLedgerBindingConfig();

@@ -78,7 +82,8 @@ public class PeerTimeTasks implements ApplicationContextAware {
Map<String, LedgerBindingConfigAware> bindingConfigAwares = applicationContext.getBeansOfType(LedgerBindingConfigAware.class);
List<NodeServer> nodeServers = new ArrayList<>();
for (HashDigest ledgerHash : newAddHashs) {
System.out.printf("newLedger[%s] \r\n", ledgerHash.toBase58());

LOGGER.info("New Ledger [{}] Need To Be Init !!!", ledgerHash.toBase58());
for (LedgerBindingConfigAware aware : bindingConfigAwares.values()) {
nodeServers.add(aware.setConfig(ledgerBindingConfig, ledgerHash));
}
@@ -89,10 +94,10 @@ public class PeerTimeTasks implements ApplicationContextAware {
consensusManage.runRealm(nodeServer);
}
} else {
System.out.println("All Ledgers is newest!!!");
LOGGER.debug("All Ledgers is newest!!!");
}
} catch (Exception e) {
e.printStackTrace();
LOGGER.error(e.getMessage());
}
}

@@ -104,7 +109,8 @@ public class PeerTimeTasks implements ApplicationContextAware {
private LedgerBindingConfig loadLedgerBindingConfig() throws Exception {
LedgerBindingConfig ledgerBindingConfig;
ledgerBindConfigFile = PeerServerBooter.ledgerBindConfigFile;
System.out.printf("load ledgerBindConfigFile = %s \r\n", ledgerBindConfigFile);
LOGGER.debug("Load LedgerBindConfigFile path = {}",
ledgerBindConfigFile == null ? "Default" : ledgerBindConfigFile);
if (ledgerBindConfigFile == null) {
ClassPathResource configResource = new ClassPathResource("ledger-binding.conf");
InputStream in = configResource.getInputStream();


+ 3
- 20
source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/LedgerInitSettings.java View File

@@ -34,7 +34,7 @@ public class LedgerInitSettings {
/**
* 共识协议
*/
private int consensusProtocol;
private String consensusProtocol;

/**
* 共识配置
@@ -70,11 +70,11 @@ public class LedgerInitSettings {
this.cryptoSetting = cryptoSetting;
}

public int getConsensusProtocol() {
public String getConsensusProtocol() {
return consensusProtocol;
}

public void setConsensusProtocol(int consensusProtocol) {
public void setConsensusProtocol(String consensusProtocol) {
this.consensusProtocol = consensusProtocol;
}

@@ -93,21 +93,4 @@ public class LedgerInitSettings {
public void setParticipantNodes(ParticipantNode[] participantNodes) {
this.participantNodes = participantNodes;
}

public enum CONSENSUS_PROTOCOL {
UNKNOWN(0),
BFTSMART(1),
MSGQUEUE(2),
;

private int code;

CONSENSUS_PROTOCOL(int code) {
this.code = code;
}

public int code() {
return code;
}
}
}

+ 5
- 0
source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java View File

@@ -147,6 +147,11 @@ public abstract class BlockchainServiceProxy implements BlockchainService {
return getQueryService(ledgerHash).getDataEntries(ledgerHash, address, keys);
}

@Override
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) {
return getQueryService(ledgerHash).getDataEntries(ledgerHash, address, kvInfoVO);
}

@Override
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) {
return getQueryService(ledgerHash).getDataEntries(ledgerHash, address, fromIndex, count);


+ 6
- 1
source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java View File

@@ -496,7 +496,11 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService
@PathParam(name="address") String address,
@RequestParam(name="keys", array = true) String... keys);

@HttpAction(method = HttpMethod.POST, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries")
@HttpAction(method=HttpMethod.POST, path="ledgers/{ledgerHash}/accounts/{address}/entries-version")
@Override
KVDataEntry[] getDataEntries(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash,
@PathParam(name="address") String address,
@RequestBody KVInfoVO kvInfoVO);

/**
* 返回数据账户中指定序号的最新值;
@@ -513,6 +517,7 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService
* 如果参数值为 -1,则返回全部的记录;<br>
* @return
*/
@HttpAction(method = HttpMethod.POST, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries")
@Override
KVDataEntry[] getDataEntries(@PathParam(name = "ledgerHash") HashDigest ledgerHash,
@PathParam(name = "address") String address,


+ 34
- 0
source/state-transfer/pom.xml View File

@@ -0,0 +1,34 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>jdchain-root</artifactId>
<version>0.9.0-SNAPSHOT</version>
</parent>
<artifactId>state-transfer</artifactId>
<dependencies>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>stp-communication</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>utils-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>utils-serialize</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

+ 75
- 0
source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequence.java View File

@@ -0,0 +1,75 @@
package com.jd.blockchain.statetransfer;

import java.net.InetSocketAddress;
import java.util.LinkedList;

/**
* 测试过程建立的一个数据序列
* @author zhangshuang
* @create 2019/4/18
* @since 1.0.0
*/
public class DataSequence {

private InetSocketAddress address;
private String id;

// 每个数据序列维护了一系列的数据序列元素
private LinkedList<DataSequenceElement> dataSequenceElements = new LinkedList<>();


public DataSequence(InetSocketAddress address, String id) {
this.address = address;
this.id = id;
}

public String getId() {
return id;
}

public InetSocketAddress getAddress() {
return address;
}


public void addElements(DataSequenceElement[] elements) {
for (DataSequenceElement element : elements) {
addElement(element);
}
}

public void addElement(DataSequenceElement element) {
try {
if (dataSequenceElements.size() == 0) {
if (element.getHeight() != 0) {
throw new IllegalArgumentException("Data sequence add element height error!");
}
dataSequenceElements.addLast(element);
}
else {
if (dataSequenceElements.getLast().getHeight() != element.getHeight() - 1) {
throw new IllegalArgumentException("Data sequence add element height error!");
}
dataSequenceElements.addLast(element);
}

} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}

public LinkedList<DataSequenceElement> getDataSequenceElements() {
return dataSequenceElements;
}

public DataSequenceInfo getDSInfo() {
if (dataSequenceElements.size() == 0) {
return new DataSequenceInfo(id, -1);
}
else {
return new DataSequenceInfo(id, dataSequenceElements.getLast().getHeight());
}
}

}

+ 53
- 0
source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceElement.java View File

@@ -0,0 +1,53 @@
package com.jd.blockchain.statetransfer;

import java.io.Serializable;

/**
* 数据序列需要复制内容的元素或单位
* @author zhangshuang
* @create 2019/4/11
* @since 1.0.0
*/
public class DataSequenceElement implements Serializable {

private static final long serialVersionUID = -719578198150380571L;

//数据序列的唯一标识符;
private String id;

//数据序列的某个高度;
private long height;

//对应某个高度的数据序列内容
private byte[][] data;

public DataSequenceElement(String id, long height, byte[][] data) {
this.id = id;
this.height = height;
this.data = data;
}

public long getHeight() {
return height;
}

public void setHeight(long height) {
this.height = height;
}

public String getId() {
return id;
}

public void setId(String id) {
id = id;
}

public byte[][] getData() {
return data;
}

public void setData(byte[][] data) {
this.data = data;
}
}

+ 37
- 0
source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceInfo.java View File

@@ -0,0 +1,37 @@
package com.jd.blockchain.statetransfer;

/**
* 共识结点上的某个数据序列的当前状态信息,每个共识结点可以对应任意个数据序列;
* @author zhangshuang
* @create 2019/4/11
* @since 1.0.0
*/
public class DataSequenceInfo {

//数据序列的唯一标识
private String id;

//数据序列的当前高度
private long height;

public DataSequenceInfo(String id, long height) {
this.id = id;
this.height = height;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public long getHeight() {
return height;
}

public void setHeight(long height) {
this.height = height;
}
}

+ 39
- 0
source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceReader.java View File

@@ -0,0 +1,39 @@
package com.jd.blockchain.statetransfer.callback;

import com.jd.blockchain.statetransfer.DataSequenceElement;
import com.jd.blockchain.statetransfer.DataSequenceInfo;

/**
* 数据序列差异提供者需要使用的回调接口
* @author zhangshuang
* @create 2019/4/11
* @since 1.0.0
*/
public interface DataSequenceReader {

/**
* 差异提供者根据数据序列标识符获取数据序列当前状态;
* @param id 数据序列标识符
* @return 数据序列当前状态信息
*/
DataSequenceInfo getDSInfo(String id);


/**
* 差异提供者根据数据序列标识符以及起始,结束高度提供数据序列该范围的差异内容;
* @param id 数据序列标识符
* @param from 差异的起始高度
* @param to 差异的结束高度
* @return 差异元素组成的数组
*/
DataSequenceElement[] getDSDiffContent(String id, long from, long to);


/**
* 差异提供者根据数据序列标识符以及高度提供数据序列的差异内容;
* @param id 数据序列标识符
* @param height 要获得哪个高度的差异元素
* @return 差异元素
*/
DataSequenceElement getDSDiffContent(String id, long height);
}

+ 59
- 0
source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceReaderImpl.java View File

@@ -0,0 +1,59 @@
package com.jd.blockchain.statetransfer.callback;

import com.jd.blockchain.statetransfer.DataSequence;
import com.jd.blockchain.statetransfer.DataSequenceElement;
import com.jd.blockchain.statetransfer.DataSequenceInfo;

import java.util.LinkedList;

/**
* 数据序列差异的提供者需要使用的回调接口实现类
* @author zhangshuang
* @create 2019/4/22
* @since 1.0.0
*/

public class DataSequenceReaderImpl implements DataSequenceReader {

DataSequence currDataSequence;

public DataSequenceReaderImpl(DataSequence currDataSequence) {
this.currDataSequence = currDataSequence;
}

@Override
public DataSequenceInfo getDSInfo(String id) {
return currDataSequence.getDSInfo();
}

@Override
public DataSequenceElement[] getDSDiffContent(String id, long from, long to) {
DataSequenceElement[] elements = new DataSequenceElement[(int)(to - from + 1)];

int i = 0;
LinkedList<DataSequenceElement> dataSequenceElements = currDataSequence.getDataSequenceElements();
for (DataSequenceElement element : dataSequenceElements) {
if (element.getHeight() < from || element.getHeight() > to) {
continue;
}
else {
elements[i++] = element;
}
}

return elements;

}

@Override
public DataSequenceElement getDSDiffContent(String id, long height) {
for(DataSequenceElement dataSequenceElement : currDataSequence.getDataSequenceElements()) {
if (dataSequenceElement.getHeight() == height) {
return dataSequenceElement;

}
}
return null;
}
}


+ 30
- 0
source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java View File

@@ -0,0 +1,30 @@
package com.jd.blockchain.statetransfer.callback;

import com.jd.blockchain.statetransfer.DataSequenceElement;
import com.jd.blockchain.statetransfer.DataSequenceInfo;

/**
* 数据序列差异请求者获得差异内容后需要回调该接口
* @author zhangshuang
* @create 2019/4/11
* @since 1.0.0
*/
public interface DataSequenceWriter {

/**
* 差异请求者更新本地数据序列的状态,一次可以更新多个差异元素
* @param dsInfo 数据序列当前状态信息
* @param diffContents 需要更新的差异元素数组
* @return 更新结果编码
*/
int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement[] diffContents);

/**
* 差异请求者更新本地数据序列的状态,一次只更新一个差异元素
* @param dsInfo 数据序列当前状态信息
* @param diffContent 需要更新的差异元素
* @return 更新结果编码
*/
// int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement diffContent);

}

+ 142
- 0
source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriterImpl.java View File

@@ -0,0 +1,142 @@
package com.jd.blockchain.statetransfer.callback;

import com.jd.blockchain.statetransfer.DataSequence;
import com.jd.blockchain.statetransfer.DataSequenceElement;
import com.jd.blockchain.statetransfer.DataSequenceInfo;

import java.util.ArrayList;

/**
* 数据序列差异的请求者需要使用的回调接口实现类
* @author zhangshuang
* @create 2019/4/22
* @since 1.0.0
*/
public class DataSequenceWriterImpl implements DataSequenceWriter {

private long currHeight;
private DataSequence currDataSequence;
private ArrayList<DataSequenceElement> deceidedElements = new ArrayList<DataSequenceElement>();

public DataSequenceWriterImpl(DataSequence currDataSequence) {
this.currDataSequence = currDataSequence;
}

/**
* 检查数据序列差异元素中的高度是否合理;
* @param currHeight 当前结点的账本高度
* @param dsUpdateElements 需要更新到本地结点的数据序列元素List
* @return
*/
private int checkElementsHeight(long currHeight, ArrayList<DataSequenceElement> dsUpdateElements) {
boolean lossMiddleElements = false;

// lose first element
if (currHeight + 1 < dsUpdateElements.get(0).getHeight()){
System.out.println("Diff response loss first element error!");
return DataSequenceErrorType.DATA_SEQUENCE_LOSS_FIRST_ELEMENT.CODE;
}
else {
for (int i = 0; i < dsUpdateElements.size(); i++) {
if (dsUpdateElements.get(i).getHeight() == currHeight + 1 + i) {
deceidedElements.add(dsUpdateElements.get(i));
}
// lose middle elements
else {
lossMiddleElements = true;
break;
}
}

if (lossMiddleElements) {
System.out.println("Diff response loss middle elements error!");
return DataSequenceErrorType.DATA_SEQUENCE_LOSS_MIDDLE_ELEMENT.CODE;
}

System.out.println("Diff response elements height normal!");
return DataSequenceErrorType.DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL.CODE;
}

}

@Override
public int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement[] diffContents) {

int result = 0;

try {
ArrayList<DataSequenceElement> dsUpdateElements = new ArrayList<DataSequenceElement>();

if (diffContents == null) {
throw new IllegalArgumentException("Update diffContents is null!");
}

//remove unexpected elements
for (int i = 0 ; i < diffContents.length; i++) {
if (diffContents[i].getId().equals(dsInfo.getId())) {
dsUpdateElements.add(diffContents[i]);
}
}

currHeight = dsInfo.getHeight();

// check element's height
result = checkElementsHeight(currHeight, dsUpdateElements);

// cann't exe update
if (result == DataSequenceErrorType.DATA_SEQUENCE_LOSS_FIRST_ELEMENT.CODE) {
return result;
}
// exe elements update
else {
System.out.println("Old data sequence state: ");
System.out.println(" Current height = " + currDataSequence.getDataSequenceElements().getLast().getHeight());
currDataSequence.addElements(deceidedElements.toArray(new DataSequenceElement[deceidedElements.size()]));

System.out.println("Update diffContents is completed!");
System.out.println("New data sequence state: ");
System.out.println(" Current height = " + currDataSequence.getDataSequenceElements().getLast().getHeight());

return result;
}



} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}

return DataSequenceErrorType.DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL.CODE;

}

// @Override
// public int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement diffContent) {
// currDataSequence.addElement(diffContent);
// return DataSequenceErrorType.DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL.CODE;
// }

public enum DataSequenceErrorType {
DATA_SEQUENCE_LOSS_FIRST_ELEMENT((byte) 0x1),
DATA_SEQUENCE_LOSS_MIDDLE_ELEMENT((byte) 0x2),
DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL((byte) 0x3),
;
public final int CODE;

private DataSequenceErrorType(byte code) {
this.CODE = code;
}

public static DataSequenceErrorType valueOf(byte code) {
for (DataSequenceErrorType errorType : DataSequenceErrorType.values()) {
if (errorType.CODE == code) {
return errorType;
}
}
throw new IllegalArgumentException("Unsupported code[" + code + "] of errorType!");
}
}

}


+ 32
- 0
source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/comparator/DataSequenceComparator.java View File

@@ -0,0 +1,32 @@
package com.jd.blockchain.statetransfer.comparator;

import com.jd.blockchain.statetransfer.DataSequenceElement;

import java.util.Comparator;

/**
* 数据序列差异元素的高度比较器
* @author zhangshuang
* @create 2019/4/18
* @since 1.0.0
*/
public class DataSequenceComparator implements Comparator<DataSequenceElement> {

// sort by data sequence height
/**
* 对差异元素根据高度大小排序
* @param o1 差异元素1
* @param o2 差异元素2
* @return >0 or <0
*/
@Override
public int compare(DataSequenceElement o1, DataSequenceElement o2) {
long height1;
long height2;

height1 = o1.getHeight();
height2 = o2.getHeight();

return (int) (height1 - height2);
}
}

+ 21
- 0
source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/exception/DataSequenceException.java View File

@@ -0,0 +1,21 @@
package com.jd.blockchain.statetransfer.exception;

/**
* 数据序列异常处理
* @author zhangshuang
* @create 2019/4/18
* @since 1.0.0
*/
public class DataSequenceException extends RuntimeException {

private static final long serialVersionUID = -4090881296855827889L;


public DataSequenceException(String message) {
super(message);
}
public DataSequenceException(String message, Throwable cause) {
super(message, cause);
}

}

+ 80
- 0
source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSDefaultMessageExecutor.java View File

@@ -0,0 +1,80 @@
package com.jd.blockchain.statetransfer.message;

import com.jd.blockchain.statetransfer.callback.DataSequenceReader;
import com.jd.blockchain.statetransfer.callback.DataSequenceWriter;
import com.jd.blockchain.statetransfer.process.DSTransferProcess;
import com.jd.blockchain.statetransfer.result.DSDiffRequestResult;
import com.jd.blockchain.stp.communication.MessageExecutor;
import com.jd.blockchain.stp.communication.RemoteSession;

/**
* 数据序列差异提供者使用,解析收到的差异请求消息并产生响应
* @author zhangshuang
* @create 2019/4/11
* @since 1.0.0
*/
public class DSDefaultMessageExecutor implements MessageExecutor {

DataSequenceReader dsReader;
DataSequenceWriter dsWriter;

public DSDefaultMessageExecutor(DataSequenceReader dsReader, DataSequenceWriter dsWriter) {
this.dsReader = dsReader;
this.dsWriter = dsWriter;
}

/**
* 对状态机复制的差异请求进行响应
* @param key 请求消息的Key
* @param data 需要解码的字节数组
* @param session 指定响应需要使用的目标结点会话
* @return 配置为自动响应时,返回值为响应的字节数组,配置为手动响应时,不需要关注返回值
*/

@Override
public byte[] receive(String key, byte[] data, RemoteSession session) {

try {
Object object = DSMsgResolverFactory.getDecoder(dsWriter, dsReader).decode(data);

// 解析CMD_DSINFO_REQUEST 请求的情况
if (object instanceof String) {
String id = (String)object;
byte[] respLoadMsg = DSMsgResolverFactory.getEncoder(dsWriter, dsReader).encode(DSTransferProcess.DataSequenceMsgType.CMD_DSINFO_RESPONSE, id, 0, 0);
session.reply(key, new DataSequenceLoadMessage(respLoadMsg));
}
// 解析CMD_GETDSDIFF_REQUEST 请求的情况
else if (object instanceof DSDiffRequestResult) {

DSDiffRequestResult requestResult = (DSDiffRequestResult)object;
String id = requestResult.getId();
long fromHeight = requestResult.getFromHeight();
long toHeight = requestResult.getToHeight();
//每个高度的数据序列差异元素进行一次响应的情况
for (long i = fromHeight; i < toHeight + 1; i++) {
byte[] respLoadMsg = DSMsgResolverFactory.getEncoder(dsWriter, dsReader).encode(DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_RESPONSE, id, i, i);
session.reply(key, new DataSequenceLoadMessage(respLoadMsg));
}
//所有差异进行一次响应的情况
}
else {
throw new IllegalArgumentException("Receive data exception, unknown message type!");
}

} catch (Exception e) {
e.printStackTrace();
}

return null;
}

/**
* 响应类型设置
* 分手动响应,自动响应两种类型
*/
@Override
public REPLY replyType() {
return REPLY.MANUAL;
}

}

+ 34
- 0
source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSMsgResolverFactory.java View File

@@ -0,0 +1,34 @@
package com.jd.blockchain.statetransfer.message;

import com.jd.blockchain.statetransfer.callback.DataSequenceReader;
import com.jd.blockchain.statetransfer.callback.DataSequenceWriter;

/**
* 数据序列消息解析器工厂
* @author zhangshuang
* @create 2019/4/18
* @since 1.0.0
*
*/
public class DSMsgResolverFactory {

/**
* 获得数据序列消息编码器实例
* @param dsWriter 差异请求者执行数据序列更新的执行器
* @param dsReader 差异响应者执行数据序列读取的执行器
* @return 消息编码器实例
*/
public static DataSequenceMsgEncoder getEncoder(DataSequenceWriter dsWriter, DataSequenceReader dsReader) {
return new DataSequenceMsgEncoder(dsWriter, dsReader);
}

/**
* 获得数据序列消息解码器实例
* @param dsWriter 差异请求者执行数据序列更新的执行器
* @param dsReader 差异响应者执行数据序列读取的执行器
* @return 消息解码器实例
*/
public static DataSequenceMsgDecoder getDecoder(DataSequenceWriter dsWriter, DataSequenceReader dsReader) {
return new DataSequenceMsgDecoder(dsWriter, dsReader);
}
}

+ 28
- 0
source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceLoadMessage.java View File

@@ -0,0 +1,28 @@
package com.jd.blockchain.statetransfer.message;

import com.jd.blockchain.stp.communication.message.LoadMessage;

/**
* 数据序列复制的负载消息
* @author zhangshuang
* @create 2019/4/18
* @since 1.0.0
*
*/
public class DataSequenceLoadMessage implements LoadMessage {

byte[] bytes;

public DataSequenceLoadMessage(byte[] bytes) {
this.bytes = bytes;
}

public void setBytes(byte[] bytes) {
this.bytes = bytes;
}

@Override
public byte[] toBytes() {
return bytes;
}
}

+ 107
- 0
source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgDecoder.java View File

@@ -0,0 +1,107 @@
package com.jd.blockchain.statetransfer.message;

import com.jd.blockchain.statetransfer.DataSequenceElement;
import com.jd.blockchain.statetransfer.DataSequenceInfo;
import com.jd.blockchain.statetransfer.callback.DataSequenceReader;
import com.jd.blockchain.statetransfer.callback.DataSequenceWriter;
import com.jd.blockchain.statetransfer.process.DSTransferProcess;
import com.jd.blockchain.statetransfer.result.DSDiffRequestResult;
import com.jd.blockchain.utils.io.BytesUtils;
import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils;

/**
* 数据序列消息解码器
* @author zhangshuang
* @create 2019/4/18
* @since 1.0.0
*/
public class DataSequenceMsgDecoder {

private int heightSize = 8;
private int msgTypeSize = 1;

private long respHeight;
private long fromHeight;
private long toHeight;
private int idSize;
private byte[] idBytes;
private String id;
private int diffElemSize;
private byte[] diffElem;
DataSequenceElement dsElement;

private DataSequenceWriter dsWriter;
private DataSequenceReader dsReader;

public DataSequenceMsgDecoder(DataSequenceWriter dsWriter, DataSequenceReader dsReader) {
this.dsWriter = dsWriter;
this.dsReader = dsReader;
}


/**
* 对编过码的字节数组解码,还原成对象实例
* @param loadMessage 字节序列
* @return 解码后的对象
*/
public Object decode(byte[] loadMessage) {

try {
if (loadMessage.length <= 5) {
System.out.println("LoadMessage size is less than 5!");
throw new IllegalArgumentException();
}

int dataLength = BytesUtils.toInt(loadMessage, 0, 4);
byte msgCode = loadMessage[4];

// send by diff provider, diff requester decode
if (msgCode == DSTransferProcess.DataSequenceMsgType.CMD_DSINFO_RESPONSE.CODE) {
respHeight = BytesUtils.toLong(loadMessage, 4 + msgTypeSize);
idSize = BytesUtils.toInt(loadMessage, 4 + msgTypeSize + heightSize, 4);
idBytes = new byte[idSize];
System.arraycopy(loadMessage, 4 + msgTypeSize + heightSize + 4, idBytes, 0, idSize);
id = new String(idBytes);
return new DataSequenceInfo(id, respHeight);
}
// send by diff provider, diff requester decode
else if (msgCode == DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_RESPONSE.CODE) {
diffElemSize = BytesUtils.toInt(loadMessage, 4 + msgTypeSize, 4);
diffElem = new byte[diffElemSize];
System.arraycopy(loadMessage, 4 + msgTypeSize + 4, diffElem, 0, diffElemSize);
dsElement = BinarySerializeUtils.deserialize(diffElem);
return dsElement;
}
// send by diff requester, diff provider decode
else if (msgCode == DSTransferProcess.DataSequenceMsgType.CMD_DSINFO_REQUEST.CODE) {
idSize = BytesUtils.toInt(loadMessage, 4 + msgTypeSize, 4);
idBytes = new byte[idSize];
System.arraycopy(loadMessage, 4 + msgTypeSize + 4, idBytes, 0, idSize);
id = new String(idBytes);
return id;
}
// send by diff requester, diff provider decode
else if (msgCode == DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_REQUEST.CODE) {
fromHeight = BytesUtils.toLong(loadMessage, 4 + msgTypeSize);
toHeight = BytesUtils.toLong(loadMessage, 4 + msgTypeSize + heightSize);
idSize = BytesUtils.toInt(loadMessage, 4 + msgTypeSize + heightSize + heightSize, 4);
idBytes = new byte[idSize];
System.arraycopy(loadMessage, 4 + msgTypeSize + heightSize + heightSize + 4, idBytes, 0, idSize);
id = new String(idBytes);
return new DSDiffRequestResult(id, fromHeight, toHeight);
}
else {
System.out.println("Unknown message type!");
throw new IllegalArgumentException();
}

} catch (Exception e) {
System.out.println("Error to decode message: " + e.getMessage() + "!");
e.printStackTrace();

}

return null;
}

}

+ 133
- 0
source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgEncoder.java View File

@@ -0,0 +1,133 @@
package com.jd.blockchain.statetransfer.message;

import com.jd.blockchain.statetransfer.DataSequenceElement;
import com.jd.blockchain.statetransfer.callback.DataSequenceReader;
import com.jd.blockchain.statetransfer.callback.DataSequenceWriter;
import com.jd.blockchain.statetransfer.process.DSTransferProcess;
import com.jd.blockchain.utils.io.BytesUtils;
import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils;

/**
* 数据序列消息编码器
* @author zhangshuang
* @create 2019/4/18
* @since 1.0.0
*/
public class DataSequenceMsgEncoder {

private int heightSize = 8;
private int msgTypeSize = 1;

private DataSequenceWriter dsWriter;
private DataSequenceReader dsReader;

public DataSequenceMsgEncoder(DataSequenceWriter dsWriter, DataSequenceReader dsReader) {
this.dsWriter = dsWriter;
this.dsReader = dsReader;
}

/**
* 目前暂时考虑fromHeight与toHeight相同的情况,即每次只对一个高度的差异内容进行编码并响应
* 把消息编码成字节数组,再交给通信层传输
* @param msgType 数据序列状态复制消息类型
* @param id 数据序列唯一标识符
* @param fromHeight 差异元素起始高度
* @param toHeight 差异元素结束高度
*/
public byte[] encode(DSTransferProcess.DataSequenceMsgType msgType, String id, long fromHeight, long toHeight) {

try {

int dataLength;
int idSize = id.getBytes().length;
byte[] loadMessage = null;

// different encoding methods for different message types
// send by diff requester, diff requester encode
if (msgType == DSTransferProcess.DataSequenceMsgType.CMD_DSINFO_REQUEST) {

// CMD_DSINFO_REQUEST Message parts : 4 bytes total message size, 1 byte message type coe,
// 4 bytes id length, id content size bytes

dataLength = 4 + msgTypeSize + 4 + idSize;

loadMessage = new byte[dataLength];

System.arraycopy(BytesUtils.toBytes(dataLength), 0, loadMessage, 0, 4);
loadMessage[4] = msgType.CODE;
System.arraycopy(BytesUtils.toBytes(idSize), 0, loadMessage, 4 + msgTypeSize, 4);
System.arraycopy(id.getBytes(), 0, loadMessage, 4 + msgTypeSize + 4, idSize);
}
// send by diff requester, diff requester encode
else if (msgType == DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_REQUEST) {

// CMD_GETDSDIFF_REQUEST Message parts : 4 bytes total message size, 1 byte message type coe, 8 bytes from height,
// 8 bytes to height, 4 bytes id length, id content size bytes

dataLength = 4 + msgTypeSize + heightSize + heightSize + 4 + idSize;

loadMessage = new byte[dataLength];

System.arraycopy(BytesUtils.toBytes(dataLength), 0, loadMessage, 0, 4);
loadMessage[4] = msgType.CODE;
System.arraycopy(BytesUtils.toBytes(fromHeight), 0, loadMessage, 4 + msgTypeSize, heightSize);
System.arraycopy(BytesUtils.toBytes(toHeight), 0, loadMessage, 4 + msgTypeSize + heightSize, heightSize);
System.arraycopy(BytesUtils.toBytes(idSize), 0, loadMessage, 4 + msgTypeSize + heightSize + heightSize, 4);
System.arraycopy(id.getBytes(), 0, loadMessage, 4 + msgTypeSize + heightSize + heightSize + 4, idSize);
}
// send by diff provider, diff provider encode
else if (msgType == DSTransferProcess.DataSequenceMsgType.CMD_DSINFO_RESPONSE) {

// CMD_DSINFO_RESPONSE Message parts : 4 bytes total message size, 1 byte message type coe, 8 bytes data sequence local height,
// 4 bytes id length, id content size bytes

dataLength = 4 + msgTypeSize + heightSize + 4 + idSize;

loadMessage = new byte[dataLength];

System.arraycopy(BytesUtils.toBytes(dataLength), 0, loadMessage, 0, 4);
loadMessage[4] = msgType.CODE;
System.arraycopy(BytesUtils.toBytes(dsReader.getDSInfo(id).getHeight()), 0, loadMessage, 4 + msgTypeSize, heightSize);

System.arraycopy(BytesUtils.toBytes(idSize), 0, loadMessage, 4 + msgTypeSize + heightSize, 4);
System.arraycopy(id.getBytes(), 0, loadMessage, 4 + msgTypeSize + heightSize + 4, idSize);

}
// send by diff provider, diff provider encode
else if (msgType == DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_RESPONSE) {
if (fromHeight != toHeight) {
throw new IllegalArgumentException("Height parameter error!");
}

// CMD_DSINFO_RESPONSE Message parts : 4 bytes total message size, 1 byte message type coe,
// 4 bytes diffElem size, diff content size;

// 回调reader,获得这个高度上的所有差异的数据序列内容,并组织成DataSequenceElement结构
DataSequenceElement element = dsReader.getDSDiffContent(id, fromHeight);

byte[] diffElem = BinarySerializeUtils.serialize(element);

dataLength = 4 + msgTypeSize + 4 + diffElem.length;
loadMessage = new byte[dataLength];

System.arraycopy(BytesUtils.toBytes(dataLength), 0, loadMessage, 0, 4); //total size
loadMessage[4] = msgType.CODE; //msgType size
System.arraycopy(BytesUtils.toBytes(diffElem.length), 0, loadMessage, 4 + msgTypeSize, 4); // diffElem size
System.arraycopy(diffElem, 0, loadMessage, 4 + msgTypeSize + 4, diffElem.length); // diffElem bytes
}
else {
System.out.println("Unknown message type!");
throw new IllegalArgumentException();
}

return loadMessage;

} catch (Exception e) {
System.out.println("Error to encode message type : " + msgType + "!");
e.printStackTrace();
}

return null;
}

}

+ 186
- 0
source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSProcessManager.java View File

@@ -0,0 +1,186 @@
package com.jd.blockchain.statetransfer.process;

import com.jd.blockchain.statetransfer.DataSequenceElement;
import com.jd.blockchain.statetransfer.DataSequenceInfo;
import com.jd.blockchain.statetransfer.callback.DataSequenceReader;
import com.jd.blockchain.statetransfer.callback.DataSequenceWriter;
import com.jd.blockchain.statetransfer.comparator.DataSequenceComparator;
import com.jd.blockchain.statetransfer.message.DSDefaultMessageExecutor;
import com.jd.blockchain.statetransfer.result.DSInfoResponseResult;
import com.jd.blockchain.stp.communication.RemoteSession;
import com.jd.blockchain.stp.communication.callback.CallBackBarrier;
import com.jd.blockchain.stp.communication.callback.CallBackDataListener;
import com.jd.blockchain.stp.communication.manager.RemoteSessionManager;
import com.jd.blockchain.stp.communication.node.LocalNode;
import com.jd.blockchain.stp.communication.node.RemoteNode;

import java.net.InetSocketAddress;
import java.util.*;
import java.util.concurrent.*;

/**
* 数据序列状态复制过程管理器
* @author zhangshuang
* @create 2019/4/11
* @since 1.0.0
*
*/
public class DSProcessManager {

private static Map<String, DSTransferProcess> dSProcessMap = new ConcurrentHashMap<>();
private RemoteSession[] remoteSessions;
private long dsInfoResponseTimeout = 20000;
private ExecutorService writeExecutors = Executors.newFixedThreadPool(5);
private int returnCode = 0;

/**
* 启动一个指定数据序列的状态复制过程
* @param dsInfo 数据序列当前状态信息
* @param listener 本地监听者
* @param targets 目标结点
* @param dsWriter 差异请求者执行数据序列更新的执行器
* @param dsReader 差异响应者执行数据序列读取的执行器
* @return returnCode 执行结果码
*/
public int startDSProcess(DataSequenceInfo dsInfo, InetSocketAddress listener, InetSocketAddress[] targets, DataSequenceWriter dsWriter, DataSequenceReader dsReader) {

// create remote sessions manager, add listener
LocalNode listenNode = new LocalNode(listener.getHostName(), listener.getPort(), new DSDefaultMessageExecutor(dsReader, dsWriter));

RemoteSessionManager remoteSessionManager = new RemoteSessionManager(listenNode);

// data sequence transfer process life cycle start
DSTransferProcess dsTransferProcess = new DSTransferProcess(dsInfo, targets);
dsTransferProcess.setDSReader(dsReader);
dsTransferProcess.setDSWriter(dsWriter);
dsTransferProcess.setRemoteSessionManager(remoteSessionManager);

dSProcessMap.put(dsInfo.getId(), dsTransferProcess);

try {

//wait all listener nodes start
Thread.sleep(2000);

// start network connections with targets
dsTransferProcess.start();

//get all target sessions
remoteSessions = dsTransferProcess.getSessions();

// async message send process
CallBackBarrier callBackBarrier = CallBackBarrier.newCallBackBarrier(remoteSessions.length, dsInfoResponseTimeout);

// response message manage map
LinkedList<CallBackDataListener> dsInfoResponses = new LinkedList<>();

System.out.println("Async send CMD_DSINFO_REQUEST msg to targets will start!");
// step1: send get dsInfo request, then hold
for (RemoteSession remoteSession : remoteSessions) {
CallBackDataListener dsInfoResponse = dsTransferProcess.send(DSTransferProcess.DataSequenceMsgType.CMD_DSINFO_REQUEST, remoteSession, 0, 0, callBackBarrier);
dsInfoResponses.addLast(dsInfoResponse);
}

System.out.println("Wait CMD_DSINFO_RESPONSE msg from targets!");
// step2: collect get dsInfo response
LinkedList<CallBackDataListener> receiveResponses = new LinkedList<>();
if (callBackBarrier.tryCall()) {
Iterator<CallBackDataListener> iterator = dsInfoResponses.iterator();
while (iterator.hasNext()) {
CallBackDataListener receiveResponse = iterator.next();
if (receiveResponse.isDone()) {
receiveResponses.addLast(receiveResponse);
}
}
}

System.out.printf("%s:%d Compute diff info!\r\n", listener.getHostName(), listener.getPort());
// step3: process received responses
DSInfoResponseResult diffResult = dsTransferProcess.computeDiffInfo(receiveResponses);

System.out.printf("%s:%d Diff info result height = %x!\r\n", listener.getHostName(), listener.getPort(), diffResult.getMaxHeight());

// height diff
long diff = dsInfo.getHeight() - diffResult.getMaxHeight();

if (diff == 0 || diff > 0) {
System.out.printf("%s:%d No duplication is required!\r\n", listener.getHostName(), listener.getPort());
// no duplication is required, life cycle ends
// dsTransferProcess.close();
dSProcessMap.remove(dsInfo.getId());
return returnCode;

}
else {
System.out.printf("%s:%d Duplication is required!\r\n", listener.getHostName(), listener.getPort());
// step4: async send get data sequence diff request
// single step get diff
// async message send process
CallBackBarrier callBackBarrierDiff = CallBackBarrier.newCallBackBarrier((int)(diffResult.getMaxHeight() - dsInfo.getHeight()), dsInfoResponseTimeout);
LinkedList<CallBackDataListener> dsDiffResponses = new LinkedList<>();

RemoteSession responseSession = findResponseSession(diffResult.getMaxHeightRemoteNode(), remoteSessions);
System.out.println("Async send CMD_GETDSDIFF_REQUEST msg to targets will start!");

// step5: collect get data sequence diff response
for (long height = dsInfo.getHeight() + 1; height < diffResult.getMaxHeight() + 1; height++) {
CallBackDataListener dsDiffResponse = dsTransferProcess.send(DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_REQUEST, responseSession, height, height, callBackBarrierDiff);
dsDiffResponses.addLast(dsDiffResponse);
}
// 上述发送不合理,考虑一次性发送请求
System.out.println("Wait CMD_GETDSDIFF_RESPONSE msg from targets!");
LinkedList<byte[]> receiveDiffResponses = new LinkedList<>();
if (callBackBarrierDiff.tryCall()) {
for (int i = 0; i < dsDiffResponses.size(); i++) {
CallBackDataListener asyncFutureDiff = dsDiffResponses.get(i);
if (asyncFutureDiff.isDone()) {
receiveDiffResponses.addLast(asyncFutureDiff.getCallBackData());
}
}
}

System.out.printf("%s:%d ReceiveDiffResponses size = %d !\r\n", listener.getHostName(), listener.getPort(), receiveDiffResponses.size());
// step6: process data sequence diff response, update local data sequence state
System.out.println("Compute diff elements!");
ArrayList<DataSequenceElement> dataSequenceElements = dsTransferProcess.computeDiffElement(receiveDiffResponses.toArray(new byte[receiveDiffResponses.size()][]));
System.out.println("Update local data sequence!");
Collections.sort(dataSequenceElements, new DataSequenceComparator());
returnCode = dsWriter.updateDSInfo(dsInfo, dataSequenceElements.toArray(new DataSequenceElement[dataSequenceElements.size()]));

// data sequence transfer complete, close all sessions, end process life cycle
System.out.println("Close all sessions");
// dsTransferProcess.close();
dSProcessMap.remove(dsInfo.getId());
}


} catch (Exception e) {
e.printStackTrace();
}
return returnCode;
}

/**
* 根据远端结点找与远端结点建立的会话
* @param remoteNode 远端结点
* @param remoteSessions 本地维护的远端结点会话表
* @return 与远端结点对应的会话
*/
RemoteSession findResponseSession(RemoteNode remoteNode, RemoteSession[] remoteSessions) {
for (RemoteSession remoteSession : remoteSessions) {
if (remoteSession.remoteNode().equals(remoteNode)) {
return remoteSession;
}
}
return null;
}
/**
*
*
*/
// void setDSReader(DataSequenceReader reader) {
//
// }


}

+ 216
- 0
source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSTransferProcess.java View File

@@ -0,0 +1,216 @@
package com.jd.blockchain.statetransfer.process;

import com.jd.blockchain.statetransfer.DataSequenceElement;
import com.jd.blockchain.statetransfer.DataSequenceInfo;
import com.jd.blockchain.statetransfer.callback.DataSequenceReader;
import com.jd.blockchain.statetransfer.callback.DataSequenceWriter;
import com.jd.blockchain.statetransfer.message.DSMsgResolverFactory;
import com.jd.blockchain.statetransfer.message.DataSequenceLoadMessage;
import com.jd.blockchain.statetransfer.result.DSInfoResponseResult;
import com.jd.blockchain.stp.communication.RemoteSession;
import com.jd.blockchain.stp.communication.callback.CallBackBarrier;
import com.jd.blockchain.stp.communication.callback.CallBackDataListener;
import com.jd.blockchain.stp.communication.manager.RemoteSessionManager;
import com.jd.blockchain.stp.communication.node.RemoteNode;
import com.jd.blockchain.utils.IllegalDataException;

import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Map;

/**
* 数据序列状态复制过程
* @author zhangshuang
* @create 2019/4/11
* @since 1.0.0
*/
public class DSTransferProcess {

private InetSocketAddress[] targets;
private DataSequenceWriter dsWriter;
private DataSequenceReader dsReader;
private DataSequenceInfo dsInfo;
private RemoteSessionManager remoteSessionManager;
private RemoteSession[] remoteSessions;
private String id;

/**
* @param dsInfo 数据序列当前状态信息
* @param targets 目标结点
*/
public DSTransferProcess(DataSequenceInfo dsInfo, InetSocketAddress[] targets) {
this.dsInfo = dsInfo;
this.targets = targets;
this.id = dsInfo.getId();
}

/**
* @param dsWriter 差异请求者执行数据序列更新的执行器
* @return void
*/
public void setDSWriter(DataSequenceWriter dsWriter) {
this.dsWriter = dsWriter;
}

/**
* @param dsReader 差异响应者执行数据序列读取的执行器
* @return void
*/
public void setDSReader(DataSequenceReader dsReader) {
this.dsReader = dsReader;
}

/**
* @param remoteSessionManager 远端会话管理器
* @return void
*/
public void setRemoteSessionManager(RemoteSessionManager remoteSessionManager) {
this.remoteSessionManager = remoteSessionManager;
}


/**
*
* @return 数据序列标识符
*/
public String getId() {
return id;
}

/**
* @param msgType 数据序列差异请求消息类型
* @param remoteSession 目标结点对应的会话
* @param fromHeight 差异起始高度
* @param toHeight 差异结束高度
* @param callBackBarrier 异步回调
* @return 异步回调
*/
CallBackDataListener send(DataSequenceMsgType msgType, RemoteSession remoteSession, long fromHeight, long toHeight, CallBackBarrier callBackBarrier) {

byte[] loadMessage = DSMsgResolverFactory.getEncoder(dsWriter, dsReader).encode(msgType, id, fromHeight, toHeight);

return remoteSession.asyncRequest(new DataSequenceLoadMessage(loadMessage), callBackBarrier);
}

/**
* 计算数据序列差异元素数组
* @param diffArray 差异的字节数组
* @return 对差异字节数组的解码结果
*/
public ArrayList<DataSequenceElement> computeDiffElement(byte[][] diffArray) {

ArrayList<DataSequenceElement> dataSequenceElements = new ArrayList<>();

for (int i = 0 ; i < diffArray.length; i++) {
Object object = DSMsgResolverFactory.getDecoder(dsWriter, dsReader).decode(diffArray[i]);
if (object instanceof DataSequenceElement) {
dataSequenceElements.add((DataSequenceElement) object);
}
else {
throw new IllegalDataException("Unknown instance object!");
}
}

return dataSequenceElements;
}

/**
* 根据差异提供者响应的数据序列状态信息找到拥有最大数据序列高度的远端结点
* @param receiveResponses 数据序列差异请求者收到的远端结点状态的响应信息
* @return 得到远端数据序列的最大高度以及拥有者结点
*/
public DSInfoResponseResult computeDiffInfo(LinkedList<CallBackDataListener> receiveResponses) {
long maxHeight = 0;
RemoteNode maxHeightRemoteNode = null;

System.out.println("ComputeDiffInfo receiveResponses size = "+ receiveResponses.size());

try {
for (CallBackDataListener receiveResponse : receiveResponses) {
Object object = DSMsgResolverFactory.getDecoder(dsWriter, dsReader).decode(receiveResponse.getCallBackData());
if (object instanceof DataSequenceInfo) {
DataSequenceInfo dsInfo = (DataSequenceInfo) object;
long height = dsInfo.getHeight();
// sava max height and its remote node
if (maxHeight < height) {
maxHeight = height;
maxHeightRemoteNode = receiveResponse.remoteNode();
}
}
else {
throw new IllegalDataException("Unknown instance object!");
}

}
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}

return new DSInfoResponseResult(maxHeight, maxHeightRemoteNode);
}

/**
* 获取本复制过程维护的远端会话表
* @param
* @return 远端会话表数组
*/
public RemoteSession[] getSessions() {
return remoteSessions;
}

/**
* 关闭本复制过程维护的所有远端会话
* @return void
*/
public void close() {
for (RemoteSession session : remoteSessions) {
session.closeAll();
}
}

/**
* 建立与远端目标结点的连接,产生本地维护的远端会话表
* @return void
*/
public void start() {

RemoteNode[] remoteNodes = new RemoteNode[targets.length];

for (int i = 0; i < remoteNodes.length; i++) {
remoteNodes[i] = new RemoteNode(targets[i].getHostName(), targets[i].getPort());
}

remoteSessions = remoteSessionManager.newSessions(remoteNodes);
}


/**
* 数据序列状态传输使用的消息类型
*
*/
public enum DataSequenceMsgType {
CMD_DSINFO_REQUEST((byte) 0x1),
CMD_DSINFO_RESPONSE((byte) 0x2),
CMD_GETDSDIFF_REQUEST((byte) 0x3),
CMD_GETDSDIFF_RESPONSE((byte) 0x4),
;
public final byte CODE;

private DataSequenceMsgType(byte code) {
this.CODE = code;
}

public static DataSequenceMsgType valueOf(byte code) {
for (DataSequenceMsgType msgType : DataSequenceMsgType.values()) {
if (msgType.CODE == code) {
return msgType;
}
}
throw new IllegalArgumentException("Unsupported code[" + code + "] of msgType!");
}
}


}

+ 45
- 0
source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSDiffRequestResult.java View File

@@ -0,0 +1,45 @@
package com.jd.blockchain.statetransfer.result;

/**
* 数据序列差异提供者解码请求者"CMD_GETDSDIFF_REQUEST"消息时得到的结果
* @author zhangshuang
* @create 2019/4/18
* @since 1.0.0
*/
public class DSDiffRequestResult {

String id;
long fromHeight;
long toHeight;

public DSDiffRequestResult(String id ,long fromHeight, long toHeight) {
this.id = id;
this.fromHeight = fromHeight;
this.toHeight = toHeight;
}

public String getId() {
return id;
}

public long getFromHeight() {
return fromHeight;
}

public long getToHeight() {
return toHeight;
}

public void setId(String id) {
this.id = id;
}

public void setFromHeight(long fromHeight) {
this.fromHeight = fromHeight;
}

public void setToHeight(long toHeight) {
this.toHeight = toHeight;
}

}

+ 37
- 0
source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSInfoResponseResult.java View File

@@ -0,0 +1,37 @@
package com.jd.blockchain.statetransfer.result;

import com.jd.blockchain.stp.communication.node.RemoteNode;

/**
* 数据序列差异请求者解码提供者"CMD_DSINFO_RESPONSE"消息时得到的结果
* @author zhangshuang
* @create 2019/4/18
* @since 1.0.0
*/
public class DSInfoResponseResult {

long maxHeight;
RemoteNode maxHeightRemoteNode;

public DSInfoResponseResult(long maxHeight, RemoteNode maxHeightRemoteNode) {
this.maxHeight = maxHeight;
this.maxHeightRemoteNode = maxHeightRemoteNode;
}

public long getMaxHeight() {
return maxHeight;
}

public RemoteNode getMaxHeightRemoteNode() {
return maxHeightRemoteNode;
}

public void setMaxHeight(long maxHeight) {
this.maxHeight = maxHeight;
}

public void setMaxHeightRemoteNode(RemoteNode maxHeightRemoteNode) {
this.maxHeightRemoteNode = maxHeightRemoteNode;
}

}

+ 155
- 0
source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/StateTransferLayerTest.java View File

@@ -0,0 +1,155 @@
package test.com.jd.blockchain.statetransfer;

import com.jd.blockchain.statetransfer.DataSequence;
import com.jd.blockchain.statetransfer.DataSequenceElement;
import com.jd.blockchain.statetransfer.DataSequenceInfo;
import com.jd.blockchain.statetransfer.callback.DataSequenceReaderImpl;
import com.jd.blockchain.statetransfer.callback.DataSequenceWriterImpl;
import com.jd.blockchain.statetransfer.process.DSProcessManager;
import com.jd.blockchain.utils.codec.Base58Utils;
import org.junit.Before;
import org.junit.Test;

import java.net.InetSocketAddress;
import java.util.LinkedList;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* @author zhangshuang
* @create 2019/4/18
* @since 1.0.0
*/
public class StateTransferLayerTest {

private final int[] listenPorts = new int[]{9000, 9010, 9020, 9030};

private String localIp = "127.0.0.1";

private int DataSequenceNum = 1;

private int nodesNum = 4;

private byte[] idBytes = new byte[20];

private Random rand = new Random();

private String[] dataSequenceIds = new String[DataSequenceNum];

private InetSocketAddress[] remoteNodeIps = new InetSocketAddress[nodesNum];

private final ExecutorService threadPool = Executors.newFixedThreadPool(8);

private static LinkedList<DataSequence> dataSequencesPerNode = new LinkedList<>();

// 假定每个数据序列元素里有四条记录数据
private byte[][] dsElementDatas = new byte[4][];


@Before
public void init() {

// 产生两个唯一的数据序列Id标识
for (int i = 0; i < DataSequenceNum; i++) {

dataSequenceIds[i] = new String();
rand.nextBytes(idBytes);
dataSequenceIds[i] = Base58Utils.encode(idBytes);
}

// 准备好所有的远端结点,包括监听者
for (int i = 0; i < nodesNum; i++) {
remoteNodeIps[i] = new InetSocketAddress(localIp, listenPorts[i]);
}

// 为数据序列的每个高度准备好内容,为了方便测试,每个高度的内容设置为一致
for (int i = 0; i < dsElementDatas.length; i++) {
rand.nextBytes(idBytes);
dsElementDatas[i] = idBytes;
}

// 为结点准备数据序列
for (String id : dataSequenceIds) {
for (int i = 0; i < remoteNodeIps.length; i++) {
DataSequence dataSequence = new DataSequence(remoteNodeIps[i], id);

// 为数据序列的0,1,2高度添加内容
for (int j = 0; j < 3; j++) {
dataSequence.addElement(new DataSequenceElement(id, j, dsElementDatas));
}
dataSequencesPerNode.addLast(dataSequence);
}

// 把其中一个结点的数据序列与其他结点区别开来
for (int i = 0; i < dataSequencesPerNode.size(); i++) {
DataSequence dataSequence = dataSequencesPerNode.get(i);
if (dataSequence.getAddress().getPort() != listenPorts[0]) {
// 为数据序列的3,4高度添加内容
for (int j = 3; j < 5; j++) {
dataSequence.addElement(new DataSequenceElement(id, j, dsElementDatas));
}
}
}
}
}

InetSocketAddress[] getTargetNodesIp(InetSocketAddress listenIp, InetSocketAddress[] remoteNodeIps) {

// 获得除监听结点之外的其他远端结点
InetSocketAddress[] targets = new InetSocketAddress[remoteNodeIps.length - 1];
int j = 0;

for (int i = 0; i < remoteNodeIps.length; i++) {
if ((remoteNodeIps[i].getHostName().equals(listenIp.getHostName())) && (remoteNodeIps[i].getPort() == listenIp.getPort())) {
continue;
}
targets[j++] = new InetSocketAddress(remoteNodeIps[i].getHostName(), remoteNodeIps[i].getPort());
}

return targets;

}


DataSequence findDataSequence(String id, InetSocketAddress listenNodeAddr) {
for (DataSequence dataSequence : dataSequencesPerNode) {
if ((dataSequence.getAddress().getPort() == listenNodeAddr.getPort() && (dataSequence.getAddress().getHostName().equals(listenNodeAddr.getHostName()))
&& (dataSequence.getId().equals(id)))) {
return dataSequence;
}
}
return null;
}


@Test
public void test() {

CountDownLatch countDownLatch = new CountDownLatch(nodesNum);

for (String id : dataSequenceIds) {
for (int i = 0; i < nodesNum; i++) {
InetSocketAddress listenNode = remoteNodeIps[i];
threadPool.execute(() -> {
// 创建数据序列处理管理者实例
DSProcessManager dsProcessManager = new DSProcessManager();
DataSequence currDataSequence = findDataSequence(id, listenNode);
DataSequenceInfo dsInfo = currDataSequence.getDSInfo();
InetSocketAddress[] targets = getTargetNodesIp(listenNode, remoteNodeIps);
dsProcessManager.startDSProcess(dsInfo, listenNode, targets, new DataSequenceWriterImpl(currDataSequence), new DataSequenceReaderImpl(currDataSequence));
countDownLatch.countDown();
});
}
}

// 等待数据序列更新完成
try {
Thread.sleep(60000);
countDownLatch.await();
} catch (Exception e) {
e.printStackTrace();
}
}
}

+ 21
- 0
source/stp/pom.xml View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>jdchain-root</artifactId>
<groupId>com.jd.blockchain</groupId>
<version>0.9.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>stp</artifactId>
<packaging>pom</packaging>
<modules>
<module>stp-communication</module>
</modules>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save