Browse Source

Merge remote-tracking branch 'remotes/origin/develop' into feature/intf-contract

tags/1.0.0
zhaoguangwei 5 years ago
parent
commit
ce1fb2b4b0
100 changed files with 4563 additions and 2346 deletions
  1. +1
    -3
      source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartConsensusClient.java
  2. +10
    -10
      source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartMessageService.java
  3. +8
    -1
      source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartConsensusManageService.java
  4. +3
    -373
      source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java
  5. +0
    -19
      source/crypto/crypto-adv/pom.xml
  6. +68
    -46
      source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/mpc/MultiSum.java
  7. +0
    -98
      source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/KeyPair.java
  8. +0
    -165
      source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/KeyPairBuilder.java
  9. +51
    -0
      source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierKeyPairGenerator.java
  10. +101
    -0
      source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierPrivateKeyParameters.java
  11. +59
    -0
      source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierPublicKeyParameters.java
  12. +197
    -40
      source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierUtils.java
  13. +0
    -75
      source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PrivateKey.java
  14. +0
    -129
      source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PublicKey.java
  15. +13
    -19
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/EqualVerifyTest.java
  16. +16
    -21
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/IntCompareTest.java
  17. +55
    -72
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/MultiSumTest.java
  18. +0
    -58
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/DecryptionTest.java
  19. +0
    -90
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/HomomorphicPropertiesTest.java
  20. +0
    -43
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/JPaillierTest.java
  21. +0
    -44
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/KeyPairBuilderPrivateKeyTest.java
  22. +0
    -57
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/KeyPairBuilderPublicKeyTest.java
  23. +0
    -113
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/KeyPairBuilderTest.java
  24. +202
    -0
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/PaillierUtilsTest.java
  25. +0
    -124
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/ResolveTest.java
  26. +4
    -3
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ClassicCryptoService.java
  27. +107
    -16
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ECDSASignatureFunction.java
  28. +5
    -27
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ED25519SignatureFunction.java
  29. +2
    -1
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RIPEMD160HashFunction.java
  30. +142
    -24
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RSACryptoFunction.java
  31. +2
    -1
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/SHA256HashFunction.java
  32. +170
    -0
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/AESUtils.java
  33. +10
    -8
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/ECDSAUtils.java
  34. +25
    -0
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RIPEMD160Utils.java
  35. +513
    -2
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java
  36. +352
    -0
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/ECDSASignatureFunctionTest.java
  37. +488
    -0
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/RSACryptoFunctionTest.java
  38. +100
    -0
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/AESUtilsTest.java
  39. +78
    -2
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/ECDSAUtilsTest.java
  40. +72
    -0
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/ED25519UtilsTest.java
  41. +32
    -0
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RIPEMD160UtilsTest.java
  42. +426
    -0
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java
  43. +1
    -1
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/SHA256UtilsTest.java
  44. +3
    -3
      source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/BaseCryptoKey.java
  45. +1
    -0
      source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/PrivKey.java
  46. +5
    -1
      source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/PubKey.java
  47. +0
    -78
      source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/serialize/ByteArrayObjectDeserializer.java
  48. +0
    -63
      source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/serialize/ByteArrayObjectSerializer.java
  49. +5
    -13
      source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/service/sm/SM2CryptoFunction.java
  50. +25
    -4
      source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/utils/sm/SM4Utils.java
  51. +0
    -1
      source/crypto/crypto-sm/src/test/java/test/com/jd/blockchain/crypto/service/sm/SM2CyptoFunctionTest.java
  52. +42
    -70
      source/crypto/crypto-sm/src/test/java/test/com/jd/blockchain/crypto/utils/SM2UtilsTest.java
  53. +22
    -0
      source/deployment/deployment-peer/pom.xml
  54. +0
    -9
      source/deployment/deployment-peer/src/main/resources/assembly.xml
  55. +1
    -0
      source/gateway/.gitignore
  56. +23
    -1
      source/gateway/pom.xml
  57. +10
    -0
      source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryService.java
  58. +144
    -0
      source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceHandler.java
  59. +37
    -37
      source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceImpl.java
  60. +12
    -0
      source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java
  61. +5
    -22
      source/gateway/src/main/java/com/jd/blockchain/gateway/web/GatewayWebServerConfigurer.java
  62. +10
    -8
      source/gateway/src/main/resources/gateway.conf
  63. +2
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminAccount.java
  64. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdministration.java
  65. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerConfiguration.java
  66. +36
    -36
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerMetadata.java
  67. +24
    -24
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSetting.java
  68. +14
    -14
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java
  69. +2
    -8
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerRepositoryImpl.java
  70. +2
    -10
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionalEditor.java
  71. +6
    -16
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java
  72. +1
    -1
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerAdminAccountTest.java
  73. +2
    -2
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerMetaDataTest.java
  74. +36
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerMetadata.java
  75. +24
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerSetting.java
  76. +8
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java
  77. +101
    -0
      source/ledger/ledger-rpc/src/main/java/com/jd/blockchain/web/serializes/ByteArrayObjectJsonDeserializer.java
  78. +120
    -0
      source/ledger/ledger-rpc/src/main/java/com/jd/blockchain/web/serializes/ByteArrayObjectJsonSerializer.java
  79. +41
    -0
      source/ledger/ledger-rpc/src/main/java/com/jd/blockchain/web/serializes/ByteArrayObjectUtil.java
  80. +1
    -0
      source/peer/.gitignore
  81. +11
    -19
      source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java
  82. +2
    -19
      source/peer/src/main/java/com/jd/blockchain/peer/web/PeerWebServerConfigurer.java
  83. +19
    -0
      source/pom.xml
  84. +113
    -0
      source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/LedgerInitSettings.java
  85. +6
    -1
      source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java
  86. +11
    -0
      source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java
  87. +1
    -1
      source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/service/NodeSigningAppender.java
  88. +6
    -0
      source/sdk/sdk-client/pom.xml
  89. +32
    -5
      source/sdk/sdk-client/src/main/java/com/jd/blockchain/sdk/client/GatewayServiceFactory.java
  90. +0
    -13
      source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Query_Test_.java
  91. +30
    -1
      source/storage/storage-composite/pom.xml
  92. +88
    -64
      source/storage/storage-composite/src/main/java/com/jd/blockchain/storage/service/impl/composite/CompositeConnectionFactory.java
  93. +1
    -0
      source/storage/storage-composite/src/main/java/com/jd/blockchain/storage/service/impl/composite/CompositeStorageConfiguration.java
  94. +110
    -112
      source/storage/storage-composite/src/test/java/test/com/jd/blockchain/storage/service/impl/composite/CompositeConnectionFactoryTest.java
  95. +1
    -0
      source/storage/storage-redis/.gitignore
  96. +28
    -2
      source/storage/storage-redis/src/main/java/com/jd/blockchain/storage/service/impl/redis/RedisConnectionFactory.java
  97. +6
    -1
      source/storage/storage-rocksdb/src/main/java/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBConnection.java
  98. +6
    -1
      source/storage/storage-rocksdb/src/main/java/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBConnectionFactory.java
  99. +7
    -1
      source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/DbConnectionFactory.java
  100. +5
    -0
      source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryDBConnFactory.java

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

@@ -20,8 +20,6 @@ public class BftsmartConsensusClient implements ConsensusClient {

this.clientSettings = clientSettings;
this.gatewayId = clientSettings.getClientId();

connect();
}


@@ -45,7 +43,7 @@ public class BftsmartConsensusClient implements ConsensusClient {
}

@Override
public void connect() {
public synchronized void connect() {

//consensus client pool
BftsmartPeerProxyFactory peerProxyFactory = new BftsmartPeerProxyFactory((BftsmartClientSettings)clientSettings, gatewayId);


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

@@ -27,16 +27,16 @@ public class BftsmartMessageService implements MessageService {
AsynchServiceProxy asynchServiceProxy = null;
try {
asynchServiceProxy = asyncPeerProxyPool.borrowObject();
//0: Transaction msg, 1: Commitblock msg
byte[] msgType = BytesUtils.toBytes(0);
byte[] wrapMsg = new byte[message.length + 4];
System.arraycopy(message, 0, wrapMsg, 4, message.length);
System.arraycopy(msgType, 0, wrapMsg, 0, 4);
System.out.printf("BftsmartMessageService invokeOrdered time = %s, id = %s threadId = %s \r\n",
System.currentTimeMillis(), asynchServiceProxy.getProcessId(), Thread.currentThread().getId());
byte[] result = asynchServiceProxy.invokeOrdered(wrapMsg);
// //0: Transaction msg, 1: Commitblock msg
// byte[] msgType = BytesUtils.toBytes(0);
// byte[] wrapMsg = new byte[message.length + 4];
// System.arraycopy(message, 0, wrapMsg, 4, message.length);
// System.arraycopy(msgType, 0, wrapMsg, 0, 4);
//
// System.out.printf("BftsmartMessageService invokeOrdered time = %s, id = %s threadId = %s \r\n",
// System.currentTimeMillis(), asynchServiceProxy.getProcessId(), Thread.currentThread().getId());
byte[] result = asynchServiceProxy.invokeOrdered(message);
asyncFuture.complete(result);

} catch (Exception e) {


+ 8
- 1
source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartConsensusManageService.java View File

@@ -13,10 +13,16 @@ import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils;

public class BftsmartConsensusManageService implements ConsensusManageService {

public static final int CLIENT_RANGE = 100 * 1000;
public static final int GATEWAY_SIZE = 100;

public static final int CLIENT_SIZE_PER_GATEWAY = 1000;

public static final int CLIENT_RANGE = GATEWAY_SIZE * CLIENT_SIZE_PER_GATEWAY;

private BftsmartNodeServer nodeServer;

private int clientId;

private static final Lock authLock = new ReentrantLock();

public BftsmartConsensusManageService(BftsmartNodeServer nodeServer) {
@@ -41,6 +47,7 @@ public class BftsmartConsensusManageService implements ConsensusManageService {
try {
authLock.lock();
((BftsmartClientIncomingConfig) clientIncomingSettings).setClientId(clientId++);
clientId += CLIENT_SIZE_PER_GATEWAY;
} finally {
authLock.unlock();
}


+ 3
- 373
source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java View File

@@ -1,16 +1,13 @@
package com.jd.blockchain.consensus.bftsmart.service;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import bftsmart.tom.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jd.blockchain.consensus.ConsensusManageService;
import com.jd.blockchain.consensus.NodeSettings;
import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider;
@@ -26,13 +23,8 @@ import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.utils.PropertiesUtils;
import com.jd.blockchain.utils.concurrent.AsyncFuture;
import com.jd.blockchain.utils.io.BytesUtils;

import bftsmart.reconfiguration.util.HostsConfig;
import bftsmart.reconfiguration.util.TOMConfiguration;
import bftsmart.tom.MessageContext;
import bftsmart.tom.ReplyContext;
import bftsmart.tom.ReplyContextMessage;
import bftsmart.tom.ServiceReplica;
import bftsmart.tom.core.messages.TOMMessage;
import bftsmart.tom.server.defaultservices.DefaultRecoverable;

@@ -42,15 +34,9 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer

private List<StateHandle> stateHandles = new CopyOnWriteArrayList<>();

// private List<BatchConsensusListener> batchConsensusListeners = new LinkedList<>();

// private Map<ReplyContextMessage, AsyncFuture<byte[]>> replyContextMessages = new ConcurrentHashMap<>();

// TODO 暂不处理队列溢出问题
private ExecutorService notifyReplyExecutors = Executors.newSingleThreadExecutor();

// private ExecutorService sendCommitExecutors = Executors.newFixedThreadPool(2);

private volatile Status status = Status.STOPPED;

private final Object mutex = new Object();
@@ -81,28 +67,6 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer

private int serverId;

// private volatile String batchId = null;
//
//// private List<AsyncFuture<byte[]>> replyMessages ;
//
// private boolean leader_has_makedicision = false;
//
// private boolean commit_block_condition = false;
//
// private final AtomicLong txIndex = new AtomicLong();
//
// private final AtomicLong blockIndex = new AtomicLong();
//
// private static final AtomicInteger incrementNum = new AtomicInteger();
//
//// private final BlockingQueue<ActionRequest> txRequestQueue = new LinkedBlockingQueue();
//
// private final ExecutorService queueExecutor = Executors.newSingleThreadExecutor();
//
// private final ScheduledExecutorService timerEexecutorService = new ScheduledThreadPoolExecutor(10);
// private ServiceProxy peerProxy;


public BftsmartNodeServer() {

}
@@ -113,28 +77,12 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer
//used later
this.stateMachineReplicate = stateMachineReplicate;
this.messageHandle = messageHandler;
this.manageService = new BftsmartConsensusManageService(this);
createConfig();
serverId = findServerId();
initConfig(serverId, systemConfig, hostsConfig);
this.manageService = new BftsmartConsensusManageService(this);
}

//aim to send commit block message
// protected void createProxyClient() {
// BftsmartTopology topologyCopy = (BftsmartTopology) topology.copyOf();
//
// MemoryBasedViewStorage viewStorage = new MemoryBasedViewStorage(topologyCopy.getView());
//
// byte[] bytes = BinarySerializeUtils.serialize(tomConfig);
//
// TOMConfiguration decodeTomConfig = BinarySerializeUtils.deserialize(bytes);
//
// decodeTomConfig.setProcessId(0);
//
// peerProxy = new ServiceProxy(decodeTomConfig, viewStorage, null, null);
//
// }

protected int findServerId() {
int serverId = 0;

@@ -242,214 +190,12 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer
return appExecuteBatch(commands, msgCtxs, fromConsensus, null);
}

// private boolean checkLeaderId(MessageContext[] msgCtxs) {
// boolean result = false;
//
// for (int i = 0; i < msgCtxs.length - 1; i++) {
// if (msgCtxs[i].getLeader() != msgCtxs[i+1].getLeader())
// return result;
// }
//
// result = true;
//
// return result;
// }
//
// //普通消息处理
// private void normalMsgProcess(ReplyContextMessage replyContextMsg, byte[] msg, String realmName, String batchId) {
// AsyncFuture<byte[]> replyMsg = messageHandle.processOrdered(replyContextMsg.getMessageContext().getOperationId(), msg, realmName, batchId);
// replyContextMessages.put(replyContextMsg, replyMsg);
// }
//
// //结块消息处理
// private void commitMsgProcess(ReplyContextMessage replyContextMsg, String realmName, String batchId) {
// try{
// //receive messages before commitblock message, then execute commit
// if (replyContextMessages.size() != 0) {
// messageHandle.completeBatch(realmName, batchId);
// messageHandle.commitBatch(realmName, batchId);
// }
//
// // commit block msg need response too
// CompletableAsyncFuture<byte[]> asyncFuture = new CompletableAsyncFuture<>();
// TransactionResponse transactionRespHandle = new TransactionRespHandle(newBlockCommitRequest(),
// TransactionState.SUCCESS, TransactionState.SUCCESS);
//
// asyncFuture.complete(BinaryEncodingUtils.encode(transactionRespHandle, TransactionResponse.class));
// replyContextMessages.put(replyContextMsg, asyncFuture);
// }catch (Exception e){
// LOGGER.error("Error occurred on commit batch transactions, so the new block is canceled! --" + e.getMessage(), e);
// messageHandle.rollbackBatch(realmName, batchId, -1);
// }finally{
// this.batchId = null;
// }
// }

// private void sendCommitMessage() {
//
// HashDigest ledgerHash = new HashDigest(Base58Utils.decode(realmName));
//
// BlockchainKeyPair userKeyPeer = BlockchainKeyGenerator.getInstance().generate();
//
// TxContentBlob txContentBlob = new TxContentBlob(ledgerHash);
//
// byte[] reqBytes = BinaryEncodingUtils.encode(txContentBlob, TransactionContent.class);
//
// HashDigest reqHash = CryptoUtils.hash(CryptoAlgorithm.SHA256).hash(reqBytes);
//
// txContentBlob.setHash(reqHash);
//
// TxRequestMessage transactionRequest = new TxRequestMessage(txContentBlob);
//
// byte[] msg = BinaryEncodingUtils.encode(transactionRequest, TransactionRequest.class);
//
// byte[] type = BytesUtils.toBytes(1);
//
// byte[] wrapMsg = new byte[msg.length + 4];
//
// System.arraycopy(type, 0, wrapMsg, 0, 4);
// System.arraycopy(msg, 0, wrapMsg, 4, msg.length);
//
// peerProxy.invokeOrdered(wrapMsg);
//
// LOGGER.info("Send commit block msg success!");
// }

// private TransactionRequest newBlockCommitRequest() {
//
// HashDigest ledgerHash = new HashDigest(Base58Utils.decode(realmName));
//
// TxContentBlob txContentBlob = new TxContentBlob(ledgerHash);
//
// byte[] reqBytes = BinaryEncodingUtils.encode(txContentBlob, TransactionContent.class);
//
// HashDigest reqHash = CryptoUtils.hash(CryptoAlgorithm.SHA256).hash(reqBytes);
//
// txContentBlob.setHash(reqHash);
//
// TxRequestMessage transactionRequest = new TxRequestMessage(txContentBlob);
//
// return transactionRequest;
// }

// private void checkConsensusFinish() {
// BftsmartCommitBlockSettings commitBlockSettings = ((BftsmartServerSettings)serverSettings).getConsensusSettings().getCommitBlockSettings();
// int txSize = commitBlockSettings.getTxSizePerBlock();
// long maxDelay = commitBlockSettings.getMaxDelayMilliSecondsPerBlock();
//
// long currIndex = txIndex.incrementAndGet();
// if (currIndex == txSize) {
// txIndex.set(0);
// this.blockIndex.getAndIncrement();
// sendCommitExecutors.execute(()-> {
// sendCommitMessage();
// });
// } else if (currIndex == 1) {
//// System.out.printf("checkConsensusFinish schedule blockIndex = %s \r\n", this.blockIndex.get());
// timerEexecutorService.schedule(timeTask(this.blockIndex.get()), maxDelay, TimeUnit.MILLISECONDS);
// }
//
// return;
// }

// @Override
// public byte[][] appExecuteBatch(byte[][] commands, MessageContext[] msgCtxs, boolean fromConsensus, List<ReplyContextMessage> replyList) {
//
// if (!checkLeaderId(msgCtxs)) {
// throw new IllegalArgumentException();
// }
//
// boolean isLeader = (msgCtxs[0].getLeader() == getId());
//
// if (isLeader) {
// for (int i = 0; i < commands.length; i++) {
// byte[] wrapMsg = commands[i];
// byte[] type = new byte[4];
// byte[] msg= new byte[wrapMsg.length - 4];
//
// System.arraycopy(wrapMsg, 0, type, 0, 4);
// System.arraycopy(wrapMsg, 4, msg, 0, wrapMsg.length - 4);
//
// MessageContext messageContext = msgCtxs[i];
// ReplyContextMessage replyContextMessage = replyList.get(i);
// replyContextMessage.setMessageContext(messageContext);
//
// if (batchId == null) {
// batchId = messageHandle.beginBatch(realmName);
// }
//
// int msgType = BytesUtils.readInt(new ByteArrayInputStream(type));
//
// if (msgType == 0) {
//
// //only leader do it
// checkConsensusFinish();
// //normal message process
// normalMsgProcess(replyContextMessage, msg, realmName, batchId);
// }
// if (!leader_has_makedicision) {
// if (msgType == 1) {
// LOGGER.error("Error occurred on appExecuteBatch msg process, leader confilicting error!");
// }
//
// if (commit_block_condition) {
// leader_has_makedicision = true;
//
//// sendCommitExecutors.execute(() -> {
// commit_block_condition = false;
// LOGGER.info("Txcount execute commit block!");
// sendCommitMessage();
//// });
//
// }
// } else if (msgType == 1) {
// //commit block message
// commitMsgProcess(replyContextMessage, realmName, batchId);
// leader_has_makedicision = false;
// sendReplyMessage();
// }
// }
// } else {
// for (int i = 0; i < commands.length; i++) {
// byte[] wrapMsg = commands[i];
// byte[] type = new byte[4];
// byte[] msg= new byte[wrapMsg.length - 4];
//
// System.arraycopy(wrapMsg, 0, type, 0, 4);
// System.arraycopy(wrapMsg, 4, msg, 0, wrapMsg.length - 4);
//
// MessageContext messageContext = msgCtxs[i];
// ReplyContextMessage replyContextMessage = replyList.get(i);
// replyContextMessage.setMessageContext(messageContext);
//
// if (batchId == null) {
// batchId = messageHandle.beginBatch(realmName);
// }
//
// int msgType = BytesUtils.readInt(new ByteArrayInputStream(type));
//
// if (msgType == 0) {
// //normal message
// normalMsgProcess(replyContextMessage, msg, realmName, batchId);
// } else if (msgType == 1) {
// // commit block message
// commitMsgProcess(replyContextMessage, realmName, batchId);
// sendReplyMessage();
// }
// }
// }
//
// return null;
// }

@Override
public byte[][] appExecuteBatch(byte[][] commands, MessageContext[] msgCtxs, boolean fromConsensus, List<ReplyContextMessage> replyList) {

if (replyList == null || replyList.size() == 0) {
throw new IllegalArgumentException();
}


// todo 此部分需要重新改造
/**
* 默认BFTSmart接口提供的commands是一个或多个共识结果的顺序集合
@@ -481,52 +227,6 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer
if (!manageConsensusCmds.isEmpty()) {
blockAndReply(manageConsensusCmds, manageReplyMsgs);
}


//// if (!checkLeaderId(msgCtxs)) {
//// throw new IllegalArgumentException();
//// }
//
// if (replyList == null || replyList.size() == 0) {
// throw new IllegalArgumentException();
// }
//
// for (int i = 0; i < commands.length; i++) {
// byte[] wrapMsg = commands[i];
// byte[] type = new byte[4];
// byte[] msg= new byte[wrapMsg.length - 4];
// // batch messages, maybe in different consensus instance, leader also maybe different
// boolean isLeader = (msgCtxs[i].getLeader() == getId());
//
// System.arraycopy(wrapMsg, 0, type, 0, 4);
// System.arraycopy(wrapMsg, 4, msg, 0, wrapMsg.length - 4);
//
// MessageContext messageContext = msgCtxs[i];
// ReplyContextMessage replyContextMessage = replyList.get(i);
// replyContextMessage.setMessageContext(messageContext);
//
// if (batchId == null) {
// batchId = messageHandle.beginBatch(realmName);
// }
//
// int msgType = BytesUtils.readInt(new ByteArrayInputStream(type));
//
// if (msgType == 0) {
//
// //only leader do it
// if (isLeader) {
// checkConsensusFinish();
// }
// //normal message process
// normalMsgProcess(replyContextMessage, msg, realmName, batchId);
// }
// else if (msgType == 1) {
// //commit block message
// commitMsgProcess(replyContextMessage, realmName, batchId);
// sendReplyMessage();
// }
// }

return null;
}

@@ -574,46 +274,6 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer
});
}

// private void sendReplyMessage() {
// for (ReplyContextMessage msg: replyContextMessages.keySet()) {
// byte[] reply = replyContextMessages.get(msg).get();
// msg.setReply(reply);
// TOMMessage request = msg.getTomMessage();
// ReplyContext replyContext = msg.getReplyContext();
// request.reply = new TOMMessage(replyContext.getId(), request.getSession(), request.getSequence(),
// request.getOperationId(), msg.getReply(), replyContext.getCurrentViewId(),
// request.getReqType());
//
// if (replyContext.getNumRepliers() > 0) {
// bftsmart.tom.util.Logger.println("(ServiceReplica.receiveMessages) sending reply to "
// + request.getSender() + " with sequence number " + request.getSequence()
// + " and operation ID " + request.getOperationId() + " via ReplyManager");
// replyContext.getRepMan().send(request);
// } else {
// bftsmart.tom.util.Logger.println("(ServiceReplica.receiveMessages) sending reply to "
// + request.getSender() + " with sequence number " + request.getSequence()
// + " and operation ID " + request.getOperationId());
// replyContext.getReplier().manageReply(request, msg.getMessageContext());
// // cs.send(new int[]{request.getSender()}, request.reply);
// }
// }
// replyContextMessages.clear();
// }

// private Runnable timeTask(final long currBlockIndex) {
// Runnable task = () -> {
// boolean isAdd = this.blockIndex.compareAndSet(currBlockIndex, currBlockIndex + 1);
// if (isAdd) {
// LOGGER.info("TimerTask execute commit block! ");
// this.txIndex.set(0);
// timerEexecutorService.execute(()-> {
// sendCommitMessage();
// });
// }
// };
// return task;
// }

//notice
public byte[] getSnapshot() {
LOGGER.debug("------- GetSnapshot...[replica.id=" + this.getId() + "]");
@@ -623,9 +283,6 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer
for (StateHandle stateHandle : stateHandles) {
// TODO: 测试代码;
return stateHandle.takeSnapshot();

// byte[] state = stateHandle.takeSnapshot();
// BytesEncoding.writeInNormal(state, out);
}
return out.toByteArray();
}
@@ -693,33 +350,6 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer
}
}

// private static class ActionRequestExtend {
//
//
// ReplyContextMessage replyContextMessage;
//
// private byte[] message;
//
// private ActionRequest actionRequest;
//
// public ActionRequestExtend(byte[] message) {
// this.message = message;
// actionRequest = BinaryEncodingUtils.decode(message);
// }
//
// public byte[] getMessage() {
// return message;
// }
//
// public ReplyContextMessage getReplyContextMessage() {
// return replyContextMessage;
// }
//
// public ActionRequest getActionRequest() {
// return actionRequest;
// }
// }

enum Status {

STARTING,


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

@@ -27,20 +27,6 @@
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.6.2</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.6.2</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>net.i2p.crypto</groupId>
<artifactId>eddsa</artifactId>
@@ -52,11 +38,6 @@
<version>5.1.0</version>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>crypto-framework</artifactId>


+ 68
- 46
source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/mpc/MultiSum.java View File

@@ -2,85 +2,89 @@ package com.jd.blockchain.crypto.mpc;

import java.math.BigInteger;

import com.jd.blockchain.crypto.paillier.PaillierPublicKeyParameters;
import com.jd.blockchain.crypto.paillier.PaillierUtils;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.agreement.ECDHBasicAgreement;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;

import com.jd.blockchain.crypto.paillier.KeyPair;
import com.jd.blockchain.crypto.paillier.PaillierUtils;
import com.jd.blockchain.crypto.paillier.PublicKey;
import com.jd.blockchain.crypto.utils.sm.SM2Utils;
import com.jd.blockchain.crypto.utils.sm.SM3Utils;
import com.jd.blockchain.utils.io.BytesUtils;

public class MultiSum {

private ECPrivateKeyParameters ePrivKey;
private ECPublicKeyParameters ePubKey;
private ECCurve curve;
private ECDomainParameters domainParams;
private static byte[] ePrivKey;
private static byte[] ePubKey;
private static ECCurve curve;
private static ECDomainParameters domainParams;

public void generateEphemeralKeyPair(){
public static void generateEphemeralKeyPair(){
AsymmetricCipherKeyPair eKeyPair = SM2Utils.generateKeyPair();
this.ePrivKey = (ECPrivateKeyParameters) eKeyPair.getPrivate();
this.ePubKey = (ECPublicKeyParameters) eKeyPair.getPublic();
this.curve = SM2Utils.getCurve();
this.domainParams = SM2Utils.getDomainParams();

ECPrivateKeyParameters ecPrivKey = (ECPrivateKeyParameters) eKeyPair.getPrivate();
ECPublicKeyParameters ecPubKey= (ECPublicKeyParameters) eKeyPair.getPublic();
ePrivKey = bigIntegerToBytes(ecPrivKey.getD());
ePubKey = ecPubKey.getQ().getEncoded(false);
curve = SM2Utils.getCurve();
domainParams = SM2Utils.getDomainParams();
}

public BigInteger calculateAgreement(CipherParameters otherEPubKey){
public static byte[] calculateAgreement(byte[] otherEPubKey, byte[] ePrivKey){
ECDHBasicAgreement basicAgreement = new ECDHBasicAgreement();
basicAgreement.init(ePrivKey);
return basicAgreement.calculateAgreement(otherEPubKey);
ECPoint ePubKeyPoint = resolvePubKeyBytes(otherEPubKey);
ECPublicKeyParameters pubKey = new ECPublicKeyParameters(ePubKeyPoint, domainParams);
ECPrivateKeyParameters privateKey = new ECPrivateKeyParameters(new BigInteger(1,ePrivKey), domainParams);

basicAgreement.init(privateKey);
BigInteger agreement = basicAgreement.calculateAgreement(pubKey);
return bigIntegerToBytes(agreement);
}

public static BigInteger deriveShares(byte[] frontID, byte[] rearID, BigInteger agreement){
byte[] agreementBytes = agreement.toByteArray();
public static byte[] deriveShares(byte[] frontID, byte[] rearID, byte[] agreementBytes){
byte[] inputBytes = BytesUtils.concat(frontID,rearID,agreementBytes);
return new BigInteger(1,SM3Utils.hash(inputBytes));
return SM3Utils.hash(inputBytes);
}

public static BigInteger encryptBlindedMsg(PublicKey encKey, BigInteger msg, BigInteger frontShare, BigInteger rearShare){
return encKey.encrypt(msg.add(frontShare).subtract(rearShare).mod(encKey.getN()));
public static byte[] encryptBlindedMsg(byte[] paillierPubKey, int input, byte[] frontShare, byte[] rearShare){
BigInteger integer = BigInteger.valueOf(input);
BigInteger frontInteger = new BigInteger(1,frontShare);
BigInteger rearInteger = new BigInteger(1,rearShare);
PaillierPublicKeyParameters encKey = PaillierUtils.bytes2PubKey(paillierPubKey);
BigInteger modulus = encKey.getModulus();
BigInteger plaintext = integer.add(frontInteger).subtract(rearInteger).mod(modulus);
return PaillierUtils.encrypt(plaintext.toByteArray(),encKey);
}

public static BigInteger aggregateCiphertexts(PublicKey encKey, BigInteger... bigIntegersList){
BigInteger aggregatedCiphertext = BigInteger.ONE;
for (BigInteger entry : bigIntegersList) {
aggregatedCiphertext = aggregatedCiphertext.multiply(entry).mod(encKey.getnSquared());
}
return aggregatedCiphertext;
public static byte[] aggregateCiphertexts(byte[] paillierPubKey, byte[]... ciphertexts){
return PaillierUtils.add(paillierPubKey,ciphertexts);
}

public static BigInteger decrypt(KeyPair keyPair, BigInteger ciphertext){
return keyPair.decrypt(ciphertext);
public static byte[] decrypt(byte[] paillierPrivKey, byte[] ciphertext){
return PaillierUtils.decrypt(ciphertext,paillierPrivKey);
}

public ECPublicKeyParameters getEPubKey(){return ePubKey;}

public ECPrivateKeyParameters getEPrivKey(){return ePrivKey;}
public static byte[] getEPubKey(){return ePubKey;}

public static byte[] getEPrivKey(){return ePrivKey;}

public byte[] getEPubKeyBytes(){
byte[] ePubKeyBytes = new byte[65];
byte[] ePubKeyBytesX = ePubKey.getQ().getAffineXCoord().getEncoded();
byte[] ePubKeyBytesY = ePubKey.getQ().getAffineYCoord().getEncoded();
System.arraycopy(Hex.decode("04"),0,ePubKeyBytes,0,1);
System.arraycopy(ePubKeyBytesX,0,ePubKeyBytes,1,32);
System.arraycopy(ePubKeyBytesY,0,ePubKeyBytes,1+32,32);
return ePubKeyBytes;
}

public byte[] getEPrivKeyBytes(){
return PaillierUtils.BigIntegerToLBytes(ePrivKey.getD(),32);
}
// public byte[] getEPubKeyBytes(){
// byte[] ePubKeyBytes = new byte[65];
// byte[] ePubKeyBytesX = ePubKey.getQ().getAffineXCoord().getEncoded();
// byte[] ePubKeyBytesY = ePubKey.getQ().getAffineYCoord().getEncoded();
// System.arraycopy(Hex.decode("04"),0,ePubKeyBytes,0,1);
// System.arraycopy(ePubKeyBytesX,0,ePubKeyBytes,1,32);
// System.arraycopy(ePubKeyBytesY,0,ePubKeyBytes,1+32,32);
// return ePubKeyBytes;
// }
//
// public byte[] getEPrivKeyBytes(){
// return bigIntegerToBytes(ePrivKey.getD());
// }

public ECPublicKeyParameters resolveEPubKey(byte[] ePubKeyBytes){
byte[] ePubKeyX = new byte[32];
@@ -95,4 +99,22 @@ public class MultiSum {
return new ECPrivateKeyParameters(new BigInteger(1,ePrivKeyBytes),domainParams);
}

// To convert BigInteger to byte[] whose length is l
private static byte[] bigIntegerToBytes(BigInteger b){
byte[] tmp = b.toByteArray();
byte[] result = new byte[32];
if (tmp.length > result.length) {
System.arraycopy(tmp, tmp.length - result.length, result, 0, result.length);
}
else {
System.arraycopy(tmp,0,result,result.length-tmp.length,tmp.length);
}
return result;
}

// To retrieve the public key point from publicKey in byte array mode
private static ECPoint resolvePubKeyBytes(byte[] publicKey){
return curve.decodePoint(publicKey);
}

}

+ 0
- 98
source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/KeyPair.java View File

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

import java.math.BigInteger;
import java.util.List;

import com.jd.blockchain.utils.io.BytesUtils;

/**
* The MIT License (MIT)
*
* Copyright (c) 2014 Hendrik Kunert
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

/**
* A class that holds a pair of associated public and private keys.
*/
public class KeyPair {
private final PrivateKey privateKey;
private final PublicKey publicKey;
private final BigInteger upperBound;

public KeyPair(PrivateKey privateKey, PublicKey publicKey, BigInteger upperBound) {
this.privateKey = privateKey;
this.publicKey = publicKey;
this.upperBound = upperBound;
}

public KeyPair(byte[] privKeyBytes,byte[] pubKeyBytes,byte[] upperBoundBytes){
this.privateKey = new PrivateKey(privKeyBytes);
this.publicKey = new PublicKey(pubKeyBytes);
this.upperBound = new BigInteger(upperBoundBytes);
}

public KeyPair(byte[] keyPairBytes){
List<byte[]> list = PaillierUtils.split(keyPairBytes, "##KeyPair##".getBytes());
this.privateKey = new PrivateKey(list.get(0));
this.publicKey = new PublicKey(list.get(1));
this.upperBound = new BigInteger(list.get(2));
}

public PrivateKey getPrivateKey() {
return privateKey;
}

public PublicKey getPublicKey() {
return publicKey;
}

public BigInteger getUpperBound() { return upperBound; }

/**
* Decrypts the given ciphertext.
*
* @param c The ciphertext that should be decrypted.
* @return The corresponding plaintext. If an upper bound was given to {@link KeyPairBuilder},
* the result can also be negative. See {@link KeyPairBuilder#upperBound(BigInteger)} for details.
*/
public final BigInteger decrypt(BigInteger c) {

BigInteger n = publicKey.getN();
BigInteger nSquare = publicKey.getnSquared();
BigInteger lambda = privateKey.getLambda();

BigInteger u = privateKey.getPreCalculatedDenominator();

BigInteger p = c.modPow(lambda, nSquare).subtract(BigInteger.ONE).divide(n).multiply(u).mod(n);

if (upperBound != null && p.compareTo(upperBound) > 0) {
p = p.subtract(n);
}

return p;
}

public byte[] getUpperBoundBytes(){ return upperBound.toByteArray(); }

public byte[] getKeyPairBytes(){
return BytesUtils.concat(privateKey.getPrivKeyBytes(),"##KeyPair##".getBytes(),publicKey.getPubKeyBytes(),"##KeyPair##".getBytes(),upperBound.toByteArray());
}
}

+ 0
- 165
source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/KeyPairBuilder.java View File

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

import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Random;
/**
* The MIT License (MIT)
*
* Copyright (c) 2014 Hendrik Kunert
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

/**
* A class that is used for generating a pair of associated public and private
* keys.
*
* @see KeyPair
*/
public class KeyPairBuilder {

private int bits = 1024;

private int certainty = 0;

private Random rng;

private BigInteger upperBound;

/**
* Sets the size of the key to be created.
* <p>
* The default size is 1024 bits.
*
* @param bits The size of the key in bits.
* @return This instance of KeyPairBuilder for method chaining.
*/
public KeyPairBuilder bits(int bits) {
this.bits = bits;
return this;
}

/**
* See {@link BigInteger#BigInteger(int, int, Random)} for more details.
* <p>
* The default value is 0.
*
* @return This instance of KeyPairBuilder for method chaining.
*/
public KeyPairBuilder certainty(int certainty) {
this.certainty = certainty;
return this;
}

/**
* Sets the random number generator that is used for the generation of
* internally needed prime numbers.
* <p>
* The default is {@link SecureRandom}.
* <p>
* <b>Warning:</b>
* The change of this value affects the security of the whole cryptographic
* system.
*
* @param rng The random number generator that should be used instead of
* {@link SecureRandom}.
* @return This instance of KeyPairBuilder for method chaining.
*/
public KeyPairBuilder randomNumberGenerator(Random rng) {
this.rng = rng;
return this;
}

/**
* Sets an upper bound that is used for decrypting ciphertexts representing a negative value.
* <p>
* In most cases the upper bound should be the same as of the underlying number system -
* for example {@link Integer#MAX_VALUE}.
*
* @param b The upper bound.
* @return This instance of KeyPairBuilder for method chaining.
*/
public KeyPairBuilder upperBound(BigInteger b) {
this.upperBound = b;
return this;
}

/**
* Creates a pair of associated public and private keys.
*
* @return The pair of associated public and private keys.
*/
public KeyPair generateKeyPair() {
if (rng == null) {
rng = new SecureRandom();
}

BigInteger p, q;
int length = bits / 2;
if (certainty > 0) {
p = new BigInteger(length, certainty, rng);
q = new BigInteger(length, certainty, rng);
} else {
p = BigInteger.probablePrime(length, rng);
q = BigInteger.probablePrime(length, rng);
}

BigInteger n = p.multiply(q);
BigInteger nSquared = n.multiply(n);

BigInteger pMinusOne = p.subtract(BigInteger.ONE);
BigInteger qMinusOne = q.subtract(BigInteger.ONE);

BigInteger lambda = this.lcm(pMinusOne, qMinusOne);

BigInteger g;
BigInteger helper;

do {
g = new BigInteger(bits, rng);
helper = calculateL(g.modPow(lambda, nSquared), n);

} while (!helper.gcd(n).equals(BigInteger.ONE));

PublicKey publicKey = new PublicKey(n, nSquared, g, bits);
PrivateKey privateKey = new PrivateKey(lambda, helper.modInverse(n));

return new KeyPair(privateKey, publicKey, upperBound);

}

// TODO separate this somewhere
private BigInteger calculateL(BigInteger u, BigInteger n) {
BigInteger result = u.subtract(BigInteger.ONE);
result = result.divide(n);
return result;
}

// TODO add to own BigInteger extended class
private BigInteger lcm(BigInteger a, BigInteger b) {
BigInteger result;
BigInteger gcd = a.gcd(b);

result = a.abs().divide(gcd);
result = result.multiply(b.abs());

return result;
}
}

+ 51
- 0
source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierKeyPairGenerator.java View File

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

import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.math.Primes;
import org.bouncycastle.util.BigIntegers;

import java.math.BigInteger;
import java.security.SecureRandom;

/**
* @author zhanglin33
* @title: PaillierKeyPairGenerator
* @description: generator of paillier key pair
* @date 2019-04-30, 14:48
*/
public class PaillierKeyPairGenerator {

private static final int STRENGTH = 2048;

public AsymmetricCipherKeyPair generateKeyPair() {

int pLength = (STRENGTH + 1) / 2;
int qLength = STRENGTH - pLength;

BigInteger p;
BigInteger q;
BigInteger n;

do {
do {
SecureRandom pRandom = new SecureRandom();
p = BigIntegers.createRandomPrime(pLength, 1, pRandom);
} while (!isProbablePrime(p));
do {
SecureRandom qRandom = new SecureRandom();
q = BigIntegers.createRandomPrime(qLength, 1, qRandom);
} while (q.equals(p) || !isProbablePrime(p));
n = q.multiply(p);
} while (n.bitLength() != STRENGTH);

return new AsymmetricCipherKeyPair(new PaillierPublicKeyParameters(n), new PaillierPrivateKeyParameters(p,q));
}

// Primes class for FIPS 186-4 C.3 primality checking
private boolean isProbablePrime(BigInteger x)
{
int iterations = 3;
SecureRandom random = new SecureRandom();
return !Primes.hasAnySmallFactors(x) && Primes.isMRProbablePrime(x, random, iterations);
}
}

+ 101
- 0
source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierPrivateKeyParameters.java View File

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

import org.bouncycastle.crypto.params.AsymmetricKeyParameter;

import java.math.BigInteger;

import static org.bouncycastle.util.BigIntegers.ONE;

/**
* @author zhanglin33
* @title: PaillierPrivateKeyParameters
* @description: parameters about Paillier private key
* @date 2019-04-30, 14:39
*/
public class PaillierPrivateKeyParameters extends AsymmetricKeyParameter {

private BigInteger p;

private BigInteger q;

private BigInteger pSquared;

private BigInteger qSquared;

private BigInteger pInverse;

private BigInteger muP;

private BigInteger muQ;

public PaillierPrivateKeyParameters(BigInteger p, BigInteger q) {
super(true);
BigInteger generator = p.multiply(q).add(ONE);
this.p = p;
this.pSquared = p.multiply(p);
this.q = q;
this.qSquared = q.multiply(q);
this.pInverse = p.modInverse(q);
this.muP = hFunction(generator, p, pSquared);
this.muQ = hFunction(generator, q, qSquared);
}

public PaillierPrivateKeyParameters(BigInteger p, BigInteger pSquared, BigInteger q, BigInteger qSquared,
BigInteger pInverse, BigInteger muP, BigInteger muQ){
super(true);
this.p = p;
this.pSquared = pSquared;
this.q = q;
this.qSquared = qSquared;
this.pInverse = pInverse;
this.muP = muP;
this.muQ = muQ;
}


// mu = h(x) = (L(g^(x-1) mod x^2))^(-1) mod n
private BigInteger hFunction(BigInteger generator, BigInteger x, BigInteger xSquared) {
BigInteger phiX = lFunction(generator.modPow(x.subtract(ONE),xSquared),x);
return phiX.modInverse(x);
}

// L(x) = (x-1) / n
public BigInteger lFunction(BigInteger x, BigInteger n) {
return x.subtract(ONE).divide(n);
}

public BigInteger getP()
{
return p;
}

public BigInteger getPSquared()
{
return pSquared;
}

public BigInteger getQ()
{
return q;
}

public BigInteger getQSquared()
{
return qSquared;
}

public BigInteger getPInverse()
{
return pInverse;
}

public BigInteger getMuP()
{
return muP;
}

public BigInteger getMuQ()
{
return muQ;
}
}

+ 59
- 0
source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierPublicKeyParameters.java View File

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

import org.bouncycastle.crypto.params.AsymmetricKeyParameter;

import java.math.BigInteger;

import static org.bouncycastle.util.BigIntegers.ONE;

/**
* @author zhanglin33
* @title: PaillierPublicKeyParameters
* @description: parameters about Paillier public key
* @date 2019-04-30, 14:41
*/
public class PaillierPublicKeyParameters extends AsymmetricKeyParameter {

private BigInteger modulus;
private BigInteger modulusSquared;
private BigInteger generator;

public PaillierPublicKeyParameters(BigInteger modulus) {
super(false);
this.modulus = validate(modulus);
this.modulusSquared = modulus.multiply(modulus);
this.generator = modulus.add(ONE);
}

public BigInteger getModulus() {
return modulus;
}

public BigInteger getModulusSquared() {
return modulusSquared;
}

public BigInteger getGenerator() {
return generator;
}

private BigInteger validate(BigInteger modulus)
{
if ((modulus.intValue() & 1) == 0)
{
throw new IllegalArgumentException("The modulus is even!");
}

// the value is the product of the 132 smallest primes from 3 to 751
if (!modulus.gcd(new BigInteger("145188775577763990151158743208307020242261438098488931355057091965" +
"931517706595657435907891265414916764399268423699130577757433083166" +
"651158914570105971074227669275788291575622090199821297575654322355" +
"049043101306108213104080801056529374892690144291505781966373045481" +
"8359472391642885328171302299245556663073719855")).equals(ONE))
{
throw new IllegalArgumentException("The modulus has a small prime factor!");
}

return modulus;
}
}

+ 197
- 40
source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierUtils.java View File

@@ -1,16 +1,200 @@
package com.jd.blockchain.crypto.paillier;

import com.jd.blockchain.utils.io.BytesUtils;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.security.SecureRandom;
import static org.bouncycastle.util.BigIntegers.ONE;

/**
* @author zhanglin33
* @title: PaillierUtils
* @description: encryption, decryption, homomorphic addition and scalar multiplication in Paillier algorithm
* @date 2019-04-30, 14:49
*/
public class PaillierUtils {

// To convert BigInteger to byte[] whose length is l
public static byte[] BigIntegerToLBytes(BigInteger b, int l){
private static final int MODULUS_LENGTH = 256;
private static final int MODULUSSQUARED_LENGTH = 512;

private static final int P_LENGTH = 128;
private static final int PSQUARED_LENGTH = 256;
private static final int Q_LENGTH = 128;
private static final int QSQUARED_LENGTH = 256;
private static final int PINVERSE_LENGTH = 128;
private static final int MUP_LENGTH = 128;
private static final int MUQ_LENGTH = 128;

private static final int PRIVKEY_LENGTH = P_LENGTH + PSQUARED_LENGTH + Q_LENGTH + QSQUARED_LENGTH
+ PINVERSE_LENGTH + MUP_LENGTH + MUQ_LENGTH;

public static AsymmetricCipherKeyPair generateKeyPair(){
PaillierKeyPairGenerator generator = new PaillierKeyPairGenerator();
return generator.generateKeyPair();
}

public static byte[] encrypt(byte[] plainBytes, byte[] publicKey) {
PaillierPublicKeyParameters pubKeyParams = bytes2PubKey(publicKey);
return encrypt(plainBytes, pubKeyParams);
}

public static byte[] encrypt(byte[] plainBytes, PaillierPublicKeyParameters pubKeyParams) {
SecureRandom random = new SecureRandom();
return encrypt(plainBytes, pubKeyParams, random);
}

// c = g^m * r^n mod n^2 = (1+n)^m * r^n mod n^2 = (1 + n*m mod n^2) * r^n mod n^2
public static byte[] encrypt(byte[] plainBytes, PaillierPublicKeyParameters pubKeyParams, SecureRandom random){

BigInteger n = pubKeyParams.getModulus();
BigInteger nSquared = pubKeyParams.getModulusSquared();

BigInteger m = new BigInteger(1,plainBytes);
BigInteger r = new BigInteger(n.bitLength(), random);

BigInteger rawCiphertext = n.multiply(m).add(ONE).mod(nSquared);
BigInteger c = r.modPow(n, nSquared).multiply(rawCiphertext).mod(nSquared);

return bigIntegerToBytes(c, MODULUSSQUARED_LENGTH);
}


public static byte[] decrypt(byte[] cipherBytes, byte[] privateKey) {
PaillierPrivateKeyParameters privKeyParams = bytes2PrivKey(privateKey);
return decrypt(cipherBytes,privKeyParams);
}
// m mod p = L(c^(p-1) mod p^2) * muP mod p
// m mod q = L(c^(q-1) mod q^2) * muQ mod q
// m = (m mod p) * (1/q mod p) * q + (m mod q) * (1/p mod q) * p
// = ((m mod q)-(m mod p)) * (1/p mod q) mod q * p + (m mod p)
public static byte[] decrypt(byte[] cipherBytes, PaillierPrivateKeyParameters privKeyParams){

BigInteger cihphertext = new BigInteger(1, cipherBytes);

BigInteger p = privKeyParams.getP();
BigInteger pSquared = privKeyParams.getPSquared();
BigInteger q = privKeyParams.getQ();
BigInteger qSquared = privKeyParams.getQSquared();
BigInteger pInverse = privKeyParams.getPInverse();
BigInteger muP = privKeyParams.getMuP();
BigInteger muQ = privKeyParams.getMuQ();

BigInteger mModP =
privKeyParams.lFunction(cihphertext.modPow(p.subtract(ONE),pSquared),p).multiply(muP).mod(p);
BigInteger mModQ =
privKeyParams.lFunction(cihphertext.modPow(q.subtract(ONE),qSquared),q).multiply(muQ).mod(q);

BigInteger midValue = mModQ.subtract(mModP).multiply(pInverse).mod(q);
BigInteger m = midValue.multiply(p).add(mModP);

return m.toByteArray();
}


public static byte[] pubKey2Bytes(PaillierPublicKeyParameters pubKeyParams) {
BigInteger n = pubKeyParams.getModulus();
return bigIntegerToBytes(n, MODULUS_LENGTH);
}

public static PaillierPublicKeyParameters bytes2PubKey(byte[] publicKey) {

if (publicKey.length != MODULUS_LENGTH) {
throw new IllegalArgumentException("publicKey's length does not meet algorithm's requirement!");
}

BigInteger n = new BigInteger(1, publicKey);
return new PaillierPublicKeyParameters(n);
}


public static byte[] privKey2Bytes(PaillierPrivateKeyParameters privKeyParams) {

BigInteger p = privKeyParams.getP();
BigInteger pSquared = privKeyParams.getPSquared();
BigInteger q = privKeyParams.getQ();
BigInteger qSquared = privKeyParams.getQSquared();
BigInteger pInverse = privKeyParams.getPInverse();
BigInteger muP = privKeyParams.getMuP();
BigInteger muQ = privKeyParams.getMuQ();

byte[] pBytes = bigIntegerToBytes(p, P_LENGTH);
byte[] pSquaredBytes = bigIntegerToBytes(pSquared, PSQUARED_LENGTH);
byte[] qBytes = bigIntegerToBytes(q, Q_LENGTH);
byte[] qSquaredBytes = bigIntegerToBytes(qSquared, QSQUARED_LENGTH);
byte[] pInverseBytes = bigIntegerToBytes(pInverse, PINVERSE_LENGTH);
byte[] muPBytes = bigIntegerToBytes(muP, MUP_LENGTH);
byte[] muQBytes = bigIntegerToBytes(muQ, MUQ_LENGTH);

return BytesUtils.concat(pBytes,pSquaredBytes,qBytes,qSquaredBytes,pInverseBytes,muPBytes,muQBytes);
}

public static PaillierPrivateKeyParameters bytes2PrivKey(byte[] privateKey) {

if (privateKey.length != PRIVKEY_LENGTH) {
throw new IllegalArgumentException("privateKey's length does not meet algorithm's requirement!");
}

byte[] pBytes = new byte[P_LENGTH];
byte[] pSquaredBytes = new byte[PSQUARED_LENGTH];
byte[] qBytes = new byte[Q_LENGTH];
byte[] qSquaredBytes = new byte[QSQUARED_LENGTH];
byte[] pInverseBytes = new byte[PINVERSE_LENGTH];
byte[] muPBytes = new byte[MUP_LENGTH];
byte[] muQBytes = new byte[MUQ_LENGTH];

split(privateKey,pBytes,pSquaredBytes,qBytes,qSquaredBytes,pInverseBytes,muPBytes,muQBytes);

BigInteger p = new BigInteger(1, pBytes);
BigInteger pSquared = new BigInteger(1, pSquaredBytes);
BigInteger q = new BigInteger(1, qBytes);
BigInteger qSquared = new BigInteger(1, qSquaredBytes);
BigInteger pInverse = new BigInteger(1, pInverseBytes);
BigInteger muP = new BigInteger(1, muPBytes);
BigInteger muQ = new BigInteger(1, muQBytes);

return new PaillierPrivateKeyParameters(p,pSquared,q,qSquared,pInverse,muP,muQ);
}

public static byte[] add(byte[] publicKey, byte[]... ciphertexts) {
PaillierPublicKeyParameters pubKeyParams = bytes2PubKey(publicKey);
return add(pubKeyParams,ciphertexts);
}

public static byte[] add(PaillierPublicKeyParameters pubKeyParams, byte[]... ciphertexts) {

BigInteger result = ONE;
BigInteger multiplier;
BigInteger nSquared = pubKeyParams.getModulusSquared();
for (byte[] each: ciphertexts) {
multiplier = new BigInteger(1, each);
result = result.multiply(multiplier).mod(nSquared);
}

return bigIntegerToBytes(result, MODULUSSQUARED_LENGTH);
}

public static byte[] scalarMultiply(byte[] publicKey, byte[] cipherBytes, long scalar) {
PaillierPublicKeyParameters pubKeyParams = bytes2PubKey(publicKey);
return scalarMultiply(pubKeyParams,cipherBytes,scalar);
}

public static byte[] scalarMultiply(PaillierPublicKeyParameters pubKeyParams, byte[] cipherBytes, long scalar) {

BigInteger nSquared = pubKeyParams.getModulusSquared();
BigInteger cihertext = new BigInteger(1, cipherBytes);
BigInteger exponent = BigInteger.valueOf(scalar);

BigInteger result = cihertext.modPow(exponent,nSquared);

return bigIntegerToBytes(result, MODULUSSQUARED_LENGTH);
}

// To convert BigInteger to byte array in specified size
private static byte[] bigIntegerToBytes(BigInteger b, int bytesSize){
byte[] tmp = b.toByteArray();
byte[] result = new byte[l];
byte[] result = new byte[bytesSize];
if (tmp.length > result.length) {
System.arraycopy(tmp, tmp.length - result.length, result, 0, result.length);
}
@@ -20,42 +204,15 @@ public class PaillierUtils {
return result;
}

public static byte[] intToBytes(int i){
byte[] result = new byte[4];
result[0] = (byte) (i >> 24);
result[1] = (byte) (i >> 16);
result[2] = (byte) (i >> 8);
result[3] = (byte) (i);
return result;
}

public static int bytesToInt(byte[] array){
int result = 0;
result |= ((array[0] & 0xFF) << 24);
result |= ((array[1] & 0xFF) << 16);
result |= ((array[2] & 0xFF) << 8);
result |= ((array[3] & 0xFF));
return result;
}
private static void split(byte[] src, byte[]... bytesList) {

public static List<byte[]> split(byte[] array, byte[] delimiter) {
List<byte[]> byteArrays = new LinkedList<>();
if (delimiter.length == 0) {
return byteArrays;
}
int begin = 0;

outer:
for (int i = 0; i < array.length - delimiter.length + 1; i++) {
for (int j = 0; j < delimiter.length; j++) {
if (array[i + j] != delimiter[j]) {
continue outer;
}
int srcPos = 0;
for (byte[] each: bytesList){
System.arraycopy(src,srcPos,each,0,each.length);
srcPos += each.length;
if (srcPos >= src.length){
break;
}
byteArrays.add(Arrays.copyOfRange(array, begin, i));
begin = i + delimiter.length;
}
byteArrays.add(Arrays.copyOfRange(array, begin, array.length));
return byteArrays;
}
}

+ 0
- 75
source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PrivateKey.java View File

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

import java.math.BigInteger;
import java.util.List;
/**
* The MIT License (MIT)
*
* Copyright (c) 2014 Hendrik Kunert
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

import com.jd.blockchain.utils.io.BytesUtils;

/**
* A class that represents the private part of the Paillier key pair.
*/
public class PrivateKey {

private final BigInteger lambda;
private final BigInteger preCalculatedDenominator;

public PrivateKey(BigInteger lambda, BigInteger preCalculatedDenominator) {
this.lambda = lambda;

this.preCalculatedDenominator = preCalculatedDenominator;
}

public PrivateKey(byte[] lambdaBytes, byte[] preCalculatedDenominatorBytes){
this.lambda = new BigInteger(lambdaBytes);
this.preCalculatedDenominator = new BigInteger(preCalculatedDenominatorBytes);
}

public PrivateKey(byte[] privKeyBytes){
List<byte[]> list = PaillierUtils.split(privKeyBytes, "##PrivateKey##".getBytes());
this.lambda = new BigInteger(list.get(0));
this.preCalculatedDenominator = new BigInteger(list.get(1));
}

public BigInteger getLambda() {
return lambda;
}

public BigInteger getPreCalculatedDenominator() {
return preCalculatedDenominator;
}

public byte[] getLambdaBytes(){
return lambda.toByteArray();
}

public byte[] getPreCalculatedDenominatorBytes(){
return preCalculatedDenominator.toByteArray();
}

public byte[] getPrivKeyBytes(){
return BytesUtils.concat(getLambdaBytes(),"##PrivateKey##".getBytes(),getPreCalculatedDenominatorBytes());
}
}

+ 0
- 129
source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PublicKey.java View File

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

import java.math.BigInteger;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
/**
* The MIT License (MIT)
*
* Copyright (c) 2014 Hendrik Kunert
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

import com.jd.blockchain.utils.io.ByteArray;
import com.jd.blockchain.utils.io.BytesUtils;

/**
* A class that represents the public part of the Paillier key pair.
* <p>
* As in all asymmetric cryptographic systems it is responsible for the
* encryption.
* <p>
* Additional instructions for the decryption can be found on {@link KeyPair}.
*
* @see KeyPair
*/
public class PublicKey {
private final int bits;
private final BigInteger n;
private final BigInteger nSquared;
private final BigInteger g;

public PublicKey(BigInteger n, BigInteger nSquared, BigInteger g, int bits) {
this.n = n;
this.nSquared = nSquared;
this.bits = bits;
this.g = g;
}

public PublicKey(byte[] nBytes, byte[] nSquaredBytes, byte[] gBytes, byte[] bitsBytes) {
this.n = new BigInteger(nBytes);
this.nSquared = new BigInteger(nSquaredBytes);
this.g = new BigInteger(gBytes);
this.bits = PaillierUtils.bytesToInt(bitsBytes);
}

public PublicKey(byte[] pubKeyBytes){
List<byte[]> list = PaillierUtils.split(pubKeyBytes, "##PublicKey##".getBytes());
this.n = new BigInteger(list.get(0));
this.nSquared = new BigInteger(list.get(1));
this.g = new BigInteger(list.get(2));
this.bits = PaillierUtils.bytesToInt(list.get(3));
}


public int getBits() {
return bits;
}

public BigInteger getN() {
return n;
}

public BigInteger getnSquared() {
return nSquared;
}

public BigInteger getG() {
return g;
}

/**
* Encrypts the given plaintext.
*
* @param m The plaintext that should be encrypted.
* @return The corresponding ciphertext.
*/
public final BigInteger encrypt(BigInteger m) {

BigInteger r;
do {
r = new BigInteger(bits, new Random());
} while (r.compareTo(n) >= 0);

BigInteger result = g.modPow(m, nSquared);
BigInteger x = r.modPow(n, nSquared);

result = result.multiply(x);
result = result.mod(nSquared);

return result;
}

public byte[] getBitsBytes(){
return PaillierUtils.intToBytes(bits);
}

public byte[] getNBytes(){ return n.toByteArray(); }

public byte[] getNSquaredBytes(){
return nSquared.toByteArray();
}

public byte[] getGBytes(){
return g.toByteArray();
}

public byte[] getPubKeyBytes(){
return BytesUtils.concat(getNBytes(),"##PublicKey##".getBytes(),getNSquaredBytes(),"##PublicKey##".getBytes(),getGBytes(),"##PublicKey##".getBytes(),getBitsBytes());
}
}


+ 13
- 19
source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/EqualVerifyTest.java View File

@@ -39,35 +39,29 @@ public class EqualVerifyTest {
byte[] responderOutput;
boolean isEqual;

int i;

for (i = 0; i < 1000; i++) {
sponsorInput = 666;
responderInput = 666;

sponsorInput = 666;
responderInput = 666;

sponsorOutput = EqualVerify.sponsor(sponsorInput,sponsorEPubKeyBytes);
responderOutput = EqualVerify.responder(responderInput,sponsorOutput,
sponsorOutput = EqualVerify.sponsor(sponsorInput,sponsorEPubKeyBytes);
responderOutput = EqualVerify.responder(responderInput,sponsorOutput,
responderEPubKeyBytes,responderEPrivKeyBytes);

isEqual = EqualVerify.sponsorCheck(sponsorInput,responderOutput,sponsorEPrivKeyBytes);
isEqual = EqualVerify.sponsorCheck(sponsorInput,responderOutput,sponsorEPrivKeyBytes);

assertTrue(isEqual);
}
assertTrue(isEqual);

for (i = 0; i < 1000; i++){

sponsorInput = 666;
responderInput = 667;
sponsorInput = 666;
responderInput = 667;

sponsorOutput = EqualVerify.sponsor(sponsorInput,sponsorEPubKeyBytes);
responderOutput = EqualVerify.responder(responderInput,sponsorOutput,
sponsorOutput = EqualVerify.sponsor(sponsorInput,sponsorEPubKeyBytes);
responderOutput = EqualVerify.responder(responderInput,sponsorOutput,
responderEPubKeyBytes,responderEPrivKeyBytes);

isEqual = EqualVerify.sponsorCheck(sponsorInput,responderOutput,sponsorEPrivKeyBytes);
isEqual = EqualVerify.sponsorCheck(sponsorInput,responderOutput,sponsorEPrivKeyBytes);

assertTrue(!isEqual);
}
}
assertTrue(!isEqual);

}
}

+ 16
- 21
source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/IntCompareTest.java View File

@@ -25,26 +25,21 @@ public class IntCompareTest {
byte[][] cipherArray;
byte[][] aggregatedCipherArray;
int output;
int i;

for (i = 0; i < 1000; i++) {
int sponsorInput = 10000;
int responderInput = 9999;

cipherArray = IntCompare.sponsor(sponsorInput, pubKeyBytes);
aggregatedCipherArray = IntCompare.responder(responderInput, cipherArray, pubKeyBytes);
output = IntCompare.sponsorOutput(aggregatedCipherArray, privKeyBytes);
assertEquals(1, output);
}

for (i = 0; i < 1000; i++) {
int sponsorInput = 10000;
int responderInput = 19999;

cipherArray = IntCompare.sponsor(sponsorInput, pubKeyBytes);
aggregatedCipherArray = IntCompare.responder(responderInput, cipherArray, pubKeyBytes);
output = IntCompare.sponsorOutput(aggregatedCipherArray, privKeyBytes);
assertEquals(0, output);
}

int sponsorInput = 10000;
int responderInput = 9999;

cipherArray = IntCompare.sponsor(sponsorInput, pubKeyBytes);
aggregatedCipherArray = IntCompare.responder(responderInput, cipherArray, pubKeyBytes);
output = IntCompare.sponsorOutput(aggregatedCipherArray, privKeyBytes);
assertEquals(1, output);

sponsorInput = 10000;
responderInput = 19999;

cipherArray = IntCompare.sponsor(sponsorInput, pubKeyBytes);
aggregatedCipherArray = IntCompare.responder(responderInput, cipherArray, pubKeyBytes);
output = IntCompare.sponsorOutput(aggregatedCipherArray, privKeyBytes);
assertEquals(0, output);
}
}

+ 55
- 72
source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/MultiSumTest.java View File

@@ -1,105 +1,88 @@
package test.com.jd.blockchain.crypto.mpc;

import com.jd.blockchain.crypto.mpc.MultiSum;
import com.jd.blockchain.crypto.paillier.KeyPair;
import com.jd.blockchain.crypto.paillier.KeyPairBuilder;
import com.jd.blockchain.crypto.paillier.PublicKey;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.util.encoders.Hex;
import org.junit.Before;
import com.jd.blockchain.crypto.paillier.PaillierPrivateKeyParameters;
import com.jd.blockchain.crypto.paillier.PaillierPublicKeyParameters;
import com.jd.blockchain.crypto.paillier.PaillierUtils;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.junit.Test;

import java.math.BigInteger;

import static org.junit.Assert.*;

public class MultiSumTest {

private KeyPair keyPair;
private PublicKey encKey;

@Before
public void init() {
KeyPairBuilder keygen = new KeyPairBuilder();
keyPair = keygen.generateKeyPair();
encKey = keyPair.getPublicKey();
}
@Test
public void testMultiSum() {

MultiSum instance1 = new MultiSum();
MultiSum instance2 = new MultiSum();
MultiSum instance3 = new MultiSum();
AsymmetricCipherKeyPair keyPair = PaillierUtils.generateKeyPair();
PaillierPublicKeyParameters pubKeyParams = (PaillierPublicKeyParameters) keyPair.getPublic();
PaillierPrivateKeyParameters privKeyParams = (PaillierPrivateKeyParameters) keyPair.getPrivate();

BigInteger value1 = BigInteger.valueOf(6);
BigInteger value2 = BigInteger.valueOf(60);
BigInteger value3 = BigInteger.valueOf(600);
BigInteger expectedSum = BigInteger.valueOf(666);
byte[] encKey = PaillierUtils.pubKey2Bytes(pubKeyParams);
byte[] decKey = PaillierUtils.privKey2Bytes(privKeyParams);

int int1 = 6;
int int2 = 60;
int int3 = 600;
int sum = 666;

byte[] id1 = "1".getBytes();
byte[] id2 = "2".getBytes();
byte[] id3 = "3".getBytes();

instance1.generateEphemeralKeyPair();
instance2.generateEphemeralKeyPair();
instance3.generateEphemeralKeyPair();
MultiSum.generateEphemeralKeyPair();
byte[] ePubKey1 = MultiSum.getEPubKey();
byte[] ePrivKey1 = MultiSum.getEPrivKey();

ECPublicKeyParameters ePubKey1 = instance1.getEPubKey();
ECPublicKeyParameters ePubKey2 = instance2.getEPubKey();
ECPublicKeyParameters ePubKey3 = instance3.getEPubKey();
MultiSum.generateEphemeralKeyPair();
byte[] ePubKey2 = MultiSum.getEPubKey();
byte[] ePrivKey2 = MultiSum.getEPrivKey();

BigInteger sk12 = instance1.calculateAgreement(ePubKey2);
BigInteger sk23 = instance2.calculateAgreement(ePubKey3);
BigInteger sk31 = instance1.calculateAgreement(ePubKey3);
MultiSum.generateEphemeralKeyPair();
byte[] ePubKey3 = MultiSum.getEPubKey();
byte[] ePrivKey3 = MultiSum.getEPrivKey();

assertEquals(sk12,instance2.calculateAgreement(ePubKey1));
assertEquals(sk23,instance3.calculateAgreement(ePubKey2));
assertEquals(sk31,instance3.calculateAgreement(ePubKey1));

BigInteger s12 = MultiSum.deriveShares(id1,id2,sk12);
BigInteger s23 = MultiSum.deriveShares(id2,id3,sk23);
BigInteger s31 = MultiSum.deriveShares(id3,id1,sk31);
byte[] sk12 = MultiSum.calculateAgreement(ePubKey2,ePrivKey1);
byte[] sk23 = MultiSum.calculateAgreement(ePubKey3,ePrivKey2);
byte[] sk31 = MultiSum.calculateAgreement(ePubKey1,ePrivKey3);

assertEquals(s12, MultiSum.deriveShares(id1,id2,sk12));
assertEquals(s23, MultiSum.deriveShares(id2,id3,sk23));
assertEquals(s31, MultiSum.deriveShares(id3,id1,sk31));
assertArrayEquals(sk12,MultiSum.calculateAgreement(ePubKey1,ePrivKey2));
assertArrayEquals(sk23,MultiSum.calculateAgreement(ePubKey2,ePrivKey3));
assertArrayEquals(sk31,MultiSum.calculateAgreement(ePubKey3,ePrivKey1));

BigInteger c1 = MultiSum.encryptBlindedMsg(encKey,value1,s12,s31);
BigInteger c2 = MultiSum.encryptBlindedMsg(encKey,value2,s23,s12);
BigInteger c3 = MultiSum.encryptBlindedMsg(encKey,value3,s31,s23);
byte[] s12 = MultiSum.deriveShares(id1,id2,sk12);
byte[] s23 = MultiSum.deriveShares(id2,id3,sk23);
byte[] s31 = MultiSum.deriveShares(id3,id1,sk31);

BigInteger aggregatedCiphertext = MultiSum.aggregateCiphertexts(encKey,c1,c2,c3);
assertArrayEquals(s12, MultiSum.deriveShares(id1,id2,sk12));
assertArrayEquals(s23, MultiSum.deriveShares(id2,id3,sk23));
assertArrayEquals(s31, MultiSum.deriveShares(id3,id1,sk31));

BigInteger decryptedValue = MultiSum.decrypt(keyPair,aggregatedCiphertext);
byte[] c1 = MultiSum.encryptBlindedMsg(encKey,int1,s12,s31);
byte[] c2 = MultiSum.encryptBlindedMsg(encKey,int2,s23,s12);
byte[] c3 = MultiSum.encryptBlindedMsg(encKey,int3,s31,s23);

assertEquals(expectedSum,decryptedValue);
}
byte[] aggregatedCiphertext = MultiSum.aggregateCiphertexts(encKey,c1,c2,c3);

@Test
public void testResolveEPrivKey(){
byte[] decryptedValue = MultiSum.decrypt(decKey,aggregatedCiphertext);

MultiSum instance = new MultiSum();
instance.generateEphemeralKeyPair();

ECPrivateKeyParameters expectedEPrivKey = instance.getEPrivKey();
byte[] ePrivKeyBytes = instance.getEPrivKeyBytes();
ECPrivateKeyParameters ePrivKey = instance.resolveEPrivKey(ePrivKeyBytes);
assertEquals(expectedEPrivKey.getD(),ePrivKey.getD());
assertEquals(sum,byteArrayToInt(decryptedValue));
}

@Test
public void testResolveEPubKey(){

MultiSum instance = new MultiSum();
instance.generateEphemeralKeyPair();

ECPublicKeyParameters expectedEPubKey = instance.getEPubKey();
byte[] ePubKeyBytes = instance.getEPubKeyBytes();
ECPublicKeyParameters ePubKey = instance.resolveEPubKey(ePubKeyBytes);

assertEquals(Hex.toHexString(expectedEPubKey.getQ().getAffineXCoord().getEncoded()),Hex.toHexString(ePubKey.getQ().getAffineXCoord().getEncoded()));
assertEquals(Hex.toHexString(expectedEPubKey.getQ().getAffineYCoord().getEncoded()),Hex.toHexString(ePubKey.getQ().getAffineYCoord().getEncoded()));
private static int byteArrayToInt(byte[] input) {
int result;
int length = input.length;
byte[] buffer = new byte[4];
if (length <= buffer.length){
System.arraycopy(input,0,buffer,buffer.length - length,length);
} else {
System.arraycopy(input,length - buffer.length,buffer,0, buffer.length);
}
result = buffer[3] & 0xFF |
(buffer[2] & 0xFF) << 8 |
(buffer[1] & 0xFF) << 16 |
(buffer[0] & 0xFF) << 24;
return result;
}
}

+ 0
- 58
source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/DecryptionTest.java View File

@@ -1,58 +0,0 @@
package test.com.jd.blockchain.crypto.paillier;

import com.jd.blockchain.crypto.paillier.KeyPair;
import com.jd.blockchain.crypto.paillier.KeyPairBuilder;
import com.jd.blockchain.crypto.paillier.PublicKey;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collection;

import static org.junit.Assert.assertEquals;

/**
* Created by kunerd on 22.09.15.
*/
@RunWith(value = Parameterized.class)
public class DecryptionTest {

@Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays.asList(createTestParameter(Long.MIN_VALUE),
createTestParameter(Integer.MIN_VALUE),
createTestParameter(Short.MIN_VALUE),
createTestParameter(0),
createTestParameter(Short.MAX_VALUE),
createTestParameter(Integer.MAX_VALUE),
createTestParameter(Long.MAX_VALUE));
}

private BigInteger input;
private BigInteger expected;

public DecryptionTest(BigInteger input, BigInteger expected) {
this.input = input;
this.expected = expected;
}

@Test
public void test() {
KeyPair keyPair = new KeyPairBuilder().upperBound(BigInteger.valueOf(Long.MAX_VALUE))
.generateKeyPair();
PublicKey publicKey = keyPair.getPublicKey();

BigInteger encryptedData = publicKey.encrypt(input);

assertEquals(expected, keyPair.decrypt(encryptedData));
}

private static Object[] createTestParameter(long plaintext) {
BigInteger p = BigInteger.valueOf(plaintext);
return new Object[]{p, p};
}

}


+ 0
- 90
source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/HomomorphicPropertiesTest.java View File

@@ -1,90 +0,0 @@
package test.com.jd.blockchain.crypto.paillier;

import com.jd.blockchain.crypto.paillier.KeyPair;
import com.jd.blockchain.crypto.paillier.KeyPairBuilder;
import com.jd.blockchain.crypto.paillier.PublicKey;
import org.junit.Before;
import org.junit.Test;

import java.math.BigInteger;

import static org.junit.Assert.assertEquals;

public class HomomorphicPropertiesTest {
private KeyPair keypair;
private PublicKey publicKey;

@Before
public void init() {
KeyPairBuilder keygen = new KeyPairBuilder();
this.keypair = keygen.generateKeyPair();
this.publicKey = keypair.getPublicKey();
}

@Test
public void testHomomorphicAddition() {
BigInteger plainA = BigInteger.valueOf(102);
BigInteger plainB = BigInteger.valueOf(203);

BigInteger encryptedA = publicKey.encrypt(plainA);
BigInteger encryptedB = publicKey.encrypt(plainB);

BigInteger decryptedProduct = keypair.decrypt(encryptedA.multiply(
encryptedB).mod(publicKey.getnSquared()));
BigInteger plainSum = plainA.add(plainB).mod(publicKey.getN());

assertEquals(decryptedProduct, plainSum);
}

@Test
public void testHomomorphicConstantMultiplication() {
BigInteger plainA = BigInteger.valueOf(14);
BigInteger plainB = BigInteger.valueOf(203);

BigInteger encryptedA = publicKey.encrypt(plainA);

BigInteger decryptedPow = keypair.decrypt(encryptedA.modPow(plainB,
publicKey.getnSquared()));
BigInteger plainSum = plainA.multiply(plainB).mod(publicKey.getN());

assertEquals(decryptedPow, plainSum);
}

@Test
public void testHomomorphicMultiplication() {
BigInteger plainA = BigInteger.valueOf(23);
BigInteger plainB = BigInteger.valueOf(234);

BigInteger encryptedA = publicKey.encrypt(plainA);
BigInteger decryptedPowA = keypair.decrypt(encryptedA.modPow(
plainB, publicKey.getnSquared()));
BigInteger plainSumA = plainA.multiply(plainB).mod(publicKey.getN());

assertEquals(decryptedPowA, plainSumA);

BigInteger encryptedB = publicKey.encrypt(plainB);
BigInteger decryptedPowB = keypair.decrypt(encryptedB.modPow(
plainA, publicKey.getnSquared()));
BigInteger plainSumB = plainA.multiply(plainB).mod(publicKey.getN());

assertEquals(decryptedPowB, plainSumB);

assertEquals(decryptedPowA, decryptedPowB);
}

@Test
public void testHomomorphicMultiplicationPowG() {
BigInteger plainA = BigInteger.valueOf(230);
BigInteger plainB = BigInteger.valueOf(100);

BigInteger g = publicKey.getG();

BigInteger encryptedA = publicKey.encrypt(plainA);
BigInteger decryptedPow = keypair.decrypt(encryptedA.multiply(g.modPow(
plainB, publicKey.getnSquared()).mod(publicKey.getnSquared())));

BigInteger plainSumA = plainA.add(plainB).mod(publicKey.getN());

assertEquals(decryptedPow, plainSumA);
}
}

+ 0
- 43
source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/JPaillierTest.java View File

@@ -1,43 +0,0 @@
package test.com.jd.blockchain.crypto.paillier;

import com.jd.blockchain.crypto.paillier.KeyPair;
import com.jd.blockchain.crypto.paillier.KeyPairBuilder;
import com.jd.blockchain.crypto.paillier.PublicKey;
import org.junit.Before;
import org.junit.Test;

import java.math.BigInteger;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;

public class JPaillierTest {
private KeyPair keyPair;
private PublicKey publicKey;

@Before
public void init() {
KeyPairBuilder keygen = new KeyPairBuilder();
keyPair = keygen.generateKeyPair();
publicKey = keyPair.getPublicKey();
}

@Test
public void testEncryption() {
BigInteger plainData = BigInteger.valueOf(10);

BigInteger encryptedData = publicKey.encrypt(plainData);

assertNotEquals(plainData, encryptedData);
}

@Test
public void testDecyption() {
BigInteger plainData = BigInteger.valueOf(10);

BigInteger encryptedData = publicKey.encrypt(plainData);
BigInteger decryptedData = keyPair.decrypt(encryptedData);

assertEquals(plainData, decryptedData);
}
}

+ 0
- 44
source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/KeyPairBuilderPrivateKeyTest.java View File

@@ -1,44 +0,0 @@
package test.com.jd.blockchain.crypto.paillier;

import com.jd.blockchain.crypto.paillier.KeyPair;
import com.jd.blockchain.crypto.paillier.KeyPairBuilder;
import com.jd.blockchain.crypto.paillier.PrivateKey;
import com.jd.blockchain.crypto.paillier.PublicKey;
import org.junit.Before;
import org.junit.Test;

import java.math.BigInteger;

import static org.junit.Assert.assertEquals;

public class KeyPairBuilderPrivateKeyTest {
private KeyPairBuilder keygen;
private KeyPair keypair;
private PrivateKey privateKey;

@Before
public void init() {
this.keygen = new KeyPairBuilder();
this.keypair = keygen.generateKeyPair();
this.privateKey = keypair.getPrivateKey();
}

@Test
public void testPreCalculatedDenominator() {
PublicKey publicKey = keypair.getPublicKey();

BigInteger preCalculatedDenominator = privateKey.getPreCalculatedDenominator();

BigInteger g = publicKey.getG();
BigInteger n = publicKey.getN();
BigInteger nSquared = publicKey.getnSquared();
BigInteger lambda = privateKey.getLambda();

BigInteger expected = g.modPow(lambda, nSquared);
expected = expected.subtract(BigInteger.ONE);
expected = expected.divide(n);
expected = expected.modInverse(n);

assertEquals(expected, preCalculatedDenominator);
}
}

+ 0
- 57
source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/KeyPairBuilderPublicKeyTest.java View File

@@ -1,57 +0,0 @@
package test.com.jd.blockchain.crypto.paillier;

import com.jd.blockchain.crypto.paillier.KeyPair;
import com.jd.blockchain.crypto.paillier.KeyPairBuilder;
import com.jd.blockchain.crypto.paillier.PrivateKey;
import com.jd.blockchain.crypto.paillier.PublicKey;
import org.junit.Before;
import org.junit.Test;

import java.math.BigInteger;

import static org.junit.Assert.assertEquals;

public class KeyPairBuilderPublicKeyTest {

private KeyPair keypair;
private PublicKey publicKey;

@Before
public void init() {
KeyPairBuilder keygen = new KeyPairBuilder();
this.keypair = keygen.generateKeyPair();
this.publicKey = keypair.getPublicKey();
}

@Test
public void testBitsSetup() {
int BITS = 1024;
assertEquals(BITS, publicKey.getBits());
}

@Test
public void testCalculationOfNSquared() {

BigInteger n = publicKey.getN();
BigInteger nSquared = n.multiply(n);

assertEquals(nSquared, publicKey.getnSquared());
}

@Test
public void testCalculationOfGOfG() {
PrivateKey privateKey = keypair.getPrivateKey();

BigInteger n = publicKey.getN();
BigInteger nSquared = publicKey.getnSquared();
BigInteger g = publicKey.getG();
BigInteger lambda = privateKey.getLambda();

BigInteger l = g.modPow(lambda, nSquared);
l = l.subtract(BigInteger.ONE);
l = l.divide(n);

assertEquals(BigInteger.ONE, l.gcd(n));
}

}

+ 0
- 113
source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/KeyPairBuilderTest.java View File

@@ -1,113 +0,0 @@
package test.com.jd.blockchain.crypto.paillier;

import static org.junit.Assert.assertEquals;

import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Random;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import com.jd.blockchain.crypto.paillier.KeyPair;
import com.jd.blockchain.crypto.paillier.KeyPairBuilder;
import com.jd.blockchain.crypto.paillier.PrivateKey;
import com.jd.blockchain.crypto.paillier.PublicKey;

@RunWith(PowerMockRunner.class)
@PrepareForTest(KeyPairBuilder.class)
public class KeyPairBuilderTest {

private static final int BITS = 128;

private KeyPairBuilder keygen;
private PublicKey publicKey;
private PrivateKey privateKey;

private BigInteger p = BigInteger.valueOf(5);
private BigInteger q = BigInteger.valueOf(7);
private BigInteger g1 = BigInteger.valueOf(35);
private BigInteger g2 = BigInteger.valueOf(36);

private Random rng;

@Before
public void beforeEach() {
rng = PowerMockito.mock(SecureRandom.class);

keygen = new KeyPairBuilder()
.bits(BITS)
.randomNumberGenerator(rng);

PowerMockito.mockStatic(BigInteger.class);
}

private void prepareTest() throws Exception {

PowerMockito.when(BigInteger.probablePrime(BITS / 2, rng)).thenReturn(p, q);

PowerMockito.whenNew(BigInteger.class).withArguments(BITS, rng).thenReturn(g1, g2);

KeyPair keypair = keygen.generateKeyPair();

publicKey = keypair.getPublicKey();
privateKey = keypair.getPrivateKey();
}

@Test
public void computationOfN() throws Exception {
prepareTest();

BigInteger e = p.multiply(q);
BigInteger a = publicKey.getN();

assertEquals(e, a);
}


@Test
public void computationOfLambda() throws Exception {
BigInteger e = new BigInteger("12");

prepareTest();

BigInteger a = privateKey.getLambda();

assertEquals(e, a);
}

@Test
public void computationOfG() throws Exception {
prepareTest();

PowerMockito.verifyNew(BigInteger.class, Mockito.times(2)).withArguments(Mockito.eq(128), Mockito.any(Random.class));
}

@Test
public void withoutCertainty() throws Exception {
prepareTest();

PowerMockito.verifyStatic(Mockito.times(2));
BigInteger.probablePrime(BITS / 2, rng);

}

@Test
public void withCertainty() throws Exception {
int certainty = 6;

keygen.certainty(certainty);

PowerMockito.whenNew(BigInteger.class).withArguments(BITS / 2, certainty, rng).thenReturn(p, q);

prepareTest();

PowerMockito.verifyNew(BigInteger.class, Mockito.times(2)).withArguments(BITS / 2, certainty, rng);
}

}

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

@@ -0,0 +1,202 @@
package test.com.jd.blockchain.crypto.paillier;

import com.jd.blockchain.crypto.paillier.PaillierPrivateKeyParameters;
import com.jd.blockchain.crypto.paillier.PaillierPublicKeyParameters;
import com.jd.blockchain.crypto.paillier.PaillierUtils;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.junit.Test;

import java.math.BigInteger;
import java.security.SecureRandom;

import static org.junit.Assert.assertEquals;

/**
* @author zhanglin33
* @title: PaillierUtilsTest
* @description: Tests on PaillierUtils
* @date 2019-04-30, 14:54
*/
public class PaillierUtilsTest {
@Test
public void generateKeyPairTest() {

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

BigInteger n = pubKeyParams.getModulus();
BigInteger nSquared = pubKeyParams.getModulusSquared();
BigInteger g = pubKeyParams.getGenerator();

BigInteger nConverted = new BigInteger(1, bigIntegerToBytes(n,256));
BigInteger nSquaredConverted = new BigInteger(1, bigIntegerToBytes(nSquared,512));
BigInteger gConverted = new BigInteger(1, bigIntegerToBytes(g,256));
assertEquals(nConverted, n);
assertEquals(nSquaredConverted, nSquared);
assertEquals(gConverted, g);

BigInteger p = privKeyParams.getP();
BigInteger pSquared = privKeyParams.getPSquared();
BigInteger q = privKeyParams.getQ();
BigInteger qSquared = privKeyParams.getQSquared();
BigInteger pInverse = privKeyParams.getPInverse();
BigInteger muP = privKeyParams.getMuP();
BigInteger muQ = privKeyParams.getMuQ();

BigInteger pConverted = new BigInteger(1, bigIntegerToBytes(p,128));
BigInteger pSquaredConverted = new BigInteger(1, bigIntegerToBytes(pSquared,256));
BigInteger qConverted = new BigInteger(1, bigIntegerToBytes(q,128));
BigInteger qSquaredConverted = new BigInteger(1, bigIntegerToBytes(qSquared,256));
BigInteger pInverseConverted = new BigInteger(1, bigIntegerToBytes(pInverse,128));
BigInteger muPConverted = new BigInteger(1, bigIntegerToBytes(muP,128));
BigInteger muQConverted = new BigInteger(1, bigIntegerToBytes(muQ,128));
assertEquals(pConverted, p);
assertEquals(pSquaredConverted, pSquared);
assertEquals(qConverted, q);
assertEquals(qSquaredConverted, qSquared);
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);

SecureRandom random = new SecureRandom();
byte[] data = new byte[256];
random.nextBytes(data);

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

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[] ciphertextFromParams = PaillierUtils.encrypt(data,pubKeyParams);
byte[] ciphertextFromBytes = PaillierUtils.encrypt(data,pubKeyBytes);

byte[] plaintextFromParams = PaillierUtils.decrypt(ciphertextFromBytes,privKeyParams);
byte[] plaintextFromBytes = PaillierUtils.decrypt(ciphertextFromParams,privKeyBytes);

int outputFromParams = byteArrayToInt(plaintextFromParams);
int outputFromBytes = byteArrayToInt(plaintextFromBytes);

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);

int input1 = 600;
int input2 = 60;
int input3 = 6;

int sum = 666;

byte[] data1 = intToByteArray(input1);
byte[] data2 = intToByteArray(input2);
byte[] data3 = intToByteArray(input3);

byte[] ciphertext1 = PaillierUtils.encrypt(data1,pubKeyParams);
byte[] ciphertext2 = PaillierUtils.encrypt(data2,pubKeyParams);
byte[] ciphertext3 = PaillierUtils.encrypt(data3,pubKeyParams);

byte[] aggregatedCiphertext = PaillierUtils.add(pubKeyParams,ciphertext1,ciphertext2,ciphertext3);
byte[] plaintext = PaillierUtils.decrypt(aggregatedCiphertext,privKeyParams);

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

aggregatedCiphertext = PaillierUtils.add(pubKeyBytes,ciphertext1,ciphertext2,ciphertext3);
plaintext = PaillierUtils.decrypt(aggregatedCiphertext,privKeyParams);

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);

int input = 111;
int scalar = 6;
byte[] 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);
assertEquals(input * scalar, output);
}

private static byte[] intToByteArray(int input) {
byte[] result = new byte[4];
result[0] = (byte) ((input >> 24) & 0xFF);
result[1] = (byte) ((input >> 16) & 0xFF);
result[2] = (byte) ((input >> 8 ) & 0xFF);
result[3] = (byte) ((input ) & 0xFF);
return result;
}

private static int byteArrayToInt(byte[] input) {
int result;
int length = input.length;
byte[] buffer = new byte[4];
if (length <= buffer.length){
System.arraycopy(input,0,buffer,buffer.length - length,length);
} else {
System.arraycopy(input,length - buffer.length,buffer,0, buffer.length);
}
result = buffer[3] & 0xFF |
(buffer[2] & 0xFF) << 8 |
(buffer[1] & 0xFF) << 16 |
(buffer[0] & 0xFF) << 24;
return result;
}

// To convert BigInteger to byte array in specified size
private static byte[] bigIntegerToBytes(BigInteger b, int bytesSize){
byte[] tmp = b.toByteArray();
byte[] result = new byte[bytesSize];
if (tmp.length > result.length) {
System.arraycopy(tmp, tmp.length - result.length, result, 0, result.length);
}
else {
System.arraycopy(tmp,0,result,result.length-tmp.length,tmp.length);
}
return result;
}
}

+ 0
- 124
source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/ResolveTest.java View File

@@ -1,124 +0,0 @@
package test.com.jd.blockchain.crypto.paillier;

import com.jd.blockchain.crypto.paillier.*;
import org.junit.Test;

import java.math.BigInteger;

import static org.junit.Assert.assertEquals;

public class ResolveTest {

@Test
public void testResolvePrivateKey() {
KeyPairBuilder keygen = new KeyPairBuilder();
KeyPair keyPair = keygen.generateKeyPair();

PrivateKey privKey = keyPair.getPrivateKey();
BigInteger lambda = privKey.getLambda();
BigInteger preCalculatedDenominator = privKey.getPreCalculatedDenominator();

byte[] privKeyBytes = privKey.getPrivKeyBytes();
byte[] lambdaBytes = privKey.getLambdaBytes();
byte[] preCalculatedDenominatorBytes = privKey.getPreCalculatedDenominatorBytes();

assertEquals(lambda,new BigInteger(lambdaBytes));
assertEquals(preCalculatedDenominator,new BigInteger(preCalculatedDenominatorBytes));

assertEquals(lambda,new PrivateKey(lambda,preCalculatedDenominator).getLambda());
assertEquals(preCalculatedDenominator,(new PrivateKey(lambda,preCalculatedDenominator)).getPreCalculatedDenominator());

assertEquals(lambda,(new PrivateKey(lambdaBytes,preCalculatedDenominatorBytes)).getLambda());
assertEquals(preCalculatedDenominator,(new PrivateKey(lambdaBytes,preCalculatedDenominatorBytes)).getPreCalculatedDenominator());

assertEquals(lambda,(new PrivateKey(privKeyBytes)).getLambda());
assertEquals(preCalculatedDenominator,(new PrivateKey(privKeyBytes)).getPreCalculatedDenominator());
}

@Test
public void testResolvePublicKey() {
KeyPairBuilder keygen = new KeyPairBuilder();
KeyPair keyPair = keygen.generateKeyPair();

PublicKey pubKey = keyPair.getPublicKey();
int bits = pubKey.getBits();
BigInteger n = pubKey.getN();
BigInteger nSquared = pubKey.getnSquared();
BigInteger g = pubKey.getG();

byte[] pubKeyBytes = pubKey.getPubKeyBytes();
byte[] bitsBytes = pubKey.getBitsBytes();
byte[] nBytes = pubKey.getNBytes();
byte[] nSquaredBytes = pubKey.getNSquaredBytes();
byte[] gBytes = pubKey.getGBytes();

assertEquals(bits,PaillierUtils.bytesToInt(bitsBytes));
assertEquals(n,new BigInteger(nBytes));
assertEquals(nSquared,new BigInteger(nSquaredBytes));
assertEquals(g,new BigInteger(gBytes));

assertEquals(bits,(new PublicKey(n,nSquared,g,bits)).getBits());
assertEquals(n,(new PublicKey(n,nSquared,g,bits)).getN());
assertEquals(nSquared,(new PublicKey(n,nSquared,g,bits)).getnSquared());
assertEquals(g,(new PublicKey(n,nSquared,g,bits)).getG());

assertEquals(bits,(new PublicKey(nBytes,nSquaredBytes,gBytes,bitsBytes)).getBits());
assertEquals(n,(new PublicKey(nBytes,nSquaredBytes,gBytes,bitsBytes)).getN());
assertEquals(nSquared,(new PublicKey(nBytes,nSquaredBytes,gBytes,bitsBytes)).getnSquared());
assertEquals(g,(new PublicKey(nBytes,nSquaredBytes,gBytes,bitsBytes)).getG());

assertEquals(bits,(new PublicKey(pubKeyBytes)).getBits());
assertEquals(n,(new PublicKey(pubKeyBytes)).getN());
assertEquals(nSquared,(new PublicKey(pubKeyBytes)).getnSquared());
assertEquals(g,(new PublicKey(pubKeyBytes)).getG());
}

@Test
public void testResolveKeyPair() {
KeyPairBuilder keygen = new KeyPairBuilder();
keygen.upperBound(new BigInteger(PaillierUtils.intToBytes(Integer.MAX_VALUE)));
KeyPair keyPair = keygen.generateKeyPair();

PrivateKey privKey = keyPair.getPrivateKey();
PublicKey pubKey = keyPair.getPublicKey();
BigInteger upperBound = keyPair.getUpperBound();

byte[] keyPairBytes = keyPair.getKeyPairBytes();
byte[] privKeyBytes = privKey.getPrivKeyBytes();
byte[] pubKeyBytes = pubKey.getPubKeyBytes();
byte[] upperBoundBytes = keyPair.getUpperBoundBytes();

assertEquals(upperBound,keyPair.getUpperBound());
assertEquals(privKey.getLambda(),keyPair.getPrivateKey().getLambda());
assertEquals(privKey.getPreCalculatedDenominator(),keyPair.getPrivateKey().getPreCalculatedDenominator());
assertEquals(pubKey.getBits(),keyPair.getPublicKey().getBits());
assertEquals(pubKey.getN(),keyPair.getPublicKey().getN());
assertEquals(pubKey.getnSquared(),keyPair.getPublicKey().getnSquared());
assertEquals(pubKey.getG(),keyPair.getPublicKey().getG());

assertEquals(upperBound,(new KeyPair(privKey,pubKey,upperBound).getUpperBound()));
assertEquals(privKey.getLambda(),(new KeyPair(privKey,pubKey,upperBound).getPrivateKey().getLambda()));
assertEquals(privKey.getPreCalculatedDenominator(),(new KeyPair(privKey,pubKey,upperBound).getPrivateKey().getPreCalculatedDenominator()));
assertEquals(pubKey.getBits(),(new KeyPair(privKey,pubKey,upperBound).getPublicKey().getBits()));
assertEquals(pubKey.getN(),(new KeyPair(privKey,pubKey,upperBound).getPublicKey().getN()));
assertEquals(pubKey.getnSquared(),(new KeyPair(privKey,pubKey,upperBound).getPublicKey().getnSquared()));
assertEquals(pubKey.getG(),(new KeyPair(privKey,pubKey,upperBound).getPublicKey().getG()));

assertEquals(upperBound,(new KeyPair(privKeyBytes,pubKeyBytes,upperBoundBytes).getUpperBound()));
assertEquals(privKey.getLambda(),(new KeyPair(privKeyBytes,pubKeyBytes,upperBoundBytes).getPrivateKey().getLambda()));
assertEquals(privKey.getPreCalculatedDenominator(),(new KeyPair(privKeyBytes,pubKeyBytes,upperBoundBytes).getPrivateKey().getPreCalculatedDenominator()));
assertEquals(pubKey.getBits(),(new KeyPair(privKeyBytes,pubKeyBytes,upperBoundBytes).getPublicKey().getBits()));
assertEquals(pubKey.getN(),(new KeyPair(privKeyBytes,pubKeyBytes,upperBoundBytes).getPublicKey().getN()));
assertEquals(pubKey.getnSquared(),(new KeyPair(privKeyBytes,pubKeyBytes,upperBoundBytes).getPublicKey().getnSquared()));
assertEquals(pubKey.getG(),(new KeyPair(privKeyBytes,pubKeyBytes,upperBoundBytes).getPublicKey().getG()));

assertEquals(upperBound,(new KeyPair(keyPairBytes).getUpperBound()));
assertEquals(privKey.getLambda(),(new KeyPair(keyPairBytes).getPrivateKey().getLambda()));
assertEquals(privKey.getPreCalculatedDenominator(),(new KeyPair(keyPairBytes).getPrivateKey().getPreCalculatedDenominator()));
assertEquals(pubKey.getBits(),(new KeyPair(keyPairBytes).getPublicKey().getBits()));
assertEquals(pubKey.getN(),(new KeyPair(keyPairBytes).getPublicKey().getN()));
assertEquals(pubKey.getnSquared(),(new KeyPair(keyPairBytes).getPublicKey().getnSquared()));
assertEquals(pubKey.getG(),(new KeyPair(keyPairBytes).getPublicKey().getG()));

}
}

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

@@ -23,13 +23,14 @@ public class ClassicCryptoService implements CryptoService {

public static final JVMSecureRandomFunction JVM_SECURE_RANDOM = new JVMSecureRandomFunction();

// public static final ECDSASignatureFunction ECDSA = new
// ECDSASignatureFunction();
public static final ECDSASignatureFunction ECDSA = new ECDSASignatureFunction();

public static final RSACryptoFunction RSA = new RSACryptoFunction();

private static final Collection<CryptoFunction> FUNCTIONS;

static {
List<CryptoFunction> funcs = Arrays.asList(AES, ED25519, RIPEMD160, SHA256, JVM_SECURE_RANDOM);
List<CryptoFunction> funcs = Arrays.asList(AES, ED25519, ECDSA, RSA, RIPEMD160, SHA256, JVM_SECURE_RANDOM);
FUNCTIONS = Collections.unmodifiableList(funcs);
}



+ 107
- 16
source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ECDSASignatureFunction.java View File

@@ -1,60 +1,129 @@
package com.jd.blockchain.crypto.service.classic;

import com.jd.blockchain.crypto.CryptoAlgorithm;
import com.jd.blockchain.crypto.AsymmetricKeypair;
import com.jd.blockchain.crypto.PrivKey;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.crypto.SignatureDigest;
import com.jd.blockchain.crypto.SignatureFunction;
import com.jd.blockchain.crypto.*;
import com.jd.blockchain.crypto.utils.classic.ECDSAUtils;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;

import java.math.BigInteger;

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;

public class ECDSASignatureFunction implements SignatureFunction {

private static final CryptoAlgorithm ECDSA = ClassicAlgorithm.ECDSA;

private static final int PUBKEY_SIZE = 65;
private static final int PRIVKEY_SIZE = 32;
private static final int SIGNATUREDIGEST_SIZE = 64;

private static final int PUBKEY_LENGTH = ALGORYTHM_CODE_SIZE + KEY_TYPE_BYTES + PUBKEY_SIZE;
private static final int PRIVKEY_LENGTH = ALGORYTHM_CODE_SIZE + KEY_TYPE_BYTES + PRIVKEY_SIZE;
private static final int SIGNATUREDIGEST_LENGTH = ALGORYTHM_CODE_SIZE + SIGNATUREDIGEST_SIZE;

ECDSASignatureFunction() {
}

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

byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();

// 验证原始私钥长度为256比特,即32字节
if (rawPrivKeyBytes.length != PRIVKEY_SIZE) {
throw new CryptoException("This key has wrong format!");
}

// 验证密钥数据的算法标识对应ECDSA签名算法
if (privKey.getAlgorithm() != ECDSA.code()) {
throw new CryptoException("This key is not ECDSA private key!");
}

// 调用ECDSA签名算法计算签名结果
return new SignatureDigest(ECDSA, ECDSAUtils.sign(data, rawPrivKeyBytes));
}

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

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

// 验证原始公钥长度为256比特,即32字节
if (rawPubKeyBytes.length != PUBKEY_SIZE) {
throw new CryptoException("This key has wrong format!");
}

// 验证密钥数据的算法标识对应ECDSA签名算法
if (pubKey.getAlgorithm() != ECDSA.code()) {
throw new CryptoException("This key is not ECDSA public key!");
}

// 验证签名数据的算法标识对应ECDSA签名算法,并且原始摘要长度为64字节
if (digest.getAlgorithm() != ECDSA.code() || rawDigestBytes.length != SIGNATUREDIGEST_SIZE) {
throw new CryptoException("This is not ECDSA signature digest!");
}

// 调用ECDSA验签算法验证签名结果
return ECDSAUtils.verify(data, rawPubKeyBytes, rawDigestBytes);
}

@Override
public PubKey retrievePubKey(PrivKey privKey) {
return null;
byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();
byte[] rawPubKeyBytes = ECDSAUtils.retrievePublicKey(rawPrivKeyBytes);
return new PubKey(ECDSA, rawPubKeyBytes);
}

@Override
public boolean supportPrivKey(byte[] privKeyBytes) {
return false;
// 验证输入字节数组长度=算法标识长度+密钥类型长度+密钥长度,密钥数据的算法标识对应ECDSA签名算法,并且密钥类型是私钥
return privKeyBytes.length == PRIVKEY_LENGTH && CryptoAlgorithm.match(ECDSA, privKeyBytes)
&& privKeyBytes[ALGORYTHM_CODE_SIZE] == PRIVATE.CODE;
}

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

@Override
public boolean supportPubKey(byte[] pubKeyBytes) {
return false;
// 验证输入字节数组长度=算法标识长度+密钥类型长度+密钥长度,密钥数据的算法标识对应ECDSA签名算法,并且密钥类型是公钥
return pubKeyBytes.length == PUBKEY_LENGTH && CryptoAlgorithm.match(ECDSA, pubKeyBytes)
&& pubKeyBytes[ALGORYTHM_CODE_SIZE] == PUBLIC.CODE;
}

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

@Override
public boolean supportDigest(byte[] digestBytes) {
return false;
// 验证输入字节数组长度=算法标识长度+摘要长度,字节数组的算法标识对应ECDSA算法
return digestBytes.length == SIGNATUREDIGEST_LENGTH && CryptoAlgorithm.match(ECDSA, digestBytes);
}

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

@Override
@@ -64,6 +133,28 @@ public class ECDSASignatureFunction implements SignatureFunction {

@Override
public AsymmetricKeypair generateKeypair() {
return null;

// 调用ECDSA算法的密钥生成算法生成公私钥对priKey和pubKey,返回密钥对
AsymmetricCipherKeyPair keyPair = ECDSAUtils.generateKeyPair();
ECPrivateKeyParameters privKeyParams = (ECPrivateKeyParameters) keyPair.getPrivate();
ECPublicKeyParameters pubKeyParams = (ECPublicKeyParameters) keyPair.getPublic();

byte[] privKeyBytes = BigIntegerTo32Bytes(privKeyParams.getD());
byte[] pubKeyBytes = pubKeyParams.getQ().getEncoded(false);

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

// To convert BigInteger to byte[] whose length is 32
private static byte[] BigIntegerTo32Bytes(BigInteger b){
byte[] tmp = b.toByteArray();
byte[] result = new byte[32];
if (tmp.length > result.length) {
System.arraycopy(tmp, tmp.length - result.length, result, 0, result.length);
}
else {
System.arraycopy(tmp,0,result,result.length-tmp.length,tmp.length);
}
return result;
}
}

+ 5
- 27
source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ED25519SignatureFunction.java View File

@@ -49,9 +49,7 @@ public class ED25519SignatureFunction implements SignatureFunction {
}

// 调用ED25519签名算法计算签名结果
// return new SignatureDigest(ED25519, Ed25519Utils.sign_512(data, rawPrivKeyBytes));
return new SignatureDigest(ED25519, ED25519Utils.sign(data, rawPrivKeyBytes));

}

@Override
@@ -70,13 +68,12 @@ public class ED25519SignatureFunction implements SignatureFunction {
throw new CryptoException("This key is not ED25519 public key!");
}

// 验证密文数据的算法标识对应ED25519签名算法,并且原始摘要长度为64字节
// 验证签名数据的算法标识对应ED25519签名算法,并且原始摘要长度为64字节
if (digest.getAlgorithm() != ED25519.code() || rawDigestBytes.length != SIGNATUREDIGEST_SIZE) {
throw new CryptoException("This is not ED25519 signature digest!");
}

// 调用ED25519验签算法验证签名结果
// return Ed25519Utils.verify(data, rawPubKeyBytes, rawDigestBytes);
return ED25519Utils.verify(data, rawPubKeyBytes, rawDigestBytes);
}

@@ -84,21 +81,8 @@ public class ED25519SignatureFunction implements SignatureFunction {
public PubKey retrievePubKey(PrivKey privKey) {
byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();
byte[] rawPubKeyBytes = ED25519Utils.retrievePublicKey(rawPrivKeyBytes);
// EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512);
// EdDSAPrivateKeySpec privateKeySpec = new EdDSAPrivateKeySpec(rawPrivKeyBytes, spec);
// byte[] rawPubKeyBytes = privateKeySpec.getA().toByteArray();
return new PubKey(ED25519, rawPubKeyBytes);
}
//
// @Override
// public byte[] retrievePubKey(byte[] privKeyBytes) {
//
// byte[] rawPrivKeyBytes = resolvePrivKey(privKeyBytes).getRawKeyBytes();
// EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512);
// EdDSAPrivateKeySpec privateKeySpec = new EdDSAPrivateKeySpec(rawPrivKeyBytes, spec);
// byte[] rawPubKeyBytes = privateKeySpec.getA().toByteArray();
// return new PubKey(ED25519, rawPubKeyBytes).toBytes();
// }

@Override
public boolean supportPrivKey(byte[] privKeyBytes) {
@@ -112,7 +96,7 @@ public class ED25519SignatureFunction implements SignatureFunction {
if (supportPrivKey(privKeyBytes)) {
return new PrivKey(privKeyBytes);
} else {
throw new CryptoException("privKeyBytes is invalid!");
throw new CryptoException("privKeyBytes are invalid!");
}
}

@@ -121,7 +105,6 @@ public class ED25519SignatureFunction implements SignatureFunction {
// 验证输入字节数组长度=算法标识长度+密钥类型长度+密钥长度,密钥数据的算法标识对应ED25519签名算法,并且密钥类型是公钥
return pubKeyBytes.length == PUBKEY_LENGTH && CryptoAlgorithm.match(ED25519, pubKeyBytes)
&& pubKeyBytes[ALGORYTHM_CODE_SIZE] == PUBLIC.CODE;

}

@Override
@@ -129,7 +112,7 @@ public class ED25519SignatureFunction implements SignatureFunction {
if (supportPubKey(pubKeyBytes)) {
return new PubKey(pubKeyBytes);
} else {
throw new CryptoException("pubKeyBytes is invalid!");
throw new CryptoException("pubKeyBytes are invalid!");
}
}

@@ -144,7 +127,7 @@ public class ED25519SignatureFunction implements SignatureFunction {
if (supportDigest(digestBytes)) {
return new SignatureDigest(digestBytes);
} else {
throw new CryptoException("digestBytes is invalid!");
throw new CryptoException("digestBytes are invalid!");
}
}

@@ -155,6 +138,7 @@ public class ED25519SignatureFunction implements SignatureFunction {

@Override
public AsymmetricKeypair generateKeypair() {

// 调用ED25519算法的密钥生成算法生成公私钥对priKey和pubKey,返回密钥对
AsymmetricCipherKeyPair keyPair = ED25519Utils.generateKeyPair();
Ed25519PrivateKeyParameters privKeyParams = (Ed25519PrivateKeyParameters) keyPair.getPrivate();
@@ -162,12 +146,6 @@ public class ED25519SignatureFunction implements SignatureFunction {

byte[] privKeyBytes = privKeyParams.getEncoded();
byte[] pubKeyBytes = pubKeyParams.getEncoded();
// KeyPairGenerator keyPairGenerator = new KeyPairGenerator();
// KeyPair keyPair = keyPairGenerator.generateKeyPair();
// EdDSAPrivateKey privKey = (EdDSAPrivateKey) keyPair.getPrivate();
// EdDSAPublicKey pubKey = (EdDSAPublicKey) keyPair.getPublic();
// return new CryptoKeyPair(new PubKey(ED25519, pubKey.getAbyte()), new PrivKey(ED25519, privKey.getSeed()));
return new AsymmetricKeypair(new PubKey(ED25519, pubKeyBytes), new PrivKey(ED25519, privKeyBytes));

}
}

+ 2
- 1
source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RIPEMD160HashFunction.java View File

@@ -9,6 +9,7 @@ import com.jd.blockchain.crypto.CryptoBytes;
import com.jd.blockchain.crypto.CryptoException;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.HashFunction;
import com.jd.blockchain.crypto.utils.classic.RIPEMD160Utils;
import com.jd.blockchain.utils.security.RipeMD160Utils;

public class RIPEMD160HashFunction implements HashFunction {
@@ -34,7 +35,7 @@ public class RIPEMD160HashFunction implements HashFunction {
throw new CryptoException("data is null!");
}

byte[] digestBytes = RipeMD160Utils.hash(data);
byte[] digestBytes = RIPEMD160Utils.hash(data);
return new HashDigest(RIPEMD160, digestBytes);
}



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

@@ -1,14 +1,15 @@
package com.jd.blockchain.crypto.service.classic;

import com.jd.blockchain.crypto.AsymmetricCiphertext;
import com.jd.blockchain.crypto.AsymmetricEncryptionFunction;
import com.jd.blockchain.crypto.Ciphertext;
import com.jd.blockchain.crypto.CryptoAlgorithm;
import com.jd.blockchain.crypto.AsymmetricKeypair;
import com.jd.blockchain.crypto.PrivKey;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.crypto.SignatureDigest;
import com.jd.blockchain.crypto.SignatureFunction;
import com.jd.blockchain.crypto.*;
import com.jd.blockchain.crypto.utils.classic.RSAUtils;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;

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;

/**
* @author zhanglin33
@@ -17,78 +18,195 @@ import com.jd.blockchain.crypto.SignatureFunction;
* @date 2019-03-25, 17:28
*/
public class RSACryptoFunction implements AsymmetricEncryptionFunction, SignatureFunction {

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,
// dP.length = 128, dQ.length = 128, qInv.length = 128
private static final int PRIVKEY_SIZE = 1153;

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

private static final int PUBKEY_LENGTH = ALGORYTHM_CODE_SIZE + KEY_TYPE_BYTES + PUBKEY_SIZE;
private static final int PRIVKEY_LENGTH = ALGORYTHM_CODE_SIZE + KEY_TYPE_BYTES + PRIVKEY_SIZE;
private static final int SIGNATUREDIGEST_LENGTH = ALGORYTHM_CODE_SIZE + SIGNATUREDIGEST_SIZE;
@Override
public Ciphertext encrypt(PubKey pubKey, byte[] data) {
return null;

byte[] rawPubKeyBytes = pubKey.getRawKeyBytes();

// 验证原始公钥长度为257字节
if (rawPubKeyBytes.length != PUBKEY_SIZE) {
throw new CryptoException("This key has wrong format!");
}

// 验证密钥数据的算法标识对应RSA算法
if (pubKey.getAlgorithm() != RSA.code()) {
throw new CryptoException("The is not RSA public key!");
}

// 调用RSA加密算法计算密文
return new AsymmetricCiphertext(RSA, RSAUtils.encrypt(data, rawPubKeyBytes));
}

@Override
public byte[] decrypt(PrivKey privKey, Ciphertext ciphertext) {
return new byte[0];

byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();
byte[] rawCiphertextBytes = ciphertext.getRawCiphertext();

// 验证原始私钥长度为1153字节
if (rawPrivKeyBytes.length != PRIVKEY_SIZE) {
throw new CryptoException("This key has wrong format!");
}

// 验证密钥数据的算法标识对应RSA算法
if (privKey.getAlgorithm() != RSA.code()) {
throw new CryptoException("This key is not RSA private key!");
}

// 验证密文数据的算法标识对应RSA算法,并且密文是分组长度的整数倍
if (ciphertext.getAlgorithm() != RSA.code()
|| rawCiphertextBytes.length % CIPHERTEXTBLOCK_SIZE != 0) {
throw new CryptoException("This is not RSA ciphertext!");
}

// 调用RSA解密算法得到明文结果
return RSAUtils.decrypt(rawCiphertextBytes, rawPrivKeyBytes);
}

@Override
public PubKey retrievePubKey(PrivKey privKey) {
return null;
byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();
byte[] rawPubKeyBytes = RSAUtils.retrievePublicKey(rawPrivKeyBytes);
return new PubKey(RSA, rawPubKeyBytes);
}

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

byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();

// 验证原始私钥长度为1153字节
if (rawPrivKeyBytes.length != PRIVKEY_SIZE) {
throw new CryptoException("This key has wrong format!");
}

// 验证密钥数据的算法标识对应RSA签名算法
if (privKey.getAlgorithm() != RSA.code()) {
throw new CryptoException("This key is not RSA private key!");
}

// 调用RSA签名算法计算签名结果
return new SignatureDigest(RSA, RSAUtils.sign(data, rawPrivKeyBytes));
}

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

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

// 验证原始公钥长度为257字节
if (rawPubKeyBytes.length != PUBKEY_SIZE) {
throw new CryptoException("This key has wrong format!");
}

// 验证密钥数据的算法标识对应RSA签名算法
if (pubKey.getAlgorithm() != RSA.code()) {
throw new CryptoException("This key is not RSA public key!");
}

// 验证签名数据的算法标识对应RSA签名算法,并且原始签名长度为256字节
if (digest.getAlgorithm() != RSA.code() || rawDigestBytes.length != SIGNATUREDIGEST_SIZE) {
throw new CryptoException("This is not RSA signature digest!");
}

// 调用RSA验签算法验证签名结果
return RSAUtils.verify(data, rawPubKeyBytes, rawDigestBytes);
}

@Override
public boolean supportPrivKey(byte[] privKeyBytes) {
return false;
// 验证输入字节数组长度=算法标识长度+密钥类型长度+密钥长度,密钥数据的算法标识对应RSA算法,并且密钥类型是私钥
return privKeyBytes.length == PRIVKEY_LENGTH && CryptoAlgorithm.match(RSA, privKeyBytes)
&& privKeyBytes[ALGORYTHM_CODE_SIZE] == PRIVATE.CODE;
}

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

@Override
public boolean supportPubKey(byte[] pubKeyBytes) {
return false;
// 验证输入字节数组长度=算法标识长度+密钥类型长度+椭圆曲线点长度,密钥数据的算法标识对应RSA算法,并且密钥类型是公钥
return pubKeyBytes.length == PUBKEY_LENGTH && CryptoAlgorithm.match(RSA, pubKeyBytes)
&& pubKeyBytes[ALGORYTHM_CODE_SIZE] == PUBLIC.CODE;
}

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

@Override
public boolean supportDigest(byte[] digestBytes) {
return false;
// 验证输入字节数组长度=算法标识长度+签名长度,字节数组的算法标识对应RSA算法
return digestBytes.length == SIGNATUREDIGEST_LENGTH && CryptoAlgorithm.match(RSA, digestBytes);
}

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

@Override
public boolean supportCiphertext(byte[] ciphertextBytes) {
return false;
// 验证输入字节数组长度=密文分组的整数倍,字节数组的算法标识对应RSA算法
return (ciphertextBytes.length % CIPHERTEXTBLOCK_SIZE == ALGORYTHM_CODE_SIZE)
&& CryptoAlgorithm.match(RSA, ciphertextBytes);
}

@Override
public AsymmetricCiphertext resolveCiphertext(byte[] ciphertextBytes) {
return null;
if (supportCiphertext(ciphertextBytes)) {
return new AsymmetricCiphertext(ciphertextBytes);
} else {
throw new CryptoException("ciphertextBytes are invalid!");
}
}

@Override
public CryptoAlgorithm getAlgorithm() {
return null;
return RSA;
}

@Override
public AsymmetricKeypair generateKeypair() {
return null;

AsymmetricCipherKeyPair keyPair = RSAUtils.generateKeyPair();
RSAKeyParameters pubKey = (RSAKeyParameters) keyPair.getPublic();
RSAPrivateCrtKeyParameters privKey = (RSAPrivateCrtKeyParameters) keyPair.getPrivate();

byte[] pubKeyBytes = RSAUtils.pubKey2Bytes_RawKey(pubKey);
byte[] privKeyBytes = RSAUtils.privKey2Bytes_RawKey(privKey);

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

+ 2
- 1
source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/SHA256HashFunction.java View File

@@ -9,6 +9,7 @@ import com.jd.blockchain.crypto.CryptoBytes;
import com.jd.blockchain.crypto.CryptoException;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.HashFunction;
import com.jd.blockchain.crypto.utils.classic.SHA256Utils;
import com.jd.blockchain.utils.security.ShaUtils;

public class SHA256HashFunction implements HashFunction {
@@ -34,7 +35,7 @@ public class SHA256HashFunction implements HashFunction {
throw new CryptoException("data is null!");
}

byte[] digestBytes = ShaUtils.hash_256(data);
byte[] digestBytes = SHA256Utils.hash(data);
return new HashDigest(SHA256, digestBytes);
}



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

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

import com.jd.blockchain.crypto.CryptoException;
import org.bouncycastle.crypto.CipherKeyGenerator;
import org.bouncycastle.crypto.KeyGenerationParameters;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PKCS7Padding;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;

import java.security.SecureRandom;
import java.util.Arrays;

/**
* @author zhanglin33
* @title: AESUtils
* @description: AES128/CBC/PKCS7Padding symmetric encryption algorithm
* @date 2019-04-22, 09:37
*/
public class AESUtils {

// AES128 supports 128-bit(16 bytes) secret key
private static final int KEY_SIZE = 128 / 8;
// One block contains 16 bytes
private static final int BLOCK_SIZE = 16;
// Initial vector's size is 16 bytes
private static final int IV_SIZE = 16;

/**
* key generation
*
* @return secret key
*/
public static byte[] generateKey(){

CipherKeyGenerator keyGenerator = new CipherKeyGenerator();

// To provide secure randomness and key length as input
// to prepare generate private key
keyGenerator.init(new KeyGenerationParameters(new SecureRandom(), KEY_SIZE * 8));

// To generate key
return keyGenerator.generateKey();
}

public static byte[] generateKey(byte[] seed){
byte[] hash = SHA256Utils.hash(seed);
return Arrays.copyOf(hash, KEY_SIZE);
}


/**
* encryption
*
* @param plainBytes plaintext
* @param secretKey symmetric key
* @param iv initial vector
* @return ciphertext
*/
public static byte[] encrypt(byte[] plainBytes, byte[] secretKey, byte[] iv){

// To ensure that plaintext is not null
if (plainBytes == null)
{
throw new CryptoException("plaintext is null!");
}

if (secretKey.length != KEY_SIZE)
{
throw new CryptoException("secretKey's length is wrong!");
}

if (iv.length != IV_SIZE)
{
throw new CryptoException("iv's length is wrong!");
}

// To get the value padded into input
int padding = 16 - plainBytes.length % BLOCK_SIZE;
// The plaintext with padding value
byte[] plainBytesWithPadding = new byte[plainBytes.length + padding];
System.arraycopy(plainBytes,0,plainBytesWithPadding,0,plainBytes.length);
// The padder adds PKCS7 padding to the input, which makes its length to
// become an integral multiple of 16 bytes
PKCS7Padding padder = new PKCS7Padding();
// To add padding
padder.addPadding(plainBytesWithPadding, plainBytes.length);

CBCBlockCipher encryptor = new CBCBlockCipher(new AESEngine());
// To provide key and initialisation vector as input
encryptor.init(true,new ParametersWithIV(new KeyParameter(secretKey),iv));
byte[] output = new byte[plainBytesWithPadding.length + IV_SIZE];
// To encrypt the input_p in CBC mode
for(int i = 0 ; i < plainBytesWithPadding.length/BLOCK_SIZE; i++) {
encryptor.processBlock(plainBytesWithPadding, i * BLOCK_SIZE, output, (i + 1) * BLOCK_SIZE);
}

// The IV locates on the first block of ciphertext
System.arraycopy(iv,0,output,0,BLOCK_SIZE);
return output;
}

public static byte[] encrypt(byte[] plainBytes, byte[] secretKey){

byte[] iv = new byte[IV_SIZE];
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
return encrypt(plainBytes,secretKey,iv);
}

/**
* decryption
*
* @param cipherBytes ciphertext
* @param secretKey symmetric key
* @return plaintext
*/
public static byte[] decrypt(byte[] cipherBytes, byte[] secretKey){

// To ensure that the ciphertext is not null
if (cipherBytes == null)
{
throw new CryptoException("ciphertext is null!");
}

// To ensure that the ciphertext's length is integral multiples of 16 bytes
if (cipherBytes.length % BLOCK_SIZE != 0)
{
throw new CryptoException("ciphertext's length is wrong!");
}

if (secretKey.length != KEY_SIZE)
{
throw new CryptoException("secretKey's length is wrong!");
}

byte[] iv = new byte[IV_SIZE];
System.arraycopy(cipherBytes,0,iv,0,BLOCK_SIZE);

CBCBlockCipher decryptor = new CBCBlockCipher(new AESEngine());
// To prepare the decryption
decryptor.init(false,new ParametersWithIV(new KeyParameter(secretKey),iv));
byte[] outputWithPadding = new byte[cipherBytes.length-BLOCK_SIZE];
// To decrypt the input in CBC mode
for(int i = 1 ; i < cipherBytes.length/BLOCK_SIZE ; i++) {
decryptor.processBlock(cipherBytes, i * BLOCK_SIZE, outputWithPadding, (i - 1) * BLOCK_SIZE);
}

int p = outputWithPadding[outputWithPadding.length-1];
// To ensure that the padding of output_p is valid
if(p > BLOCK_SIZE || p < 0x01)
{
throw new CryptoException("There no exists such padding!");

}
for(int i = 0 ; i < p ; i++)
{
if(outputWithPadding[outputWithPadding.length - i -1] != p)
{
throw new CryptoException("Padding is invalid!");
}
}

// To remove the padding from output and obtain plaintext
byte[] output = new byte[outputWithPadding.length - p];
System.arraycopy(outputWithPadding, 0, output, 0, output.length);
return output;
}
}

+ 10
- 8
source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/ECDSAUtils.java View File

@@ -89,10 +89,10 @@ public class ECDSAUtils {
return sign(data,params);
}

public static byte[] sign(byte[] data, byte[] privateKey, SecureRandom random, String ID){
public static byte[] sign(byte[] data, byte[] privateKey, SecureRandom random){

ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(new BigInteger(1,privateKey), DOMAIN_PARAMS);
CipherParameters params = new ParametersWithID(new ParametersWithRandom(privKey,random),ID.getBytes());
CipherParameters params = new ParametersWithRandom(privKey,random);

return sign(data,params);
}
@@ -100,16 +100,14 @@ public class ECDSAUtils {
public static byte[] sign(byte[] data, CipherParameters params){

byte[] hashedMsg = SHA256Utils.hash(data);
return sign(params,hashedMsg);
}

public static byte[] sign(CipherParameters params, byte[] hashedMsg){
ECDSASigner signer = new ECDSASigner();
signer.init(true, params);
BigInteger[] signature = signer.generateSignature(hashedMsg);

// // To decode the signature
// ASN1Sequence sig = ASN1Sequence.getInstance(encodedSignature);
// byte[] rBytes = BigIntegerTo32Bytes(ASN1Integer.getInstance(sig.getObjectAt(0)).getValue());
// byte[] sBytes = BigIntegerTo32Bytes(ASN1Integer.getInstance(sig.getObjectAt(1)).getValue());

byte[] rBytes = BigIntegerTo32Bytes(signature[0]);
byte[] sBytes = BigIntegerTo32Bytes(signature[1]);

@@ -120,6 +118,7 @@ public class ECDSAUtils {
return result;
}


/**
* verification
*
@@ -139,6 +138,10 @@ public class ECDSAUtils {
public static boolean verify(byte[] data, CipherParameters params, byte[] signature){

byte[] hashedMsg = SHA256Utils.hash(data);
return verify(params,signature,hashedMsg);
}

public static boolean verify(CipherParameters params, byte[] signature, byte[] hashedMsg){

byte[] rBytes = new byte[R_SIZE];
byte[] sBytes = new byte[S_SIZE];
@@ -153,7 +156,6 @@ public class ECDSAUtils {
return verifier.verifySignature(hashedMsg,r,s);
}


// To convert BigInteger to byte[] whose length is 32
private static byte[] BigIntegerTo32Bytes(BigInteger b){
byte[] tmp = b.toByteArray();


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

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

import org.bouncycastle.crypto.digests.RIPEMD160Digest;

/**
* @author zhanglin33
* @title: RIPEMD160Utils
* @description: RIPEMD160 hash algorithm
* @date 2019-04-10, 16:51
*/
public class RIPEMD160Utils {

// The length of RIPEMD160 output is 20 bytes
private static final int RIPEMD160DIGEST_LENGTH = 160 / 8;

public static byte[] hash(byte[] data){

byte[] result = new byte[RIPEMD160DIGEST_LENGTH];
RIPEMD160Digest ripemd160Digest = new RIPEMD160Digest();

ripemd160Digest.update(data,0,data.length);
ripemd160Digest.doFinal(result,0);
return result;
}
}

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

@@ -1,10 +1,521 @@
package com.jd.blockchain.crypto.utils.classic;

import com.jd.blockchain.utils.io.BytesUtils;
import org.bouncycastle.asn1.*;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.crypto.*;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.encodings.PKCS1Encoding;
import org.bouncycastle.crypto.engines.RSAEngine;
import org.bouncycastle.crypto.generators.RSAKeyPairGenerator;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
import org.bouncycastle.crypto.signers.RSADigestSigner;
import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil;
import sun.security.rsa.RSAPrivateCrtKeyImpl;

import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
* @author zhanglin33
* @title: RSAUtils
* @description: RSA encryption and signature algorithms
* @description: RSA2048 encryption(RSA/ECB/PKCS1Padding) and signature(SHA256withRSA) algorithms,
* and keys are output in raw, PKCS1v2 and PKCS8 formats
* @date 2019-03-25, 17:20
*/
public class RSAUtils {
public class RSAUtils {

private static final int KEYSIZEBITS = 2048;
private static final int CERTAINTY = 100;

private static final int MODULUS_LENGTH = 2048 / 8;
private static final int PRIVEXP_LENGTH = 2048 / 8;
private static final int P_LENGTH = 1024 / 8;
private static final int Q_LENGTH = 1024 / 8;
private static final int DP_LENGTH = 1024 / 8;
private static final int DQ_LENGTH = 1024 / 8;
private static final int QINV_LENGTH = 1024 / 8;

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

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

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

private static final int PLAINTEXT_BLOCKSIZE = 256 - 11;
private static final int CIPHERTEXT_BLOCKSIZE = 256;


//-----------------Key Generation Algorithm-----------------

/**
* key pair generation
*
* @return key pair
*/
public static AsymmetricCipherKeyPair generateKeyPair(){
return generateKeyPair(new SecureRandom());
}

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

// Retrieve public key in raw keys form
public static byte[] retrievePublicKey(byte[] privateKey) {

RSAPrivateCrtKeyParameters privKey = bytes2PrivKey_RawKey(privateKey);

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

RSAKeyParameters pubKey = new RSAKeyParameters(false, modulus, exponent);

return pubKey2Bytes_RawKey(pubKey);
}


//-----------------Digital Signature Algorithm-----------------

/**
* signature generation
*
* @param data data to be signed
* @param privateKey private key
* @return signature
*/
public static byte[] sign(byte[] data, byte[] privateKey){
RSAPrivateCrtKeyParameters privKey = bytes2PrivKey_RawKey(privateKey);
return sign(data,privKey);
}

public static byte[] sign(byte[] data, CipherParameters params){

SHA256Digest digest = new SHA256Digest();
RSADigestSigner signer = new RSADigestSigner(digest);
signer.init(true, params);
signer.update(data, 0, data.length);
try {
return signer.generateSignature();
} catch (CryptoException e) {
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e);
}
}

/**
* verification
*
* @param data data to be signed
* @param publicKey public key
* @param signature signature to be verified
* @return true or false
*/
public static boolean verify(byte[] data, byte[] publicKey, byte[] signature){
RSAKeyParameters pubKey = bytes2PubKey_RawKey(publicKey);
return verify(data,pubKey,signature);
}

public static boolean verify(byte[] data, CipherParameters params, byte[] signature){

SHA256Digest digest = new SHA256Digest();
RSADigestSigner signer = new RSADigestSigner(digest);

signer.init(false, params);
signer.update(data, 0, data.length);
return signer.verifySignature(signature);
}


//-----------------Public Key Encryption Algorithm-----------------

/**
* encryption
*
* @param plainBytes plaintext
* @param publicKey public key
* @return ciphertext
*/
public static byte[] encrypt(byte[] plainBytes, byte[] publicKey){
RSAKeyParameters pubKey = bytes2PubKey_RawKey(publicKey);
return encrypt(plainBytes,pubKey);
}

public static byte[] encrypt(byte[] plainBytes, byte[] publicKey, SecureRandom random){

RSAKeyParameters pubKey = bytes2PubKey_RawKey(publicKey);
ParametersWithRandom params = new ParametersWithRandom(pubKey,random);

return encrypt(plainBytes,params);
}

public static byte[] encrypt(byte[] plainBytes, CipherParameters params){

int blockNum = (plainBytes.length % PLAINTEXT_BLOCKSIZE == 0) ? (plainBytes.length / PLAINTEXT_BLOCKSIZE)
: (plainBytes.length / PLAINTEXT_BLOCKSIZE + 1);
int inputLength;
byte[] result = new byte[blockNum * CIPHERTEXT_BLOCKSIZE];
byte[] buffer;

AsymmetricBlockCipher encryptor = new PKCS1Encoding(new RSAEngine());
encryptor.init(true, params);
try {
for (int i= 0; i < blockNum; i++) {
inputLength = ((plainBytes.length - i * PLAINTEXT_BLOCKSIZE) > PLAINTEXT_BLOCKSIZE)?
PLAINTEXT_BLOCKSIZE : (plainBytes.length - i * PLAINTEXT_BLOCKSIZE);
buffer = encryptor.processBlock(plainBytes, i * PLAINTEXT_BLOCKSIZE, inputLength);
System.arraycopy(buffer,0,
result, i * CIPHERTEXT_BLOCKSIZE, CIPHERTEXT_BLOCKSIZE);
}
} catch (InvalidCipherTextException e) {
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e);
}
return result;
}

/**
* decryption
*
* @param cipherBytes ciphertext
* @param privateKey private key
* @return plaintext
*/
public static byte[] decrypt(byte[] cipherBytes, byte[] privateKey){
RSAPrivateCrtKeyParameters privKey = bytes2PrivKey_RawKey(privateKey);
return decrypt(cipherBytes,privKey);
}

public static byte[] decrypt(byte[] cipherBytes, CipherParameters params){

if (cipherBytes.length % CIPHERTEXT_BLOCKSIZE != 0)
{
throw new com.jd.blockchain.crypto.CryptoException("ciphertext's length is wrong!");
}

int blockNum = cipherBytes.length / CIPHERTEXT_BLOCKSIZE;
int count = 0;
byte[] buffer;
byte[] plaintextWithZeros = new byte[blockNum * PLAINTEXT_BLOCKSIZE];
byte[] result;

AsymmetricBlockCipher decryptor = new PKCS1Encoding(new RSAEngine());
decryptor.init(false,params);
try {
for (int i = 0; i < blockNum; i++){
buffer = decryptor.processBlock(cipherBytes,i * CIPHERTEXT_BLOCKSIZE, CIPHERTEXT_BLOCKSIZE);
count += buffer.length;
System.arraycopy(buffer,0,plaintextWithZeros, i * PLAINTEXT_BLOCKSIZE, buffer.length);
}
} catch (InvalidCipherTextException e) {
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e);
}

result = new byte[count];
System.arraycopy(plaintextWithZeros,0,result,0,result.length);

return result;
}


/**
* This outputs the key in PKCS1v2 format.
* RSAPublicKey ::= SEQUENCE {
* modulus INTEGER, -- n
* publicExponent INTEGER, -- e
* }
*/
public static byte[] pubKey2Bytes_PKCS1(RSAKeyParameters pubKey)
{
ASN1EncodableVector v = new ASN1EncodableVector();

v.add(new ASN1Integer(pubKey.getModulus()));
v.add(new ASN1Integer(pubKey.getExponent()));

DERSequence pubKeySequence = new DERSequence(v);

byte[] result;

try {
result = pubKeySequence.getEncoded(ASN1Encoding.DER);
} catch (IOException e) {
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e);
}

return result;
}

public static byte[] pubKey2Bytes_PKCS8(RSAKeyParameters pubKey){

BigInteger modulus = pubKey.getModulus();
BigInteger exponent = pubKey.getExponent();

return KeyUtil.getEncodedSubjectPublicKeyInfo(RSA_ALGORITHM_IDENTIFIER,
new org.bouncycastle.asn1.pkcs.RSAPublicKey(modulus, exponent));
}

public static byte[] pubKey2Bytes_RawKey(RSAKeyParameters pubKey){

BigInteger modulus = pubKey.getModulus();
BigInteger exponent = pubKey.getExponent();

byte[] exponentBytes = exponent.toByteArray();
byte[] modulusBytes = bigInteger2Bytes(modulus,MODULUS_LENGTH);

return BytesUtils.concat(modulusBytes,exponentBytes);
}

public static RSAKeyParameters bytes2PubKey_PKCS1(byte[] pubKeyBytes) {

ASN1Sequence pubKeySequence = ASN1Sequence.getInstance(pubKeyBytes);

BigInteger modulus = ASN1Integer.getInstance(pubKeySequence.getObjectAt(0)).getValue();
BigInteger exponent = ASN1Integer.getInstance(pubKeySequence.getObjectAt(1)).getValue();

return new RSAKeyParameters(false, modulus, exponent);
}

public static RSAKeyParameters bytes2PubKey_PKCS8(byte[] pubKeyBytes) {

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);
}

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

assert publicKey != null;

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

return new RSAKeyParameters(false,modulus,exponent);
}

public static RSAKeyParameters bytes2PubKey_RawKey(byte[] pubKeyBytes) {

byte[] modulusBytes = new byte[MODULUS_LENGTH];
byte[] exponentBytes = new byte[pubKeyBytes.length - MODULUS_LENGTH];

System.arraycopy(pubKeyBytes,0, modulusBytes,0, MODULUS_LENGTH);

System.arraycopy(pubKeyBytes,MODULUS_LENGTH, exponentBytes,0,exponentBytes.length);

BigInteger modulus = new BigInteger(1, modulusBytes);
BigInteger exponent = new BigInteger(1, exponentBytes);

return new RSAKeyParameters(false,modulus,exponent);
}

/**
* This outputs the key in PKCS1v2 format.
* RSAPrivateKey ::= SEQUENCE {
* VERSION_2PRIMES Version,
* modulus INTEGER, -- n
* publicExponent INTEGER, -- e
* privateExponent INTEGER, -- d
* prime1 INTEGER, -- p
* prime2 INTEGER, -- q
* exponent1 INTEGER, -- d mod (p-1)
* exponent2 INTEGER, -- d mod (q-1)
* coefficient INTEGER, -- (inverse of q) mod p
* otherPrimeInfos OtherPrimeInfos OPTIONAL
* }
*
* Version ::= INTEGER { two-prime(0), multi(1) }
* (CONSTRAINED BY {-- version must be multi if otherPrimeInfos present --})
*
* This routine is written to output PKCS1 version 2.1, private keys.
*/
public static byte[] privKey2Bytes_PKCS1(RSAPrivateCrtKeyParameters privKey)
{
ASN1EncodableVector v = new ASN1EncodableVector();

v.add(new ASN1Integer(VERSION_2PRIMES)); // version
v.add(new ASN1Integer(privKey.getModulus()));
v.add(new ASN1Integer(privKey.getPublicExponent()));
v.add(new ASN1Integer(privKey.getExponent()));
v.add(new ASN1Integer(privKey.getP()));
v.add(new ASN1Integer(privKey.getQ()));
v.add(new ASN1Integer(privKey.getDP()));
v.add(new ASN1Integer(privKey.getDQ()));
v.add(new ASN1Integer(privKey.getQInv()));

DERSequence privKeySequence = new DERSequence(v);

byte[] result;

try {
result = privKeySequence.getEncoded(ASN1Encoding.DER);
} catch (IOException e) {
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e);
}

return result;
}

public static byte[] privKey2Bytes_PKCS8(RSAPrivateCrtKeyParameters privKey){

BigInteger modulus = privKey.getModulus();
BigInteger pubExp = privKey.getPublicExponent();
BigInteger privExp = privKey.getExponent();
BigInteger p = privKey.getP();
BigInteger q = privKey.getQ();
BigInteger dP = privKey.getDP();
BigInteger dQ = privKey.getDQ();
BigInteger qInv = privKey.getQInv();

return KeyUtil.getEncodedPrivateKeyInfo(RSA_ALGORITHM_IDENTIFIER,
new RSAPrivateKey(modulus, pubExp, privExp, p, q, dP, dQ, qInv));
}

public static byte[] privKey2Bytes_RawKey(RSAPrivateCrtKeyParameters privKey){

BigInteger modulus = privKey.getModulus();
BigInteger pubExp = privKey.getPublicExponent();
BigInteger privExp = privKey.getExponent();
BigInteger p = privKey.getP();
BigInteger q = privKey.getQ();
BigInteger dP = privKey.getDP();
BigInteger dQ = privKey.getDQ();
BigInteger qInv = privKey.getQInv();

byte[] modulusBytes = bigInteger2Bytes(modulus,MODULUS_LENGTH);
byte[] pubExpBytes = pubExp.toByteArray();
byte[] privExpBytes = bigInteger2Bytes(privExp,PRIVEXP_LENGTH);
byte[] pBytes = bigInteger2Bytes(p,P_LENGTH);
byte[] qBytes = bigInteger2Bytes(q,Q_LENGTH);
byte[] dPBytes = bigInteger2Bytes(dP,DP_LENGTH);
byte[] dQBytes = bigInteger2Bytes(dQ,DQ_LENGTH);
byte[] qInvBytes = bigInteger2Bytes(qInv,QINV_LENGTH);


return BytesUtils.concat(modulusBytes,pubExpBytes,privExpBytes,pBytes,qBytes,dPBytes,dQBytes,qInvBytes);
}

public static RSAPrivateCrtKeyParameters bytes2PrivKey_PKCS1(byte[] privKeyBytes){

ASN1Sequence priKeySequence = ASN1Sequence.getInstance(privKeyBytes);

BigInteger modulus = ASN1Integer.getInstance(priKeySequence.getObjectAt(1)).getValue();
BigInteger pubExp = ASN1Integer.getInstance(priKeySequence.getObjectAt(2)).getValue();
BigInteger privExp = ASN1Integer.getInstance(priKeySequence.getObjectAt(3)).getValue();
BigInteger p = ASN1Integer.getInstance(priKeySequence.getObjectAt(4)).getValue();
BigInteger q = ASN1Integer.getInstance(priKeySequence.getObjectAt(5)).getValue();
BigInteger dP = ASN1Integer.getInstance(priKeySequence.getObjectAt(6)).getValue();
BigInteger dQ = ASN1Integer.getInstance(priKeySequence.getObjectAt(7)).getValue();
BigInteger qInv = ASN1Integer.getInstance(priKeySequence.getObjectAt(8)).getValue();

return new RSAPrivateCrtKeyParameters(modulus, pubExp, privExp, p, q, dP, dQ, qInv);
}

public static RSAPrivateCrtKeyParameters bytes2PrivKey_PKCS8(byte[] privKeyBytes){

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);
}

RSAPrivateCrtKeyImpl privateKey;
try {
privateKey = (RSAPrivateCrtKeyImpl) keyFactory.generatePrivate(keySpec);
} catch (InvalidKeySpecException 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();
BigInteger p = privateKey.getPrimeP();
BigInteger q = privateKey.getPrimeQ();
BigInteger dP = privateKey.getPrimeExponentP();
BigInteger dQ = privateKey.getPrimeExponentQ();
BigInteger qInv = privateKey.getCrtCoefficient();

return new RSAPrivateCrtKeyParameters(modulus, pubExp, privExp, p, q, dP, dQ, qInv);
}

public static RSAPrivateCrtKeyParameters bytes2PrivKey_RawKey(byte[] privKeyBytes){

byte[] modulusBytes = new byte[MODULUS_LENGTH];
byte[] pubExpBytes = new byte[privKeyBytes.length - MODULUS_LENGTH - PRIVEXP_LENGTH - P_LENGTH - Q_LENGTH
- DP_LENGTH - DQ_LENGTH - QINV_LENGTH];
byte[] privExpBytes = new byte[PRIVEXP_LENGTH];
byte[] pBytes = new byte[P_LENGTH];
byte[] qBytes = new byte[Q_LENGTH];
byte[] dPBytes = new byte[DP_LENGTH];
byte[] dQBytes = new byte[DQ_LENGTH];
byte[] qInvBytes = new byte[QINV_LENGTH];

System.arraycopy(privKeyBytes,0, modulusBytes,0, MODULUS_LENGTH);
System.arraycopy(privKeyBytes, MODULUS_LENGTH, pubExpBytes,0,pubExpBytes.length);
System.arraycopy(privKeyBytes,MODULUS_LENGTH + pubExpBytes.length,
privExpBytes,0,PRIVEXP_LENGTH);
System.arraycopy(privKeyBytes,MODULUS_LENGTH + pubExpBytes.length + PRIVEXP_LENGTH,
pBytes,0,P_LENGTH);
System.arraycopy(privKeyBytes,MODULUS_LENGTH + pubExpBytes.length + PRIVEXP_LENGTH + P_LENGTH,
qBytes,0,Q_LENGTH);
System.arraycopy(privKeyBytes,MODULUS_LENGTH + pubExpBytes.length + PRIVEXP_LENGTH + P_LENGTH +
Q_LENGTH, dPBytes,0,DP_LENGTH);
System.arraycopy(privKeyBytes,MODULUS_LENGTH + pubExpBytes.length + PRIVEXP_LENGTH + P_LENGTH +
Q_LENGTH + DP_LENGTH, dQBytes,0,DQ_LENGTH);
System.arraycopy(privKeyBytes,MODULUS_LENGTH + pubExpBytes.length + PRIVEXP_LENGTH + P_LENGTH +
Q_LENGTH + DP_LENGTH + DQ_LENGTH, qInvBytes,0,QINV_LENGTH);

BigInteger modulus = new BigInteger(1, modulusBytes);
BigInteger pubExp = new BigInteger(1, pubExpBytes);
BigInteger privExp = new BigInteger(1, privExpBytes);
BigInteger p = new BigInteger(1, pBytes);
BigInteger q = new BigInteger(1, qBytes);
BigInteger dP = new BigInteger(1, dPBytes);
BigInteger dQ = new BigInteger(1, dQBytes);
BigInteger qInv = new BigInteger(1, qInvBytes);

return new RSAPrivateCrtKeyParameters(modulus, pubExp, privExp, p, q, dP, dQ, qInv);
}

private static byte[] bigInteger2Bytes(BigInteger src, int length){

byte[] result = new byte[length];
byte[] srcBytes = src.toByteArray();
int srcLength = srcBytes.length;

if (srcLength > length) {
System.arraycopy(srcBytes,srcLength - length,
result,0, length);
} else {
System.arraycopy(srcBytes,0,
result,length - srcLength, length);
}

return result;
}
}

+ 352
- 0
source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/ECDSASignatureFunctionTest.java View File

@@ -0,0 +1,352 @@
package test.com.jd.blockchain.crypto.service.classic;

import com.jd.blockchain.crypto.*;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
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: ECDSASignatureFunctionTest
* @description: JunitTest for ECDSASignatureFunction in SPI mode
* @date 2019-04-23, 09:37
*/
public class ECDSASignatureFunctionTest {

@Test
public void getAlgorithmTest() {

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

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

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

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

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

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

@Test
public void generateKeyPairTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("ECDSA");
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);
assertEquals(65, pubKey.getRawKeyBytes().length);
assertEquals(PRIVATE.CODE, privKey.getKeyType().CODE);
assertEquals(32, privKey.getRawKeyBytes().length);

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

assertEquals(2 + 1 + 65, pubKey.toBytes().length);
assertEquals(2 + 1 + 32, privKey.toBytes().length);

byte[] algoBytes = CryptoAlgorithm.toBytes(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("ECDSA");
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("ECDSA");
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();

assertEquals(2 + 64, signatureBytes.length);
assertEquals(ClassicAlgorithm.ECDSA.code(), signatureDigest.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 22 & 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("ECDSA");
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 supportPrivKeyTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("ECDSA");
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.toBytes(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("ECDSA");
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(32, resolvedPrivKey.getRawKeyBytes().length);
assertEquals(ClassicAlgorithm.ECDSA.code(), resolvedPrivKey.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 22 & 0x00FF)),
resolvedPrivKey.getAlgorithm());
assertArrayEquals(privKeyBytes, resolvedPrivKey.toBytes());

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.toBytes(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 {
signatureFunction.resolvePrivKey(ripemd160PubKeyBytes);
} catch (Exception e) {
actualEx = e;
}
assertNotNull(actualEx);
assertTrue(expectedException.isAssignableFrom(actualEx.getClass()));
}

@Test
public void supportPubKeyTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("ECDSA");
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.toBytes(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("ECDSA");
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(65, resolvedPubKey.getRawKeyBytes().length);
assertEquals(ClassicAlgorithm.ECDSA.code(), resolvedPubKey.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 22 & 0x00FF)),
resolvedPubKey.getAlgorithm());
assertArrayEquals(pubKeyBytes, resolvedPubKey.toBytes());

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.toBytes(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) {
actualEx = e;
}
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("ECDSA");
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.toBytes(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("ECDSA");
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);

assertEquals(64, resolvedSignatureDigest.getRawDigest().length);
assertEquals(ClassicAlgorithm.ECDSA.code(), resolvedSignatureDigest.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 22 & 0x00FF)),
resolvedSignatureDigest.getAlgorithm());
assertArrayEquals(signatureDigestBytes, resolvedSignatureDigest.toBytes());

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.toBytes(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) {
actualEx = e;
}
assertNotNull(actualEx);
assertTrue(expectedException.isAssignableFrom(actualEx.getClass()));
}
}

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

@@ -0,0 +1,488 @@
package test.com.jd.blockchain.crypto.service.classic;

import com.jd.blockchain.crypto.*;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
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: RSACryptoFunctionTest
* @description: JunitTest for RSACryptoFunction in SPI mode
* @date 2019-04-23, 15:30
*/
public class RSACryptoFunctionTest {

@Test
public void getAlgorithmTest() {

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

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

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

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

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

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

@Test
public void generateKeyPairTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
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);
assertEquals(257, pubKey.getRawKeyBytes().length);
assertEquals(PRIVATE.CODE, privKey.getKeyType().CODE);
assertEquals(1153, 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);

byte[] algoBytes = CryptoAlgorithm.toBytes(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("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);

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("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();

assertEquals(2 + 256, signatureBytes.length);
assertEquals(algorithm.code(), signatureDigest.getAlgorithm());

assertEquals(ClassicAlgorithm.RSA.code(), signatureDigest.getAlgorithm());
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();
assertEquals(2 + 256, ciphertextBytes.length);
assertEquals(ClassicAlgorithm.RSA.code(), ciphertext.getAlgorithm());

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.toBytes(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(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.toBytes(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 {
signatureFunction.resolvePrivKey(ripemd160PubKeyBytes);
} catch (Exception e) {
actualEx = e;
}
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.toBytes(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(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.toBytes(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) {
actualEx = e;
}
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.toBytes(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);

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

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.toBytes(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) {
actualEx = e;
}
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.toBytes(algorithm);
byte[] rawCiphertextBytes = ciphertext.toBytes();
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.toBytes(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) {
actualEx = e;
}
assertNotNull(actualEx);
assertTrue(expectedException.isAssignableFrom(actualEx.getClass()));
}

}

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

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

import com.jd.blockchain.crypto.utils.classic.AESUtils;
import com.jd.blockchain.utils.io.BytesUtils;
import org.bouncycastle.util.encoders.Hex;
import org.junit.Test;

import java.util.Random;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;

/**
* @author zhanglin33
* @title: AESUtilsTest
* @description: Tests for methods in AESUtils
* @date 2019-04-22, 16:06
*/
public class AESUtilsTest {

@Test
public void generateKeyTest(){
byte[] key = AESUtils.generateKey();
assertEquals(16,key.length);
key = AESUtils.generateKey("abc".getBytes());
assertArrayEquals(
Hex.decode("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad".substring(0,32)),key);
}


@Test
public void encryptTest(){
String plaintext = "abc";
String key = "1234567890123456";
System.out.println(key.getBytes().length);
String iv = "1234567890123456";
String expectedCiphertextIn2ndBlock = "f479efae2d41d23227f61e675fced95c";

byte[] ciphertext = AESUtils.encrypt(plaintext.getBytes(),key.getBytes(),iv.getBytes());
byte[] expectedCiphertext = BytesUtils.concat(iv.getBytes(),Hex.decode(expectedCiphertextIn2ndBlock));
assertArrayEquals(expectedCiphertext,ciphertext);
}


@Test
public void decryptTest(){

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

byte[] key = AESUtils.generateKey();

byte[] ciphertext = AESUtils.encrypt(data,key);
byte[] plaintext = AESUtils.decrypt(ciphertext,key);

assertArrayEquals(data,plaintext);
}
//
//
// @Test
// public void encryptingPerformance() {
//
// byte[] data = new byte[1000];
// Random random = new Random();
// random.nextBytes(data);
//
// byte[] aesCiphertext = null;
//
// int count = 100000;
//
//
// byte[] aesKey = AESUtils.generateKey();
//
// System.out.println("=================== do AES encrypt test ===================");
// for (int r = 0; r < 5; r++) {
// System.out.println("------------- round[" + r + "] --------------");
// long startTS = System.currentTimeMillis();
// for (int i = 0; i < count; i++) {
// aesCiphertext = AESUtils.encrypt(data, aesKey);
// }
// long elapsedTS = System.currentTimeMillis() - startTS;
// System.out.println(String.format("AES Encrypting Count=%s; Elapsed Times=%s; KBPS=%.2f", count, elapsedTS,
// (count * 1000.00D) / elapsedTS));
// }
//
//
// System.out.println("=================== do AES decrypt test ===================");
// for (int r = 0; r < 5; r++) {
// System.out.println("------------- round[" + r + "] --------------");
// long startTS = System.currentTimeMillis();
// for (int i = 0; i < count; i++) {
// AESUtils.decrypt(aesCiphertext, aesKey);
// }
// long elapsedTS = System.currentTimeMillis() - startTS;
// System.out.println(String.format("AES Decrypting Count=%s; Elapsed Times=%s; KBPS=%.2f", count, elapsedTS,
// (count * 1000.00D) / elapsedTS));
// }
// }
}

+ 78
- 2
source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/ECDSAUtilsTest.java View File

@@ -2,16 +2,20 @@ package test.com.jd.blockchain.crypto.utils.classic;

import com.jd.blockchain.crypto.utils.classic.ECDSAUtils;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.math.ec.ECMultiplier;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.ec.FixedPointCombMultiplier;
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.util.test.FixedSecureRandom;
import org.junit.Test;

import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Random;

import static org.junit.Assert.*;
@@ -110,6 +114,80 @@ public class ECDSAUtilsTest {
assertEquals("04" + xCoord + yCoord,Hex.toHexString(result).toUpperCase());
}

@Test
public void checkDeterministicValues(){
// https://crypto.stackexchange.com/questions/41316/complete-set-of-test-vectors-for-ecdsa-secp256k1
ECDomainParameters domainParams = ECDSAUtils.getDomainParams();
ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(
new BigInteger("ebb2c082fd7727890a28ac82f6bdf97bad8de9f5d7c9028692de1a255cad3e0f", 16),
domainParams);
ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
domainParams.getCurve().decodePoint(Hex.decode("04" +
"779dd197a5df977ed2cf6cb31d82d43328b790dc6b3b7d4437a427bd5847dfcd" +
"e94b724a555b6d017bb7607c3e3281daf5b1699d6ef4124975c9237b917d426f")),
domainParams);

byte[] privKeyBytes = BigIntegerTo32Bytes(privKey.getD());
byte[] pubKeyBytes = ECDSAUtils.retrievePublicKey(privKeyBytes);

assertArrayEquals(pubKeyBytes,pubKey.getQ().getEncoded(false));

SecureRandom k = new FixedSecureRandom(Hex.decode("49a0d7b786ec9cde0d0721d72804befd06571c974b191efb42ecf322ba9ddd9a"));
CipherParameters params = new ParametersWithRandom(privKey,k);

byte[] hashedMsg = Hex.decode("4b688df40bcedbe641ddb16ff0a1842d9c67ea1c3bf63f3e0471baa664531d1a");

byte[] signature = ECDSAUtils.sign(params,hashedMsg);

String r = "241097efbf8b63bf145c8961dbdf10c310efbb3b2676bbc0f8b08505c9e2f795";
String s = "021006b7838609339e8b415a7f9acb1b661828131aef1ecbc7955dfb01f3ca0e";
assertEquals(Hex.toHexString(signature),r + s);

assertTrue(ECDSAUtils.verify(pubKey,signature,hashedMsg));
}

@Test
public void performanceTest(){

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

AsymmetricCipherKeyPair keyPair = ECDSAUtils.generateKeyPair();
ECPrivateKeyParameters privKeyParams = (ECPrivateKeyParameters) keyPair.getPrivate();
ECPublicKeyParameters pubKeyParams = (ECPublicKeyParameters) keyPair.getPublic();

byte[] signatureDigest = ECDSAUtils.sign(data,privKeyParams);

assertTrue(ECDSAUtils.verify(data,pubKeyParams,signatureDigest));

System.out.println("=================== do ECDSA sign test ===================");

for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
ECDSAUtils.sign(data,privKeyParams);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("ECDSA Signing Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do ECDSA verify test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
ECDSAUtils.verify(data,pubKeyParams,signatureDigest);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("ECDSA Verifying Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}
}

// To convert BigInteger to byte[] whose length is 32
private static byte[] BigIntegerTo32Bytes(BigInteger b){
byte[] tmp = b.toByteArray();
@@ -122,6 +200,4 @@ public class ECDSAUtilsTest {
}
return result;
}


}

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

@@ -108,4 +108,76 @@ public class ED25519UtilsTest {
assertTrue(Ed25519Utils.verify(data,pubKeyBytes,signatureDigest));

}

@Test
public void performanceTest(){

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

AsymmetricCipherKeyPair keyPair = ED25519Utils.generateKeyPair();
Ed25519PrivateKeyParameters privKeyParams = (Ed25519PrivateKeyParameters) keyPair.getPrivate();
Ed25519PublicKeyParameters pubKeyParams = (Ed25519PublicKeyParameters) keyPair.getPublic();

byte[] pubKeyBytes = pubKeyParams.getEncoded();
byte[] privKeyBytes = privKeyParams.getEncoded();

byte[] signatureDigest = ED25519Utils.sign(data,privKeyParams);

assertTrue(ED25519Utils.verify(data,pubKeyParams,signatureDigest));

System.out.println("=================== do ED25519 sign test ===================");

for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
ED25519Utils.sign(data,privKeyParams);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("ED25519 Signing Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do ED25519 verify test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
ED25519Utils.verify(data,pubKeyParams,signatureDigest);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("ED25519 Verifying Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do ED25519 sign test ===================");

for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
Ed25519Utils.sign_512(data,privKeyBytes);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("ED25519 Signing Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do ED25519 verify test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
Ed25519Utils.verify(data,pubKeyBytes,signatureDigest);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("ED25519 Verifying Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

}

}

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

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

import com.jd.blockchain.crypto.utils.classic.RIPEMD160Utils;
import org.bouncycastle.util.encoders.Hex;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

/**
* @author zhanglin33
* @title: RIPEMD160UtilsTest
* @description: Tests for the hash method in RIPEMD160Utils
* @date 2019-04-10, 16:54
*/
public class RIPEMD160UtilsTest {

@Test
public void hashTest() {

byte[] data1 = "a".getBytes();
byte[] data2 = "abc".getBytes();

byte[] result1 = RIPEMD160Utils.hash(data1);
byte[] result2 = RIPEMD160Utils.hash(data2);

String respectedResult1 = "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe";
String respectedResult2 = "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc";

assertEquals(respectedResult1, Hex.toHexString(result1));
assertEquals(respectedResult2, Hex.toHexString(result2));
}
}

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

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

import com.jd.blockchain.crypto.utils.classic.RSAUtils;
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.junit.Test;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Random;

import static org.junit.Assert.*;

/**
* @author zhanglin33
* @title: RSAUtilsTest
* @description: Tests for methods in RSAUtils
* @date 2019-04-11, 17:10
*/
public class RSAUtilsTest {

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

byte[] pubKeyBytes_RawKey = RSAUtils.pubKey2Bytes_RawKey(pubKey);
byte[] pubKeyBytesConverted_RawKey =
RSAUtils.pubKey2Bytes_RawKey(RSAUtils.bytes2PubKey_RawKey(pubKeyBytes_RawKey));
assertArrayEquals(pubKeyBytes_RawKey,pubKeyBytesConverted_RawKey);

byte[] privKeyBytes_RawKey = RSAUtils.privKey2Bytes_RawKey(privKey);
byte[] privKeyBytesConverted_RawKey =
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));
assertArrayEquals(pubKeyBytes_PKCS1,pubKeyBytesConverted_PKCS1);

byte[] privKeyBytes_PKCS1 = RSAUtils.privKey2Bytes_PKCS1(privKey);
byte[] privKeyBytesConverted_PKCS1 =
RSAUtils.privKey2Bytes_PKCS1(RSAUtils.bytes2PrivKey_PKCS1(privKeyBytes_PKCS1));
assertArrayEquals(privKeyBytes_PKCS1,privKeyBytesConverted_PKCS1);

byte[] pubKeyBytes_PKCS8 = RSAUtils.pubKey2Bytes_PKCS8(pubKey);
byte[] pubKeyBytesConverted_PKCS8 =
RSAUtils.pubKey2Bytes_PKCS8(RSAUtils.bytes2PubKey_PKCS8(pubKeyBytes_PKCS8));
assertArrayEquals(pubKeyBytes_PKCS8,pubKeyBytesConverted_PKCS8);

byte[] privKeyBytes_PKCS8 = RSAUtils.privKey2Bytes_PKCS8(privKey);
byte[] privKeyBytesConverted_PKCS8 =
RSAUtils.privKey2Bytes_PKCS8(RSAUtils.bytes2PrivKey_PKCS8(privKeyBytes_PKCS8));
assertArrayEquals(privKeyBytes_PKCS8,privKeyBytesConverted_PKCS8);
}

@Test
public void retrievePublicKeyTest(){

AsymmetricCipherKeyPair kp = RSAUtils.generateKeyPair();
RSAKeyParameters pubKey = (RSAKeyParameters) kp.getPublic();
RSAPrivateCrtKeyParameters privKey = (RSAPrivateCrtKeyParameters) kp.getPrivate();

byte[] privKeyBytes = RSAUtils.privKey2Bytes_RawKey(privKey);
byte[] pubKeyBytes = RSAUtils.pubKey2Bytes_RawKey(pubKey);
byte[] retrievedPubKeyBytes = RSAUtils.retrievePublicKey(privKeyBytes);

assertArrayEquals(pubKeyBytes,retrievedPubKeyBytes);
}

@Test
public void signTest(){

byte[] data = new byte[1024];
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);

boolean isValidFromPubKey = RSAUtils.verify(data, pubKey, signature);
boolean isValidFromPubKeyBytes = RSAUtils.verify(data, pubKeyBytes, signature);

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(){

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);

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

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


@Test
public void performanceTest(){

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

AsymmetricCipherKeyPair keyPair = RSAUtils.generateKeyPair();
AsymmetricKeyParameter privKey = keyPair.getPrivate();
AsymmetricKeyParameter pubKey = keyPair.getPublic();

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

System.out.println("=================== do RSA sign test ===================");

for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
RSAUtils.sign(data,privKey);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("RSA Signing Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do RSA verify test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
RSAUtils.verify(data,pubKey,signature);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("RSA Verifying Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do RSA encrypt test ===================");

for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
RSAUtils.encrypt(data,pubKey);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("RSA Encrypting Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do RSA decrypt test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
RSAUtils.decrypt(ciphertext,privKey);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("RSA Decrypting Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}
}

@Test
public void encryptionConsistencyTest(){

int count = 10000;
byte[] data = new byte[222];
Random random = new Random();
random.nextBytes(data);

KeyPairGenerator keyPairGen = null;
try {
keyPairGen = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
assert keyPairGen != null;
keyPairGen.initialize(2048, new SecureRandom());
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

byte[] publicKeyBytes = publicKey.getEncoded();
byte[] privateKeyBytes = privateKey.getEncoded();

RSAKeyParameters pubKey = RSAUtils.bytes2PubKey_PKCS8(publicKeyBytes);
RSAPrivateCrtKeyParameters privKey = RSAUtils.bytes2PrivKey_PKCS8(privateKeyBytes);

Cipher cipher;
byte[] ciphertext = null;
byte[] plaintext = null;

System.out.println("=================== do BouncyCastle-based RSA encrypt test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
ciphertext = RSAUtils.encrypt(data,pubKey);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("BouncyCastle-based RSA Encrypting Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

assert ciphertext != null;
System.out.println("=================== do BouncyCastle-based RSA decrypt test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
plaintext = RSAUtils.decrypt(ciphertext,privKey);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("BouncyCastle-based RSA Decrypting Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do JDK-based RSA encrypt test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
try {
cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
ciphertext = cipher.doFinal(data);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
| IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
}
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("JDK-based RSA Encrypting Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do JDK-based RSA decrypt test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
try {
cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
plaintext = cipher.doFinal(ciphertext);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
| IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
}
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("JDK-based RSA Decrypting Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}


assertArrayEquals(data,plaintext);
assertArrayEquals(data,plaintext);
}

@Test
public void signatureConsistencyTest() {

int count = 10000;
byte[] data = new byte[222];
Random random = new Random();
random.nextBytes(data);

KeyPairGenerator keyPairGen = null;
try {
keyPairGen = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
assert keyPairGen != null;
keyPairGen.initialize(2048, new SecureRandom());
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

byte[] publicKeyBytes = publicKey.getEncoded();
byte[] privateKeyBytes = privateKey.getEncoded();

byte[] signature = null;
boolean isValid = false;

RSAKeyParameters pubKey = RSAUtils.bytes2PubKey_PKCS8(publicKeyBytes);
RSAPrivateCrtKeyParameters privKey = RSAUtils.bytes2PrivKey_PKCS8(privateKeyBytes);

System.out.println("=================== do BouncyCastle-based RSA sign test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
signature = RSAUtils.sign(data,privKey);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("BouncyCastle-based RSA Signing Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do BouncyCastle-based RSA verify test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
isValid = RSAUtils.verify(data,pubKey,signature);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("BouncyCastle-based RSA Verifying Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}




System.out.println("=================== do JDK-based RSA sign test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
try {
Signature signer = Signature.getInstance("SHA256withRSA");
signer.initSign(privateKey);
signer.update(data);
signature = signer.sign();
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
e.printStackTrace();
}
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("JDK-based RSA Signing Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do JDK-based RSA verify test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
try {
Signature verifier = Signature.getInstance("SHA256withRSA");
verifier.initVerify(publicKey);
verifier.update(data);
isValid = verifier.verify(signature);
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
e.printStackTrace();
}
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("JDK-based RSA Verifying Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println(isValid);

}
}

+ 1
- 1
source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/SHA256UtilsTest.java View File

@@ -9,7 +9,7 @@ import static org.junit.Assert.assertEquals;
/**
* @author zhanglin33
* @title: SHA256UtilsTest
* @description: Tests for the hash method in ECDSAUtils
* @description: Tests for the hash method in SHA256Utils
* @date 2019-04-09, 16:18
*/
public class SHA256UtilsTest {


+ 3
- 3
source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/BaseCryptoKey.java View File

@@ -7,9 +7,9 @@ public abstract class BaseCryptoKey extends BaseCryptoBytes implements CryptoKey
public static final int KEY_TYPE_BYTES = 1;
private static final long serialVersionUID = 4543074827807908363L;

// public BaseCryptoKey() {
// super();
// }
public BaseCryptoKey() {
super();
}

protected BaseCryptoKey(short algorithm, byte[] rawKeyBytes, CryptoKeyType keyType) {
super(algorithm, CryptoBytesEncoding.encodeKeyBytes(rawKeyBytes, keyType));


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

@@ -7,6 +7,7 @@ package com.jd.blockchain.crypto;
*
*/
public class PrivKey extends BaseCryptoKey {
private static final long serialVersionUID = 6265440395252295646L;
public PrivKey(short algorithm, byte[] rawCryptoBytes) {


+ 5
- 1
source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/PubKey.java View File

@@ -9,7 +9,11 @@ package com.jd.blockchain.crypto;
public class PubKey extends BaseCryptoKey {

private static final long serialVersionUID = -2055071197736385328L;

public PubKey() {
super();
}

public PubKey(short algorithm, byte[] rawCryptoBytes) {
super(algorithm, rawCryptoBytes, CryptoKeyType.PUBLIC);
}


+ 0
- 78
source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/serialize/ByteArrayObjectDeserializer.java View File

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

import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.JSONToken;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.crypto.SignatureDigest;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.codec.Base58Utils;
import com.jd.blockchain.utils.io.BytesSlice;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;
import java.util.Map;

public class ByteArrayObjectDeserializer extends JavaBeanDeserializer {

private ByteArrayObjectDeserializer(Class<?> clazz) {
super(ParserConfig.global, clazz);
}

public static ByteArrayObjectDeserializer getInstance(Class<?> clazz) {
return new ByteArrayObjectDeserializer(clazz);
}

@SuppressWarnings("unchecked")
@Override
public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
if (type instanceof Class && clazz.isAssignableFrom((Class<?>) type)) {
String base58Str = parser.parseObject(String.class);
byte[] hashBytes = Base58Utils.decode(base58Str);
if (clazz == HashDigest.class) {
return (T) new HashDigest(hashBytes);
} else if (clazz == PubKey.class) {
return (T) new HashDigest(hashBytes);
} else if (clazz == SignatureDigest.class) {
return (T) new SignatureDigest(hashBytes);
} else if (clazz == Bytes.class) {
return (T) new Bytes(hashBytes);
} else if (clazz == BytesSlice.class) {
return (T) new BytesSlice(hashBytes);
}
}
return (T) parser.parse(fieldName);
}

@Override
public Object createInstance(Map<String, Object> map, ParserConfig config) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
if (map == null || map.isEmpty()) {
return null;
}
for (Map.Entry<String, Object> entry : map.entrySet()) {
Object value = entry.getValue();
if (value instanceof String) {
byte[] hashBytes = Base58Utils.decode((String)value);
if (clazz == HashDigest.class) {
return new HashDigest(hashBytes);
} else if (clazz == PubKey.class) {
return new PubKey(hashBytes);
} else if (clazz == SignatureDigest.class) {
return new SignatureDigest(hashBytes);
} else if (clazz == Bytes.class) {
return new Bytes(hashBytes);
} else if (clazz == BytesSlice.class) {
return new BytesSlice(hashBytes);
}
}
}
return null;
}

@Override
public int getFastMatchToken() {
return JSONToken.LBRACE;
}
}

+ 0
- 63
source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/serialize/ByteArrayObjectSerializer.java View File

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

import java.lang.reflect.Type;

import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.crypto.SignatureDigest;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.io.BytesSlice;

public class ByteArrayObjectSerializer implements ObjectSerializer {

private Class<?> clazz;

private ByteArrayObjectSerializer(Class<?> clazz) {
this.clazz = clazz;
}

public static ByteArrayObjectSerializer getInstance(Class<?> clazz) {
return new ByteArrayObjectSerializer(clazz);
}

@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) {
if (object.getClass() != clazz) {
serializer.writeNull();
return;
}
if (object instanceof HashDigest) {
serializer.write(new HashDigestJson(((HashDigest) object).toBase58()));
} else if (object instanceof PubKey) {
serializer.write(new HashDigestJson(((PubKey) object).toBase58()));
} else if (object instanceof SignatureDigest) {
serializer.write(new HashDigestJson(((SignatureDigest) object).toBase58()));
} else if (object instanceof Bytes) {
serializer.write(new HashDigestJson(((Bytes) object).toBase58()));
} else if (object instanceof BytesSlice) {
byte[] bytes = ((BytesSlice) object).toBytes();
serializer.write(new HashDigestJson(new String(bytes)));
}
}

private static class HashDigestJson {

String value;

public HashDigestJson(String value) {
this.value = value;
}

@SuppressWarnings("unused")
public String getValue() {
return value;
}

@SuppressWarnings("unused")
public void setValue(String value) {
this.value = value;
}
}
}

+ 5
- 13
source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/service/sm/SM2CryptoFunction.java View File

@@ -72,7 +72,7 @@ public class SM2CryptoFunction implements AsymmetricEncryptionFunction, Signatur
throw new CryptoException("This key is not SM2 private key!");
}

// 验证密文数据的算法标识对应SM2签名算法,并且原始摘要长度为64字节
// 验证密文数据的算法标识对应SM2算法,并且密文符合长度要求
if (ciphertext.getAlgorithm() != SM2.code()
|| rawCiphertextBytes.length < ECPOINT_SIZE + HASHDIGEST_SIZE) {
throw new CryptoException("This is not SM2 ciphertext!");
@@ -89,14 +89,6 @@ public class SM2CryptoFunction implements AsymmetricEncryptionFunction, Signatur
return new PubKey(SM2, rawPubKeyBytes);
}

// @Override
// public byte[] retrievePubKey(byte[] privKeyBytes) {
//
// byte[] rawPrivKeyBytes = resolvePrivKey(privKeyBytes).getRawKeyBytes();
// byte[] rawPubKeyBytes = SM2Utils.retrievePublicKey(rawPrivKeyBytes);
// return new PubKey(SM2, rawPubKeyBytes).toBytes();
// }

@Override
public boolean supportPrivKey(byte[] privKeyBytes) {
// 验证输入字节数组长度=算法标识长度+密钥类型长度+密钥长度,密钥数据的算法标识对应SM2算法,并且密钥类型是私钥
@@ -109,7 +101,7 @@ public class SM2CryptoFunction implements AsymmetricEncryptionFunction, Signatur
if (supportPrivKey(privKeyBytes)) {
return new PrivKey(privKeyBytes);
} else {
throw new CryptoException("privKeyBytes is invalid!");
throw new CryptoException("privKeyBytes are invalid!");
}
}

@@ -125,7 +117,7 @@ public class SM2CryptoFunction implements AsymmetricEncryptionFunction, Signatur
if (supportPubKey(pubKeyBytes)) {
return new PubKey(pubKeyBytes);
} else {
throw new CryptoException("pubKeyBytes is invalid!");
throw new CryptoException("pubKeyBytes are invalid!");
}
}

@@ -141,7 +133,7 @@ public class SM2CryptoFunction implements AsymmetricEncryptionFunction, Signatur
if (supportCiphertext(ciphertextBytes)) {
return new AsymmetricCiphertext(ciphertextBytes);
} else {
throw new CryptoException("ciphertextBytes is invalid!");
throw new CryptoException("ciphertextBytes are invalid!");
}
}

@@ -200,7 +192,7 @@ public class SM2CryptoFunction implements AsymmetricEncryptionFunction, Signatur
if (supportDigest(digestBytes)) {
return new SignatureDigest(digestBytes);
} else {
throw new CryptoException("digestBytes is invalid!");
throw new CryptoException("digestBytes are invalid!");
}
}



+ 25
- 4
source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/utils/sm/SM4Utils.java View File

@@ -11,11 +11,12 @@ import org.bouncycastle.crypto.params.ParametersWithIV;


import java.security.SecureRandom;
import java.util.Arrays;

public class SM4Utils {

// SM4 supports 128-bit secret key
private static final int KEY_LENGTH = 128;
// SM4 supports 128-bit(16 bytes) secret key
private static final int KEY_SIZE = 128 / 8;
// One block contains 16 bytes
private static final int BLOCK_SIZE = 16;
// Initial vector's size is 16 bytes
@@ -33,12 +34,17 @@ public class SM4Utils {

// To provide secure randomness and key length as input
// to prepare generate private key
keyGenerator.init(new KeyGenerationParameters(new SecureRandom(), KEY_LENGTH));
keyGenerator.init(new KeyGenerationParameters(new SecureRandom(), KEY_SIZE * 8));

// To generate key
return keyGenerator.generateKey();
}

public static byte[] generateKey(byte[] seed){
byte[] hash = SM3Utils.hash(seed);
return Arrays.copyOf(hash, KEY_SIZE);
}


/**
* encryption
@@ -56,6 +62,16 @@ public class SM4Utils {
throw new CryptoException("plaintext is null!");
}

if (secretKey.length != KEY_SIZE)
{
throw new CryptoException("secretKey's length is wrong!");
}

if (iv.length != IV_SIZE)
{
throw new CryptoException("iv's length is wrong!");
}

// To get the value padded into input
int padding = 16 - plainBytes.length % BLOCK_SIZE;
// The plaintext with padding value
@@ -105,11 +121,16 @@ public class SM4Utils {
}

// To ensure that the ciphertext's length is integral multiples of 16 bytes
if ( cipherBytes.length % BLOCK_SIZE != 0 )
if (cipherBytes.length % BLOCK_SIZE != 0)
{
throw new CryptoException("ciphertext's length is wrong!");
}

if (secretKey.length != KEY_SIZE)
{
throw new CryptoException("secretKey's length is wrong!");
}

byte[] iv = new byte[IV_SIZE];
System.arraycopy(cipherBytes,0,iv,0,BLOCK_SIZE);



+ 0
- 1
source/crypto/crypto-sm/src/test/java/test/com/jd/blockchain/crypto/service/sm/SM2CyptoFunctionTest.java View File

@@ -484,5 +484,4 @@ public class SM2CyptoFunctionTest {
assertNotNull(actualEx);
assertTrue(expectedException.isAssignableFrom(actualEx.getClass()));
}

}

+ 42
- 70
source/crypto/crypto-sm/src/test/java/test/com/jd/blockchain/crypto/utils/SM2UtilsTest.java View File

@@ -13,6 +13,8 @@ import org.junit.Test;

import com.jd.blockchain.crypto.utils.sm.SM2Utils;

import java.util.Random;

public class SM2UtilsTest {

@Test
@@ -160,74 +162,44 @@ public class SM2UtilsTest {
// }
//
//
// @Test
// public void signingPerformace(){
//
// byte[] data = new byte[1000];
// Random random = new Random();
// random.nextBytes(data);
//
// int count = 10000;
//
// byte[] sm2Digest = null;
// byte[] ed25519Digest = null;
//
// AsymmetricCipherKeyPair keyPair = SM2Utils.generateKeyPair();
// ECPublicKeyParameters ecPub = (ECPublicKeyParameters) keyPair.getPublic();
// ECPrivateKeyParameters ecPriv = (ECPrivateKeyParameters) keyPair.getPrivate();
//
// System.out.println("=================== do SM2 sign test ===================");
//
// for (int r = 0; r < 5; r++) {
// System.out.println("------------- round[" + r + "] --------------");
// long startTS = System.currentTimeMillis();
// for (int i = 0; i < count; i++) {
// sm2Digest = SM2Utils.sign(data,ecPriv);
// }
// long elapsedTS = System.currentTimeMillis() - startTS;
// System.out.println(String.format("SM2 Signing Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
// (count * 1000.00D) / elapsedTS));
// }
//
// System.out.println("=================== do SM2 verify test ===================");
// for (int r = 0; r < 5; r++) {
// System.out.println("------------- round[" + r + "] --------------");
// long startTS = System.currentTimeMillis();
// for (int i = 0; i < count; i++) {
// SM2Utils.verify(data,ecPub,sm2Digest);
// }
// long elapsedTS = System.currentTimeMillis() - startTS;
// System.out.println(String.format("SM2 Verifying Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
// (count * 1000.00D) / elapsedTS));
// }
//
// KeyPairGenerator keyPairGenerator = new KeyPairGenerator();
// KeyPair ed25519KeyPair = keyPairGenerator.generateKeyPair();
// EdDSAPrivateKey privKey = (EdDSAPrivateKey) ed25519KeyPair.getPrivate();
// EdDSAPublicKey pubKey = (EdDSAPublicKey) ed25519KeyPair.getPublic();
//
// System.out.println("=================== do ED25519 sign test ===================");
// for (int r = 0; r < 5; r++) {
// System.out.println("------------- round[" + r + "] --------------");
// long startTS = System.currentTimeMillis();
// for (int i = 0; i < count; i++) {
// ed25519Digest = Ed25519Utils.sign_512(data,privKey.getSeed());
// }
// long elapsedTS = System.currentTimeMillis() - startTS;
// System.out.println(String.format("ED25519 Signing Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
// (count * 1000.00D) / elapsedTS));
// }
//
// System.out.println("=================== do ED25519 verify test ===================");
// for (int r = 0; r < 5; r++) {
// System.out.println("------------- round[" + r + "] --------------");
// long startTS = System.currentTimeMillis();
// for (int i = 0; i < count; i++) {
// Ed25519Utils.verify(data,pubKey.getAbyte(),ed25519Digest);
// }
// long elapsedTS = System.currentTimeMillis() - startTS;
// System.out.println(String.format("ED25519 Verifying Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
// (count * 1000.00D) / elapsedTS));
// }
// }
@Test
public void signingPerformace(){

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

int count = 10000;

byte[] sm2Digest = null;

AsymmetricCipherKeyPair keyPair = SM2Utils.generateKeyPair();
ECPublicKeyParameters ecPub = (ECPublicKeyParameters) keyPair.getPublic();
ECPrivateKeyParameters ecPriv = (ECPrivateKeyParameters) keyPair.getPrivate();

System.out.println("=================== do SM2 sign test ===================");

for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
sm2Digest = SM2Utils.sign(data,ecPriv);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("SM2 Signing Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do SM2 verify test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
SM2Utils.verify(data,ecPub,sm2Digest);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("SM2 Verifying Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}
}
}

+ 22
- 0
source/deployment/deployment-peer/pom.xml View File

@@ -25,6 +25,28 @@
<artifactId>runtime-modular-booter</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>storage-composite</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>storage-service</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>storage-redis</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>storage-rocksdb</artifactId>
<version>${project.version}</version>
</dependency>

<!-- <dependency> <groupId>com.jd.blockchain</groupId> <artifactId>gateway</artifactId>
<version>${project.version}</version> </dependency> -->



+ 0
- 9
source/deployment/deployment-peer/src/main/resources/assembly.xml View File

@@ -62,15 +62,6 @@
<useAllReactorProjects>true</useAllReactorProjects>
<includes>
<include>com.jd.blockchain:tools-initializer-booter</include>
</includes>
<binaries>
<outputDirectory>libs</outputDirectory>
<unpack>false</unpack>
</binaries>
</moduleSet>
<moduleSet>
<useAllReactorProjects>true</useAllReactorProjects>
<includes>
<include>com.jd.blockchain:tools-keygen-booter</include>
</includes>
<binaries>


+ 1
- 0
source/gateway/.gitignore View File

@@ -1 +1,2 @@
/target/
/.apt_generated_tests/

+ 23
- 1
source/gateway/pom.xml View File

@@ -15,6 +15,17 @@
<artifactId>consensus-framework</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>consensus-bftsmart</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>consensus-mq</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>ledger-rpc</artifactId>
@@ -43,11 +54,22 @@
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>crypto-framework</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>crypto-classic</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>crypto-sm</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>


+ 10
- 0
source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryService.java View File

@@ -2,6 +2,7 @@ package com.jd.blockchain.gateway.service;

import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.sdk.LedgerInitSettings;

/**
* queryService only for gateway;
@@ -24,4 +25,13 @@ public interface GatewayQueryService {
* @return
*/
ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash, int fromIndex, int count);

/**
* 获取账本初始化配置信息
*
* @param ledgerHash
* 账本Hash
* @return
*/
LedgerInitSettings getLedgerInitSettings(HashDigest ledgerHash);
}

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

@@ -0,0 +1,144 @@
package com.jd.blockchain.gateway.service;

import com.jd.blockchain.consensus.ConsensusProvider;
import com.jd.blockchain.consensus.ConsensusProviders;
import com.jd.blockchain.consensus.ConsensusSettings;
import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider;
import com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.gateway.PeerService;
import com.jd.blockchain.ledger.LedgerMetadata;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.sdk.LedgerInitSettings;
import com.jd.blockchain.utils.QueryUtil;
import com.jd.blockchain.utils.codec.HexUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;


/**
* @Author zhaogw
* @Date 2019/2/22 10:39
*/
@Component
public class GatewayQueryServiceHandler implements GatewayQueryService {

@Autowired
private PeerService peerService;

@Override
public HashDigest[] getLedgersHash(int fromIndex, int count) {
HashDigest ledgersHash[] = peerService.getQueryService().getLedgerHashs();
int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex,count,ledgersHash.length);
HashDigest ledgersHashNew[] = Arrays.copyOfRange(ledgersHash,indexAndCount[0],indexAndCount[0]+indexAndCount[1]);
return ledgersHashNew;
}

@Override
public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash, int fromIndex, int count) {
ParticipantNode participantNode[] = peerService.getQueryService().getConsensusParticipants(ledgerHash);
int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex,count,participantNode.length);
ParticipantNode participantNodesNew[] = Arrays.copyOfRange(participantNode,indexAndCount[0],indexAndCount[0]+indexAndCount[1]);
return participantNodesNew;
}

@Override
public LedgerInitSettings getLedgerInitSettings(HashDigest ledgerHash) {

ParticipantNode[] participantNodes = peerService.getQueryService().getConsensusParticipants(ledgerHash);

LedgerMetadata ledgerMetadata = peerService.getQueryService().getLedgerMetadata(ledgerHash);

return initLedgerInitSettings(participantNodes, ledgerMetadata);
}

/**
* 初始化账本配置
*
* @param participantNodes
* 参与方列表
* @param ledgerMetadata
* 账本元数据
* @return
*/
private LedgerInitSettings initLedgerInitSettings(ParticipantNode[] participantNodes, LedgerMetadata ledgerMetadata) {
LedgerInitSettings ledgerInitSettings = new LedgerInitSettings();

// 设置参与方
ledgerInitSettings.setParticipantNodes(participantNodes);

// 设置共识设置
ledgerInitSettings.setConsensusSettings(initConsensusSettings(ledgerMetadata));

// 设置参与方根Hash
ledgerInitSettings.setParticipantsHash(ledgerMetadata.getParticipantsHash());

// 设置算法配置
ledgerInitSettings.setCryptoSetting(ledgerMetadata.getSetting().getCryptoSetting());

// 设置种子
ledgerInitSettings.setSeed(initSeed(ledgerMetadata.getSeed()));

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

return ledgerInitSettings;
}

/**
* 初始化账本种子信息
*
* @param seedBytes
* 种子的字节数组显示
* @return
* 种子以十六进制方式显示,为方便阅读,每隔八个字符中间以"-"分割
*/
private String initSeed(byte[] seedBytes) {
String seedString = HexUtils.encode(seedBytes);
// 每隔八个字符中加入一个一个横线
StringBuffer seed = new StringBuffer();

for( int i = 0; i < seedString.length(); i++) {
char c = seedString.charAt(i);
if (i != 0 && i % 8 == 0) {
seed.append("-");
}
seed.append(c);
}

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();
}

/**
* 初始化共识配置
*
* @param ledgerMetadata
* 账本元数据
* @return
*/
private ConsensusSettings initConsensusSettings(LedgerMetadata ledgerMetadata) {
String consensusProvider = ledgerMetadata.getSetting().getConsensusProvider();
ConsensusProvider provider = ConsensusProviders.getProvider(consensusProvider);
byte[] consensusSettingsBytes = ledgerMetadata.getSetting().getConsensusSetting().toBytes();
return provider.getSettingsFactory().getConsensusSettingsEncoder().decode(consensusSettingsBytes);
}
}

+ 37
- 37
source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceImpl.java View File

@@ -1,37 +1,37 @@
package com.jd.blockchain.gateway.service;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.gateway.PeerService;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.utils.QueryUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import static com.jd.blockchain.utils.BaseConstant.QUERY_LIST_MAX;
/**
* @Author zhaogw
* @Date 2019/2/22 10:39
*/
@Component
public class GatewayQueryServiceImpl implements GatewayQueryService {
@Autowired
private PeerService peerService;
@Override
public HashDigest[] getLedgersHash(int fromIndex, int count) {
HashDigest ledgersHash[] = peerService.getQueryService().getLedgerHashs();
int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex,count,ledgersHash.length);
HashDigest ledgersHashNew[] = Arrays.copyOfRange(ledgersHash,indexAndCount[0],indexAndCount[0]+indexAndCount[1]);
return ledgersHashNew;
}
@Override
public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash, int fromIndex, int count) {
ParticipantNode participantNode[] = peerService.getQueryService().getConsensusParticipants(ledgerHash);
int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex,count,participantNode.length);
ParticipantNode participantNodesNew[] = Arrays.copyOfRange(participantNode,indexAndCount[0],indexAndCount[0]+indexAndCount[1]);
return participantNodesNew;
}
}
//package com.jd.blockchain.gateway.service;
//
//import com.jd.blockchain.crypto.HashDigest;
//import com.jd.blockchain.gateway.PeerService;
//import com.jd.blockchain.ledger.ParticipantNode;
//import com.jd.blockchain.utils.QueryUtil;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Component;
//import java.util.Arrays;
//
//import static com.jd.blockchain.utils.BaseConstant.QUERY_LIST_MAX;
//
///**
// * @Author zhaogw
// * @Date 2019/2/22 10:39
// */
//@Component
//public class GatewayQueryServiceImpl implements GatewayQueryService {
// @Autowired
// private PeerService peerService;
//
// @Override
// public HashDigest[] getLedgersHash(int fromIndex, int count) {
// HashDigest ledgersHash[] = peerService.getQueryService().getLedgerHashs();
// int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex,count,ledgersHash.length);
// HashDigest ledgersHashNew[] = Arrays.copyOfRange(ledgersHash,indexAndCount[0],indexAndCount[0]+indexAndCount[1]);
// return ledgersHashNew;
// }
//
// @Override
// public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash, int fromIndex, int count) {
// ParticipantNode participantNode[] = peerService.getQueryService().getConsensusParticipants(ledgerHash);
// int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex,count,participantNode.length);
// ParticipantNode participantNodesNew[] = Arrays.copyOfRange(participantNode,indexAndCount[0],indexAndCount[0]+indexAndCount[1]);
// return participantNodesNew;
// }
//}

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

@@ -8,6 +8,7 @@ import com.jd.blockchain.gateway.service.DataRetrievalService;
import com.jd.blockchain.gateway.service.GatewayQueryService;
import com.jd.blockchain.ledger.*;
import com.jd.blockchain.sdk.BlockchainExtendQueryService;
import com.jd.blockchain.sdk.LedgerInitSettings;
import com.jd.blockchain.tools.keygen.KeyGenCommand;
import com.jd.blockchain.utils.BaseConstant;
import com.jd.blockchain.utils.ConsoleUtils;
@@ -58,6 +59,17 @@ public class BlockBrowserController implements BlockchainExtendQueryService {
return peerService.getQueryService().getConsensusParticipants(ledgerHash);
}

@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/metadata")
@Override
public LedgerMetadata getLedgerMetadata(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
return peerService.getQueryService().getLedgerMetadata(ledgerHash);
}

@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/settings")
public LedgerInitSettings getLedgerInitSettings(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
return gatewayQueryService.getLedgerInitSettings(ledgerHash);
}

@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks")
public LedgerBlock[] getBlocks(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
LedgerInfo ledgerInfo = peerService.getQueryService().getLedger(ledgerHash);


+ 5
- 22
source/gateway/src/main/java/com/jd/blockchain/gateway/web/GatewayWebServerConfigurer.java View File

@@ -2,7 +2,7 @@ package com.jd.blockchain.gateway.web;

import java.util.List;

import com.jd.blockchain.utils.io.BytesSlice;
import com.jd.blockchain.web.serializes.ByteArrayObjectUtil;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
@@ -11,12 +11,6 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.crypto.SignatureDigest;
import com.jd.blockchain.crypto.serialize.ByteArrayObjectDeserializer;
import com.jd.blockchain.crypto.serialize.ByteArrayObjectSerializer;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.io.ByteArray;
import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils;
import com.jd.blockchain.utils.web.model.JsonWebResponseMessageConverter;
@@ -30,13 +24,6 @@ import com.jd.blockchain.web.converters.HashDigestInputConverter;
@Configuration
public class GatewayWebServerConfigurer implements WebMvcConfigurer {

private static final Class<?>[] BYTEARRAY_JSON_SERIALIZE_CLASS = new Class<?>[] {
HashDigest.class,
PubKey.class,
SignatureDigest.class,
Bytes.class,
BytesSlice.class};

static {
JSONSerializeUtils.disableCircularReferenceDetect();
JSONSerializeUtils.configStringSerializer(ByteArray.class);
@@ -67,11 +54,11 @@ public class GatewayWebServerConfigurer implements WebMvcConfigurer {
registry.addConverter(new HashDigestInputConverter());
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources");
}
}

@Override
public void addViewControllers(ViewControllerRegistry registry) {
@@ -79,10 +66,6 @@ public class GatewayWebServerConfigurer implements WebMvcConfigurer {
}

private void initByteArrayJsonSerialize() {
for (Class<?> byteArrayClass : BYTEARRAY_JSON_SERIALIZE_CLASS) {
JSONSerializeUtils.configSerialization(byteArrayClass,
ByteArrayObjectSerializer.getInstance(byteArrayClass),
ByteArrayObjectDeserializer.getInstance(byteArrayClass));
}
ByteArrayObjectUtil.init();
}
}

+ 10
- 8
source/gateway/src/main/resources/gateway.conf View File

@@ -1,28 +1,30 @@
#网关的HTTP服务地址;
http.host=127.0.0.1
http.host=0.0.0.0
#网关的HTTP服务端口;
http.port=8081
#网关的HTTP服务上下文路径,可选;
#http.context-path=
#共识节点的服务地址;
#共识节点的服务地址(与该网关节点连接的Peer节点的IP地址)
peer.host=127.0.0.1
#共识节点的服务端口;
peer.port=7080
#共识节点的服务端口(与该网关节点连接的Peer节点的端口)
peer.port=12000
#共识节点的服务是否启用安全证书;
peer.secure=false
#共识节点的服务提供解析器
#BftSmart共识Provider:com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider
#简单消息共识Provider:com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider
peer.providers=com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider
#数据检索服务对应URL
#数据检索服务对应URL,格式:http://{ip}:{port},例如:http://127.0.0.1:10001
#若该值不配置或配置不正确,则浏览器模糊查询部分无法正常显示
data.retrieval.url=http://192.168.1.1:10001
data.retrieval.url=http://127.0.0.1:10001
#默认公钥的内容(Base58编码数据);
keys.default.pubkey=endPsK36g6bhgn5bj66uyX4uxqnkfGvdjpxWurAA5hbf8vVoVi8H
keys.default.pubkey=3snPdw7i7PapsDoW185c3kfK6p8s6SwiJAdEUzgnfeuUox12nxgzXu
#默认私钥的路径;在 pk-path 和 pk 之间必须设置其一;
keys.default.privkey-path=
#默认私钥的内容(加密的Base58编码数据);在 pk-path 和 pk 之间必须设置其一;
keys.default.privkey=177gjwmuvDnccAvrvmJyCN1dgAqqGzfYpe3pZ8dWWNBneM5GgdsS96vgjvBP4fX61jWfohQ
keys.default.privkey=177gjyoEUhdD1NkQSxBVvfSyovMd1ha5H46zsb9kyErLNBuQkLRAf2ea6CNjStjCFJQN8S1
#默认私钥的解码密码;
keys.default.privkey-password=DYu3G8aGTMBW1WrTw76zxQJQU4DHLw9MLyy7peG4LKkY

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

@@ -1,5 +1,7 @@
package com.jd.blockchain.ledger.core;
import com.jd.blockchain.ledger.LedgerMetadata;
import com.jd.blockchain.ledger.LedgerSetting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


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

@@ -1,5 +1,6 @@
package com.jd.blockchain.ledger.core;

import com.jd.blockchain.ledger.LedgerMetadata;
import com.jd.blockchain.ledger.ParticipantNode;

public interface LedgerAdministration {


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

@@ -1,6 +1,7 @@
package com.jd.blockchain.ledger.core;

import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerSetting;
import com.jd.blockchain.utils.Bytes;

public class LedgerConfiguration implements LedgerSetting {


+ 36
- 36
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerMetadata.java View File

@@ -1,36 +1,36 @@
package com.jd.blockchain.ledger.core;
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;
@DataContract(code = DataCodes.METADATA)
public interface LedgerMetadata {
/**
* 账本的初始化种子;
*
* @return
*/
@DataField(order = 1, primitiveType = PrimitiveType.BYTES)
byte[] getSeed();
/**
* 共识参与方的默克尔树的根;
*
* @return
*/
@DataField(order = 2, primitiveType = PrimitiveType.BYTES)
HashDigest getParticipantsHash();
/**
* 账本配置;
*
* @return
*/
@DataField(order = 3, refContract = true)
LedgerSetting getSetting();
}
//package com.jd.blockchain.ledger.core;
//
//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;
//
//@DataContract(code = DataCodes.METADATA)
//public interface LedgerMetadata {
//
// /**
// * 账本的初始化种子;
// *
// * @return
// */
// @DataField(order = 1, primitiveType = PrimitiveType.BYTES)
// byte[] getSeed();
//
// /**
// * 共识参与方的默克尔树的根;
// *
// * @return
// */
// @DataField(order = 2, primitiveType = PrimitiveType.BYTES)
// HashDigest getParticipantsHash();
//
// /**
// * 账本配置;
// *
// * @return
// */
// @DataField(order = 3, refContract = true)
// LedgerSetting getSetting();
//
//}

+ 24
- 24
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSetting.java View File

@@ -1,24 +1,24 @@
package com.jd.blockchain.ledger.core;
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.ledger.CryptoSetting;
import com.jd.blockchain.utils.Bytes;
@DataContract(code = DataCodes.METADATA_LEDGER_SETTING)
public interface LedgerSetting {
@DataField(order=0, primitiveType=PrimitiveType.TEXT)
String getConsensusProvider();
@DataField(order=1, primitiveType=PrimitiveType.BYTES)
Bytes getConsensusSetting();
@DataField(order=2, refContract=true)
CryptoSetting getCryptoSetting();
// PrivilegeModelSetting getPrivilegesModelSetting();
}
//package com.jd.blockchain.ledger.core;
//
//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.ledger.CryptoSetting;
//import com.jd.blockchain.utils.Bytes;
//
//@DataContract(code = DataCodes.METADATA_LEDGER_SETTING)
//public interface LedgerSetting {
//
// @DataField(order=0, primitiveType=PrimitiveType.TEXT)
// String getConsensusProvider();
//
// @DataField(order=1, primitiveType=PrimitiveType.BYTES)
// Bytes getConsensusSetting();
//
// @DataField(order=2, refContract=true)
// CryptoSetting getCryptoSetting();
//
//// PrivilegeModelSetting getPrivilegesModelSetting();
//
//}

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

@@ -3,16 +3,7 @@ package com.jd.blockchain.ledger.core.impl;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.KVDataObject;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerInfo;
import com.jd.blockchain.ledger.LedgerTransaction;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.UserInfo;
import com.jd.blockchain.ledger.*;
import com.jd.blockchain.ledger.core.ContractAccountSet;
import com.jd.blockchain.ledger.core.DataAccount;
import com.jd.blockchain.ledger.core.DataAccountSet;
@@ -50,10 +41,12 @@ public class LedgerQueryService implements BlockchainQueryService {
@Override
public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
LedgerAdministration administration = ledger.getAdminAccount(block);
return administration.getParticipants();
return ledgerAdministration(ledgerHash).getParticipants();
}
@Override
public LedgerMetadata getLedgerMetadata(HashDigest ledgerHash) {
return ledgerAdministration(ledgerHash).getMetadata();
}
@Override
@@ -338,4 +331,11 @@ public class LedgerQueryService implements BlockchainQueryService {
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex,count,(int)contractAccountSet.getTotalCount());
return contractAccountSet.getAccounts(pages[0],pages[1]);
}
private LedgerAdministration ledgerAdministration(HashDigest ledgerHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
LedgerAdministration administration = ledger.getAdminAccount(block);
return administration;
}
}

+ 2
- 8
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerRepositoryImpl.java View File

@@ -4,12 +4,7 @@ import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.HashFunction;
import com.jd.blockchain.ledger.BlockBody;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerDataSnapshot;
import com.jd.blockchain.ledger.LedgerInitSetting;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.*;
import com.jd.blockchain.ledger.core.AccountAccessPolicy;
import com.jd.blockchain.ledger.core.ContractAccountSet;
import com.jd.blockchain.ledger.core.DataAccountSet;
@@ -20,7 +15,6 @@ import com.jd.blockchain.ledger.core.LedgerDataSet;
import com.jd.blockchain.ledger.core.LedgerEditor;
import com.jd.blockchain.ledger.core.LedgerException;
import com.jd.blockchain.ledger.core.LedgerRepository;
import com.jd.blockchain.ledger.core.LedgerSetting;
import com.jd.blockchain.ledger.core.LedgerTransactionContext;
import com.jd.blockchain.ledger.core.TransactionSet;
import com.jd.blockchain.ledger.core.UserAccountSet;
@@ -486,7 +480,7 @@ public class LedgerRepositoryImpl implements LedgerRepository {
}

static TransactionSet newTransactionSet(LedgerSetting ledgerSetting, String keyPrefix,
ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) {
ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) {
// TransactionSet transactionSet = new
// TransactionSet(ledgerSetting.getCryptoSetting(),
// PrefixAppender.prefix(TRANSACTION_SET_PREFIX, ledgerExStorage),


+ 2
- 10
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionalEditor.java View File

@@ -5,17 +5,9 @@ import java.util.Stack;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.BlockBody;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerDataSnapshot;
import com.jd.blockchain.ledger.LedgerInitSetting;
import com.jd.blockchain.ledger.LedgerTransaction;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.*;
import com.jd.blockchain.ledger.core.LedgerDataSet;
import com.jd.blockchain.ledger.core.LedgerEditor;
import com.jd.blockchain.ledger.core.LedgerSetting;
import com.jd.blockchain.ledger.core.LedgerTransactionContext;
import com.jd.blockchain.ledger.core.TransactionSet;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
@@ -67,7 +59,7 @@ public class LedgerTransactionalEditor implements LedgerEditor {
}

public static LedgerTransactionalEditor createEditor(LedgerSetting ledgerSetting, LedgerBlock previousBlock,
String ledgerKeyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) {
String ledgerKeyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) {
// new block;
LedgerBlockData currBlock = new LedgerBlockData(previousBlock.getHeight() + 1, previousBlock.getLedgerHash(),
previousBlock.getHash());


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

@@ -6,22 +6,7 @@ import java.util.List;
import com.alibaba.fastjson.JSON;
import com.jd.blockchain.contract.LedgerContext;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.BytesValueEntry;
import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.ledger.DataAccountRegisterOperation;
import com.jd.blockchain.ledger.BytesValueType;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerInfo;
import com.jd.blockchain.ledger.LedgerTransaction;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.UserInfo;
import com.jd.blockchain.ledger.UserRegisterOperation;
import com.jd.blockchain.ledger.*;
import com.jd.blockchain.ledger.core.impl.OperationHandleContext;
import com.jd.blockchain.transaction.BlockchainQueryService;
import com.jd.blockchain.transaction.DataAccountKVSetOperationBuilder;
@@ -61,6 +46,11 @@ public class ContractLedgerContext implements LedgerContext {
return innerQueryService.getConsensusParticipants(ledgerHash);
}

@Override
public LedgerMetadata getLedgerMetadata(HashDigest ledgerHash) {
return innerQueryService.getLedgerMetadata(ledgerHash);
}

@Override
public LedgerBlock getBlock(HashDigest ledgerHash, long height) {
return innerQueryService.getBlock(ledgerHash, height);


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

@@ -9,6 +9,7 @@ import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.Random;

import com.jd.blockchain.ledger.LedgerMetadata;
import org.junit.Test;

import com.jd.blockchain.crypto.AddressEncoding;
@@ -20,7 +21,6 @@ import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.ledger.core.CryptoConfig;
import com.jd.blockchain.ledger.core.LedgerAdminAccount;
import com.jd.blockchain.ledger.core.LedgerConfiguration;
import com.jd.blockchain.ledger.core.LedgerMetadata;
import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
import com.jd.blockchain.transaction.ConsensusParticipantData;
import com.jd.blockchain.transaction.LedgerInitSettingData;


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

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

import java.util.Random;

import com.jd.blockchain.ledger.LedgerMetadata;
import com.jd.blockchain.ledger.LedgerSetting;
import org.junit.Before;
import org.junit.Test;

@@ -21,8 +23,6 @@ import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.ledger.core.CryptoConfig;
import com.jd.blockchain.ledger.core.LedgerAdminAccount;
import com.jd.blockchain.ledger.core.LedgerConfiguration;
import com.jd.blockchain.ledger.core.LedgerMetadata;
import com.jd.blockchain.ledger.core.LedgerSetting;
import com.jd.blockchain.ledger.core.ParticipantCertData;
import com.jd.blockchain.utils.Bytes;



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

@@ -0,0 +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;

@DataContract(code = DataCodes.METADATA)
public interface LedgerMetadata {

/**
* 账本的初始化种子;
*
* @return
*/
@DataField(order = 1, primitiveType = PrimitiveType.BYTES)
byte[] getSeed();

/**
* 共识参与方的默克尔树的根;
*
* @return
*/
@DataField(order = 2, primitiveType = PrimitiveType.BYTES)
HashDigest getParticipantsHash();

/**
* 账本配置;
*
* @return
*/
@DataField(order = 3, refContract = true)
LedgerSetting getSetting();

}

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

@@ -0,0 +1,24 @@
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.ledger.CryptoSetting;
import com.jd.blockchain.utils.Bytes;

@DataContract(code = DataCodes.METADATA_LEDGER_SETTING)
public interface LedgerSetting {

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

@DataField(order=1, primitiveType=PrimitiveType.BYTES)
Bytes getConsensusSetting();

@DataField(order=2, refContract=true)
CryptoSetting getCryptoSetting();

// PrivilegeModelSetting getPrivilegesModelSetting();

}

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

@@ -36,6 +36,14 @@ public interface BlockchainQueryService {
*/
ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash);
/**
* 返回当前账本的元数据
*
* @param ledgerHash
* @return
*/
LedgerMetadata getLedgerMetadata(HashDigest ledgerHash);
/**
* 返回指定账本序号的区块;
*


+ 101
- 0
source/ledger/ledger-rpc/src/main/java/com/jd/blockchain/web/serializes/ByteArrayObjectJsonDeserializer.java View File

@@ -0,0 +1,101 @@
package com.jd.blockchain.web.serializes;

import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.JSONToken;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.crypto.SignatureDigest;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.codec.Base58Utils;
import com.jd.blockchain.utils.io.BytesSlice;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;
import java.util.Map;

public class ByteArrayObjectJsonDeserializer extends JavaBeanDeserializer {

private ByteArrayObjectJsonDeserializer(Class<?> clazz) {
super(ParserConfig.global, clazz);
}

public static ByteArrayObjectJsonDeserializer getInstance(Class<?> clazz) {
return new ByteArrayObjectJsonDeserializer(clazz);
}

@SuppressWarnings("unchecked")
@Override
public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
if (type instanceof Class && clazz.isAssignableFrom((Class<?>) type)) {
String parseText = parser.parseObject(String.class);
byte[] hashBytes = Base58Utils.decode(parseText);
if (clazz == HashDigest.class) {
return (T) new HashDigest(hashBytes);
} else if (clazz == PubKey.class) {
return (T) new HashDigest(hashBytes);
} else if (clazz == SignatureDigest.class) {
return (T) new SignatureDigest(hashBytes);
} else if (clazz == Bytes.class) {
return (T) new Bytes(hashBytes);
} else if (clazz == BytesSlice.class) {
return (T) new BytesSlice(hashBytes);
}

// else if (clazz == BytesValue.class) {
// ByteArrayObjectJsonSerializer.BytesValueJson valueJson = JSON.parseObject(parseText, ByteArrayObjectJsonSerializer.BytesValueJson.class);
// DataType dataType = valueJson.getType();
// Object dataVal = valueJson.getValue();
// byte[] bytes = null;
// switch (dataType) {
// case BYTES:
// bytes = ByteArray.fromHex((String) dataVal);
// break;
// case TEXT:
// bytes = ((String) dataVal).getBytes();
// break;
// case INT64:
// bytes = BytesUtils.toBytes((Long) dataVal);
// break;
// case JSON:
// bytes = ((String) dataVal).getBytes();
// break;
// }
// BytesValue bytesValue = new BytesValueImpl(dataType, bytes);
// return (T) bytesValue;
// }
}
return (T) parser.parse(fieldName);
}

@Override
public Object createInstance(Map<String, Object> map, ParserConfig config) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
if (map == null || map.isEmpty()) {
return null;
}
for (Map.Entry<String, Object> entry : map.entrySet()) {
Object value = entry.getValue();
if (value instanceof String) {
byte[] hashBytes = Base58Utils.decode((String) value);
if (clazz == HashDigest.class) {
return new HashDigest(hashBytes);
} else if (clazz == PubKey.class) {
return new PubKey(hashBytes);
} else if (clazz == SignatureDigest.class) {
return new SignatureDigest(hashBytes);
} else if (clazz == Bytes.class) {
return new Bytes(hashBytes);
} else if (clazz == BytesSlice.class) {
return new BytesSlice(hashBytes);
}
}
}
return null;
}

@Override
public int getFastMatchToken() {
return JSONToken.LBRACE;
}
}

+ 120
- 0
source/ledger/ledger-rpc/src/main/java/com/jd/blockchain/web/serializes/ByteArrayObjectJsonSerializer.java View File

@@ -0,0 +1,120 @@
package com.jd.blockchain.web.serializes;

import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import com.jd.blockchain.binaryproto.DataType;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.crypto.SignatureDigest;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.codec.Base58Utils;
import com.jd.blockchain.utils.io.BytesSlice;

import java.lang.reflect.Type;

public class ByteArrayObjectJsonSerializer implements ObjectSerializer {

private Class<?> clazz;

private ByteArrayObjectJsonSerializer(Class<?> clazz) {
this.clazz = clazz;
}

public static ByteArrayObjectJsonSerializer getInstance(Class<?> clazz) {
return new ByteArrayObjectJsonSerializer(clazz);
}

@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) {
if (object.getClass() != clazz) {
serializer.writeNull();
return;
}
if (object instanceof HashDigest) {
serializer.write(new HashDigestJson(((HashDigest) object).toBase58()));
} else if (object instanceof PubKey) {
serializer.write(new HashDigestJson(((PubKey) object).toBase58()));
} else if (object instanceof SignatureDigest) {
serializer.write(new HashDigestJson(((SignatureDigest) object).toBase58()));
} else if (object instanceof Bytes) {
serializer.write(new HashDigestJson(((Bytes) object).toBase58()));
} else if (object instanceof BytesSlice) {
serializer.write(Base58Utils.encode(((BytesSlice) object).toBytes()));
}

// else if (object instanceof BytesValue) {
// DataType dataType = ((BytesValue) object).getType();
// BytesSlice bytesValue = ((BytesValue) object).getValue();
// Object realVal;
// switch (dataType) {
// case NIL:
// realVal = null;
// break;
// case TEXT:
// realVal = bytesValue.getString();
// break;
// case BYTES:
// realVal = ByteArray.toHex(bytesValue.toBytes());
// break;
// case INT32:
// realVal = bytesValue.getInt();
// break;
// case INT64:
// realVal = bytesValue.getLong();
// break;
// case JSON:
// realVal = bytesValue.getString();
// break;
// default:
// realVal = ByteArray.toHex(bytesValue.toBytes());
// break;
// }
// serializer.write(new BytesValueJson(dataType, realVal));
// }
}

private static class HashDigestJson {

String value;

public HashDigestJson(String value) {
this.value = value;
}

public String getValue() {
return value;
}

public void setValue(String value) {
this.value = value;
}
}

public static class BytesValueJson {

public BytesValueJson(DataType type, Object value) {
this.type = type;
this.value = value;
}

DataType type;

Object value;

public DataType getType() {
return type;
}

public void setType(DataType type) {
this.type = type;
}

public Object getValue() {
return value;
}

public void setValue(Object value) {
this.value = value;
}
}
}

+ 41
- 0
source/ledger/ledger-rpc/src/main/java/com/jd/blockchain/web/serializes/ByteArrayObjectUtil.java View File

@@ -0,0 +1,41 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.web.serializes.ByteArrayObjectUtil
* Author: shaozhuguang
* Department: Y事业部
* Date: 2019/3/27 上午11:23
* Description:
*/
package com.jd.blockchain.web.serializes;

import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.crypto.SignatureDigest;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.io.BytesSlice;
import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils;

/**
*
* @author shaozhuguang
* @create 2019/3/27
* @since 1.0.0
*/

public class ByteArrayObjectUtil {

public static final Class<?>[] BYTEARRAY_JSON_SERIALIZE_CLASS = new Class<?>[] {
HashDigest.class,
PubKey.class,
SignatureDigest.class,
Bytes.class,
BytesSlice.class};

public static void init() {
for (Class<?> byteArrayClass : BYTEARRAY_JSON_SERIALIZE_CLASS) {
JSONSerializeUtils.configSerialization(byteArrayClass,
ByteArrayObjectJsonSerializer.getInstance(byteArrayClass),
ByteArrayObjectJsonDeserializer.getInstance(byteArrayClass));
}
}
}

+ 1
- 0
source/peer/.gitignore View File

@@ -1 +1,2 @@
/target/
/.apt_generated_tests/

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

@@ -1,5 +1,7 @@
package com.jd.blockchain.peer.web;
import com.jd.blockchain.ledger.*;
import com.jd.blockchain.ledger.core.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -10,25 +12,6 @@ import org.springframework.web.bind.annotation.RestController;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.KVDataObject;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerInfo;
import com.jd.blockchain.ledger.LedgerTransaction;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.UserInfo;
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;
@@ -79,6 +62,15 @@ public class LedgerQueryController implements BlockchainQueryService {
return null;
}
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/metadata")
@Override
public LedgerMetadata getLedgerMetadata(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerAdministration ledgerAdministration = ledger.getAdminInfo();
LedgerMetadata ledgerMetadata = ledgerAdministration.getMetadata();
return ledgerMetadata;
}
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}")
@Override
public LedgerBlock getBlock(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,


+ 2
- 19
source/peer/src/main/java/com/jd/blockchain/peer/web/PeerWebServerConfigurer.java View File

@@ -2,22 +2,16 @@ package com.jd.blockchain.peer.web;
import java.util.List;
import com.jd.blockchain.utils.io.BytesSlice;
import com.jd.blockchain.web.converters.BinaryMessageConverter;
import com.jd.blockchain.web.converters.HashDigestInputConverter;
import com.jd.blockchain.web.serializes.ByteArrayObjectUtil;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.crypto.SignatureDigest;
import com.jd.blockchain.crypto.serialize.ByteArrayObjectDeserializer;
import com.jd.blockchain.crypto.serialize.ByteArrayObjectSerializer;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.io.ByteArray;
import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils;
import com.jd.blockchain.utils.web.model.JsonWebResponseMessageConverter;
@@ -25,13 +19,6 @@ import com.jd.blockchain.utils.web.model.JsonWebResponseMessageConverter;
@Configuration
public class PeerWebServerConfigurer implements WebMvcConfigurer {
private static final Class<?>[] BYTEARRAY_JSON_SERIALIZE_CLASS = new Class<?>[] {
HashDigest.class,
PubKey.class,
SignatureDigest.class,
Bytes.class,
BytesSlice.class};
static {
JSONSerializeUtils.disableCircularReferenceDetect();
JSONSerializeUtils.configStringSerializer(ByteArray.class);
@@ -59,10 +46,6 @@ public class PeerWebServerConfigurer implements WebMvcConfigurer {
}
private void initByteArrayJsonSerialize() {
for (Class<?> byteArrayClass : BYTEARRAY_JSON_SERIALIZE_CLASS) {
JSONSerializeUtils.configSerialization(byteArrayClass,
ByteArrayObjectSerializer.getInstance(byteArrayClass),
ByteArrayObjectDeserializer.getInstance(byteArrayClass));
}
ByteArrayObjectUtil.init();
}
}

+ 19
- 0
source/pom.xml View File

@@ -297,6 +297,25 @@
<artifactId>commons-collections4</artifactId>
<version>4.1</version>
</dependency>

<!-- jar包扫描 -->
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.10</version>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
</dependencies>
</dependencyManagement>



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

@@ -0,0 +1,113 @@
package com.jd.blockchain.sdk;


import com.jd.blockchain.consensus.ConsensusSettings;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.ParticipantNode;

/**
* 账本初始化配置
*
* @author shaozhuguang
* @date 2019-04-23
* @since 1.0.0
*
*/
public class LedgerInitSettings {

/**
* 账本初始化种子
*/
private String seed;

/**
* 共识参与方的默克尔树的根;
*/
private HashDigest participantsHash;

/**
* 算法配置
*/
private CryptoSetting cryptoSetting;

/**
* 共识协议
*/
private int consensusProtocol;

/**
* 共识配置
*/
private ConsensusSettings consensusSettings;

/**
* 共识参与方
*/
private ParticipantNode[] participantNodes;

public void setSeed(String seed) {
this.seed = seed;
}

public String getSeed() {
return seed;
}

public HashDigest getParticipantsHash() {
return participantsHash;
}

public void setParticipantsHash(HashDigest participantsHash) {
this.participantsHash = participantsHash;
}

public CryptoSetting getCryptoSetting() {
return cryptoSetting;
}

public void setCryptoSetting(CryptoSetting cryptoSetting) {
this.cryptoSetting = cryptoSetting;
}

public int getConsensusProtocol() {
return consensusProtocol;
}

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

public ConsensusSettings getConsensusSettings() {
return consensusSettings;
}

public void setConsensusSettings(ConsensusSettings consensusSettings) {
this.consensusSettings = consensusSettings;
}

public ParticipantNode[] getParticipantNodes() {
return participantNodes;
}

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;
}
}
}

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

@@ -37,7 +37,12 @@ public abstract class BlockchainServiceProxy implements BlockchainService {
return getQueryService(ledgerHash).getConsensusParticipants(ledgerHash);
}

@Override
@Override
public LedgerMetadata getLedgerMetadata(HashDigest ledgerHash) {
return getQueryService(ledgerHash).getLedgerMetadata(ledgerHash);
}

@Override
public LedgerBlock getBlock(HashDigest ledgerHash, long height) {
return getQueryService(ledgerHash).getBlock(ledgerHash, height);
}


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

@@ -204,6 +204,17 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService
@Override
ParticipantNode[] getConsensusParticipants(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash);


/**
* 返回指定账本的元数据
*
* @param ledgerHash
* @return
*/
@HttpAction(method=HttpMethod.GET, path="ledgers/{ledgerHash}/metadata")
@Override
LedgerMetadata getLedgerMetadata(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash);

/**
* 返回指定账本序号的区块;
*


+ 1
- 1
source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/service/NodeSigningAppender.java View File

@@ -72,7 +72,7 @@ public class NodeSigningAppender implements TransactionService {

// 计算交易哈希;
byte[] nodeRequestBytes = BinaryProtocol.encode(txMessage, TransactionRequest.class);
HashFunction hashFunc = Crypto.getHashFunction(signAlgorithm);
HashFunction hashFunc = Crypto.getHashFunction(this.hashAlgorithm);
HashDigest txHash = hashFunc.hash(nodeRequestBytes);
txMessage.setHash(txHash);



+ 6
- 0
source/sdk/sdk-client/pom.xml View File

@@ -14,5 +14,11 @@
<artifactId>sdk-base</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>ledger-rpc</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

+ 32
- 5
source/sdk/sdk-client/src/main/java/com/jd/blockchain/sdk/client/GatewayServiceFactory.java View File

@@ -3,15 +3,16 @@ package com.jd.blockchain.sdk.client;
import java.io.Closeable;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.consensus.ClientIdentification;
import com.jd.blockchain.consensus.ClientIdentifications;
import com.jd.blockchain.consensus.action.ActionRequest;
import com.jd.blockchain.consensus.action.ActionResponse;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.PrivKey;
import com.jd.blockchain.crypto.SignatureDigest;
import com.jd.blockchain.crypto.SignatureFunction;
import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionResponse;
import com.jd.blockchain.ledger.*;
import com.jd.blockchain.sdk.BlockchainService;
import com.jd.blockchain.sdk.BlockchainServiceFactory;
import com.jd.blockchain.sdk.proxy.HttpBlockchainQueryService;
@@ -24,6 +25,7 @@ import com.jd.blockchain.utils.http.agent.ServiceConnection;
import com.jd.blockchain.utils.http.agent.ServiceConnectionManager;
import com.jd.blockchain.utils.http.agent.ServiceEndpoint;
import com.jd.blockchain.utils.net.NetworkAddress;
import com.jd.blockchain.web.serializes.ByteArrayObjectUtil;
public class GatewayServiceFactory implements BlockchainServiceFactory, Closeable {
@@ -33,6 +35,31 @@ public class GatewayServiceFactory implements BlockchainServiceFactory, Closeabl
private BlockchainService blockchainService;
static {
DataContractRegistry.register(TransactionContent.class);
DataContractRegistry.register(TransactionContentBody.class);
DataContractRegistry.register(TransactionRequest.class);
DataContractRegistry.register(NodeRequest.class);
DataContractRegistry.register(EndpointRequest.class);
DataContractRegistry.register(TransactionResponse.class);
DataContractRegistry.register(DataAccountKVSetOperation.class);
DataContractRegistry.register(DataAccountKVSetOperation.KVWriteEntry.class);
DataContractRegistry.register(Operation.class);
DataContractRegistry.register(ContractCodeDeployOperation.class);
DataContractRegistry.register(ContractEventSendOperation.class);
DataContractRegistry.register(DataAccountRegisterOperation.class);
DataContractRegistry.register(UserRegisterOperation.class);
DataContractRegistry.register(ActionRequest.class);
DataContractRegistry.register(ActionResponse.class);
DataContractRegistry.register(ClientIdentifications.class);
DataContractRegistry.register(ClientIdentification.class);
ByteArrayObjectUtil.init();
}
protected GatewayServiceFactory(ServiceEndpoint gatewayEndpoint, BlockchainKeypair userKey) {
httpConnectionManager = new ServiceConnectionManager();
this.userKey = userKey;


+ 0
- 13
source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Query_Test_.java View File

@@ -19,8 +19,6 @@ import com.jd.blockchain.crypto.HashFunction;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.crypto.SignatureDigest;
import com.jd.blockchain.crypto.SignatureFunction;
import com.jd.blockchain.crypto.serialize.ByteArrayObjectDeserializer;
import com.jd.blockchain.crypto.serialize.ByteArrayObjectSerializer;
import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
@@ -53,17 +51,6 @@ import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils;

public class SDK_GateWay_Query_Test_ {

private static Class<?>[] byteArrayClasss = new Class<?>[] { HashDigest.class, PubKey.class,
SignatureDigest.class };

static {
for (Class<?> byteArrayClass : byteArrayClasss) {
JSONSerializeUtils.configSerialization(byteArrayClass,
ByteArrayObjectSerializer.getInstance(byteArrayClass),
ByteArrayObjectDeserializer.getInstance(byteArrayClass));
}
}

private BlockchainKeypair CLIENT_CERT = null;

private String GATEWAY_IPADDR = null;


+ 30
- 1
source/storage/storage-composite/pom.xml View File

@@ -14,7 +14,7 @@
<artifactId>storage-service</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<!--<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>storage-redis</artifactId>
<version>${project.version}</version>
@@ -24,6 +24,35 @@
<artifactId>storage-rocksdb</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>storage-tikv</artifactId>
<version>${project.version}</version>
</dependency>-->
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
</dependency>

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>

<!--<dependency>
<groupId>org.rocksdb</groupId>
<artifactId>rocksdbjni</artifactId>


+ 88
- 64
source/storage/storage-composite/src/main/java/com/jd/blockchain/storage/service/impl/composite/CompositeConnectionFactory.java View File

@@ -1,76 +1,100 @@
package com.jd.blockchain.storage.service.impl.composite;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import com.jd.blockchain.storage.service.DbConnection;
import com.jd.blockchain.storage.service.DbConnectionFactory;
import com.jd.blockchain.storage.service.impl.redis.JedisConnection;
import com.jd.blockchain.storage.service.impl.redis.RedisConnectionFactory;
import com.jd.blockchain.storage.service.impl.rocksdb.RocksDBConnection;
import com.jd.blockchain.storage.service.impl.rocksdb.RocksDBConnectionFactory;
//import com.jd.blockchain.storage.service.utils.MemoryBasedDb;
import com.jd.blockchain.storage.service.utils.MemoryDBConn;
import com.jd.blockchain.storage.service.utils.MemoryDBConnFactory;
import org.reflections.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class CompositeConnectionFactory implements DbConnectionFactory {

private static final RocksDBConnectionFactory rocksDBConnFactory = new RocksDBConnectionFactory();

private static final RedisConnectionFactory redisConnFactory = new RedisConnectionFactory();

private static final MemoryDBConnFactory memoryConnFactory = new MemoryDBConnFactory();

private static final String CONN_PREFIX_REDIS = "redis://";

private static final String CONN_PREFIX_ROCKSDB = "rocksdb://";

private static final String CONN_PREFIX_MEMORY = "memory://";

private final Map<String, DbConnection> connections = new ConcurrentHashMap<>();

@Override
public DbConnection connect(String dbUri) {
return connect(dbUri, null);
}

@Override
public DbConnection connect(String dbConnectionString, String password) {
if (!dbConnectionString.startsWith(CONN_PREFIX_REDIS) &&
!dbConnectionString.startsWith(CONN_PREFIX_ROCKSDB) &&
!dbConnectionString.startsWith(CONN_PREFIX_MEMORY)){
throw new IllegalArgumentException("Illegal format of composite db connection string!");
}

if (dbConnectionString.startsWith(CONN_PREFIX_REDIS)) {
return redisConnFactory.connect(dbConnectionString, password);
} else if (dbConnectionString.startsWith(CONN_PREFIX_ROCKSDB)) {
return rocksDBConnFactory.connect(dbConnectionString, password);
} else if (dbConnectionString.startsWith(CONN_PREFIX_MEMORY)) {
return memoryConnFactory.connect(dbConnectionString, password);
}
return null;
}

@Override
public void close() {
for (DbConnection dbConnection : connections.values()) {
if (dbConnection.getClass().equals(JedisConnection.class)) {
((JedisConnection)dbConnection).close();
}
else if (dbConnection.getClass().equals(RocksDBConnection.class)) {
((RocksDBConnection)dbConnection).dbClose();
}
else if (dbConnection.getClass().equals(MemoryDBConn.class)) {
((MemoryDBConn)dbConnection).close();
}
}
connections.clear();
}

@Override
public boolean support(String scheme) {
return rocksDBConnFactory.support(scheme) || redisConnFactory.support(scheme) || memoryConnFactory.support(scheme);
}
// SPI的方式,需要初始化对应的Factory
private static final Map<String, DbConnectionFactory> connectionFactoryMap = new ConcurrentHashMap<>();

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

public CompositeConnectionFactory() {
init();
}

private void init() {
// 初始化所有实现类
Reflections reflections = new Reflections("com.jd.blockchain.storage.service");

Set<Class<? extends DbConnectionFactory>> connectionSet =
reflections.getSubTypesOf(DbConnectionFactory.class);

for (Class<? extends DbConnectionFactory> clazz : connectionSet) {
if (clazz.equals(CompositeConnectionFactory.class)) {
continue;
} else {
try {
// 根据class生成对象
DbConnectionFactory dbConnectionFactory = clazz.newInstance();
String dbPrefix = dbConnectionFactory.dbPrefix();
if (dbPrefix != null && dbPrefix.length() > 0 &&
!connectionFactoryMap.containsKey(dbPrefix)) {
connectionFactoryMap.put(dbPrefix, dbConnectionFactory);
}
} catch (Exception e) {
LOGGER.error("class:{%s} init error {%s}", clazz.getName(), e.getMessage());
}
}
}
}


@Override
public DbConnection connect(String dbUri) {
return connect(dbUri, null);
}

@Override
public DbConnection connect(String dbConnectionString, String password) {
if (connectionFactoryMap.isEmpty()) {
throw new IllegalArgumentException("DB connections is empty, please init first!");
}

for (Map.Entry<String, DbConnectionFactory> entry : connectionFactoryMap.entrySet()) {
String prefix = entry.getKey();
if (dbConnectionString.startsWith(prefix)) {
return entry.getValue().connect(dbConnectionString, password);
}
}

throw new IllegalArgumentException("Illegal format of composite db connection string!");
}

@Override
public void close() {
if (!connectionFactoryMap.isEmpty()) {
for (Map.Entry<String, DbConnectionFactory> entry : connectionFactoryMap.entrySet()) {
DbConnectionFactory dbConnectionFactory = entry.getValue();
dbConnectionFactory.close();
}
}
}

@Override
public String dbPrefix() {
return null;
}

@Override
public boolean support(String scheme) {
if (!connectionFactoryMap.isEmpty()) {
for (Map.Entry<String, DbConnectionFactory> entry : connectionFactoryMap.entrySet()) {
DbConnectionFactory dbConnectionFactory = entry.getValue();
if (dbConnectionFactory.support(scheme)) {
return true;
}
}
}
return false;
}
}

+ 1
- 0
source/storage/storage-composite/src/main/java/com/jd/blockchain/storage/service/impl/composite/CompositeStorageConfiguration.java View File

@@ -12,6 +12,7 @@ import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class CompositeStorageConfiguration {

@ConditionalOnMissingBean
@Bean
public DbConnectionFactory compositeConnectionFactory() {


+ 110
- 112
source/storage/storage-composite/src/test/java/test/com/jd/blockchain/storage/service/impl/composite/CompositeConnectionFactoryTest.java View File

@@ -1,112 +1,110 @@
package test.com.jd.blockchain.storage.service.impl.composite;
import static org.junit.Assert.*;

import com.jd.blockchain.storage.service.DbConnection;
import com.jd.blockchain.storage.service.DbConnectionFactory;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.storage.service.impl.composite.CompositeConnectionFactory;
import com.jd.blockchain.storage.service.impl.rocksdb.RocksDBConnectionFactory;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.io.BytesUtils;
import com.jd.blockchain.utils.io.FileUtils;

import org.junit.Test;

import java.io.File;
import java.util.regex.Pattern;

public class CompositeConnectionFactoryTest {

public static final Pattern URI_PATTER_REDIS = Pattern
.compile("^\\w+\\://(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})\\:\\d+(/\\d*(/.*)*)?$");

@Test
public void testRedisConnectionString() {
String connStr = "redis://192.168.86.130:6379/";
boolean match = URI_PATTER_REDIS.matcher(connStr).matches();
assertTrue(match);

connStr = "redis://192.168.86.131:6379/";
match = URI_PATTER_REDIS.matcher(connStr).matches();
assertTrue(match);

connStr = "redis://192.168.86.132:6379/";
match = URI_PATTER_REDIS.matcher(connStr).matches();
assertTrue(match);

connStr = "redis://192.168.86.133:6379/";
match = URI_PATTER_REDIS.matcher(connStr).matches();
assertTrue(match);
}

@Test
public void testRocksDbConnect() {
String dbUri = initEmptyDB("rocksdb_storage_test");
long expectedVersion;
try (CompositeConnectionFactory dbConnFactory = new CompositeConnectionFactory()) {
// try (CompositeConnectionFactory dbConnFactory = CompositeConnectionFactory.getInstance()) {
DbConnection conn = dbConnFactory.connect(dbUri);
VersioningKVStorage verStorage = conn.getStorageService().getVersioningKVStorage();
ExPolicyKVStorage exStorage = conn.getStorageService().getExPolicyKVStorage();

expectedVersion = test(verStorage);

test(exStorage);
}
}
private String initEmptyDB(String name) {
String currDir = FileUtils.getCurrentDir();
String dbDir = new File(currDir, name + ".db").getAbsolutePath();
FileUtils.deleteFile(dbDir);
String dbURI = "rocksdb://" + dbDir;
return dbURI;
}
private long test(VersioningKVStorage verStorage) {
String key = "k1";
long v = verStorage.getVersion(Bytes.fromString(key));
assertEquals(-1, v);
byte[] data = verStorage.get(Bytes.fromString(key), -1);
assertNull(data);
data = verStorage.get(Bytes.fromString(key), 0);
assertNull(data);
data = verStorage.get(Bytes.fromString(key), 1);
assertNull(data);

data = BytesUtils.toBytes("data");
v = verStorage.set(Bytes.fromString(key), data, -1);
assertEquals(0, v);
v = verStorage.set(Bytes.fromString(key), data, -1);
assertEquals(-1, v);
v = verStorage.set(Bytes.fromString(key), data, 0);
assertEquals(1, v);
return v;
}

private void test(ExPolicyKVStorage exStorage) {
String key = "kex";
assertFalse(exStorage.exist(Bytes.fromString(key)));

byte[] data = exStorage.get(Bytes.fromString(key));
assertNull(data);

data = BytesUtils.toBytes("data");
assertFalse(exStorage.set(Bytes.fromString(key), data, ExPolicyKVStorage.ExPolicy.EXISTING));

assertTrue(exStorage.set(Bytes.fromString(key), data, ExPolicyKVStorage.ExPolicy.NOT_EXISTING));
assertTrue(exStorage.exist(Bytes.fromString(key)));

assertFalse(exStorage.set(Bytes.fromString(key), data, ExPolicyKVStorage.ExPolicy.NOT_EXISTING));

assertTrue(exStorage.set(Bytes.fromString(key), data, ExPolicyKVStorage.ExPolicy.EXISTING));
assertTrue(exStorage.set(Bytes.fromString(key), data, ExPolicyKVStorage.ExPolicy.EXISTING));
assertFalse(exStorage.set(Bytes.fromString(key), data, ExPolicyKVStorage.ExPolicy.NOT_EXISTING));

assertTrue(exStorage.exist(Bytes.fromString(key)));

byte[] reloadData = exStorage.get(Bytes.fromString(key));
assertTrue(BytesUtils.equals(data, reloadData));
}


}
//package test.com.jd.blockchain.storage.service.impl.composite;
//import static org.junit.Assert.*;
//
//import com.jd.blockchain.storage.service.DbConnection;
//import com.jd.blockchain.storage.service.ExPolicyKVStorage;
//import com.jd.blockchain.storage.service.VersioningKVStorage;
//import com.jd.blockchain.storage.service.impl.composite.CompositeConnectionFactory;
//import com.jd.blockchain.utils.Bytes;
//import com.jd.blockchain.utils.io.BytesUtils;
//import com.jd.blockchain.utils.io.FileUtils;
//
//import org.junit.Test;
//
//import java.io.File;
//import java.util.regex.Pattern;
//
//public class CompositeConnectionFactoryTest {
//
// public static final Pattern URI_PATTER_REDIS = Pattern
// .compile("^\\w+\\://(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})\\:\\d+(/\\d*(/.*)*)?$");
//
// @Test
// public void testRedisConnectionString() {
// String connStr = "redis://192.168.86.130:6379/";
// boolean match = URI_PATTER_REDIS.matcher(connStr).matches();
// assertTrue(match);
//
// connStr = "redis://192.168.86.131:6379/";
// match = URI_PATTER_REDIS.matcher(connStr).matches();
// assertTrue(match);
//
// connStr = "redis://192.168.86.132:6379/";
// match = URI_PATTER_REDIS.matcher(connStr).matches();
// assertTrue(match);
//
// connStr = "redis://192.168.86.133:6379/";
// match = URI_PATTER_REDIS.matcher(connStr).matches();
// assertTrue(match);
// }
//
// @Test
// public void testRocksDbConnect() {
// String dbUri = initEmptyDB("rocksdb_storage_test");
// long expectedVersion;
// try (CompositeConnectionFactory dbConnFactory = new CompositeConnectionFactory()) {
//// try (CompositeConnectionFactory dbConnFactory = CompositeConnectionFactory.getInstance()) {
// DbConnection conn = dbConnFactory.connect(dbUri);
// VersioningKVStorage verStorage = conn.getStorageService().getVersioningKVStorage();
// ExPolicyKVStorage exStorage = conn.getStorageService().getExPolicyKVStorage();
//
// expectedVersion = test(verStorage);
//
// test(exStorage);
// }
// }
// private String initEmptyDB(String name) {
// String currDir = FileUtils.getCurrentDir();
// String dbDir = new File(currDir, name + ".db").getAbsolutePath();
// FileUtils.deleteFile(dbDir);
// String dbURI = "rocksdb://" + dbDir;
// return dbURI;
// }
// private long test(VersioningKVStorage verStorage) {
// String key = "k1";
// long v = verStorage.getVersion(Bytes.fromString(key));
// assertEquals(-1, v);
// byte[] data = verStorage.get(Bytes.fromString(key), -1);
// assertNull(data);
// data = verStorage.get(Bytes.fromString(key), 0);
// assertNull(data);
// data = verStorage.get(Bytes.fromString(key), 1);
// assertNull(data);
//
// data = BytesUtils.toBytes("data");
// v = verStorage.set(Bytes.fromString(key), data, -1);
// assertEquals(0, v);
// v = verStorage.set(Bytes.fromString(key), data, -1);
// assertEquals(-1, v);
// v = verStorage.set(Bytes.fromString(key), data, 0);
// assertEquals(1, v);
// return v;
// }
//
// private void test(ExPolicyKVStorage exStorage) {
// String key = "kex";
// assertFalse(exStorage.exist(Bytes.fromString(key)));
//
// byte[] data = exStorage.get(Bytes.fromString(key));
// assertNull(data);
//
// data = BytesUtils.toBytes("data");
// assertFalse(exStorage.set(Bytes.fromString(key), data, ExPolicyKVStorage.ExPolicy.EXISTING));
//
// assertTrue(exStorage.set(Bytes.fromString(key), data, ExPolicyKVStorage.ExPolicy.NOT_EXISTING));
// assertTrue(exStorage.exist(Bytes.fromString(key)));
//
// assertFalse(exStorage.set(Bytes.fromString(key), data, ExPolicyKVStorage.ExPolicy.NOT_EXISTING));
//
// assertTrue(exStorage.set(Bytes.fromString(key), data, ExPolicyKVStorage.ExPolicy.EXISTING));
// assertTrue(exStorage.set(Bytes.fromString(key), data, ExPolicyKVStorage.ExPolicy.EXISTING));
// assertFalse(exStorage.set(Bytes.fromString(key), data, ExPolicyKVStorage.ExPolicy.NOT_EXISTING));
//
// assertTrue(exStorage.exist(Bytes.fromString(key)));
//
// byte[] reloadData = exStorage.get(Bytes.fromString(key));
// assertTrue(BytesUtils.equals(data, reloadData));
// }
//
//
//}

+ 1
- 0
source/storage/storage-redis/.gitignore View File

@@ -0,0 +1 @@
/.apt_generated_tests/

+ 28
- 2
source/storage/storage-redis/src/main/java/com/jd/blockchain/storage/service/impl/redis/RedisConnectionFactory.java View File

@@ -1,6 +1,9 @@
package com.jd.blockchain.storage.service.impl.redis;

import java.io.IOException;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;

import com.jd.blockchain.storage.service.DbConnection;
@@ -17,13 +20,20 @@ public class RedisConnectionFactory implements DbConnectionFactory {
// public static final Pattern URI_PATTER = Pattern
// .compile("^\\w+\\://(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})\\:\\d+(/\\d+)?(/.*)*$");

private static final Map<String, DbConnection> connections = new ConcurrentHashMap<>();

@Override
public DbConnection connect(String dbUri) {
return connect(dbUri, null);
}

@Override
public DbConnection connect(String dbConnectionString, String password) {
public synchronized DbConnection connect(String dbConnectionString, String password) {

if (connections.containsKey(dbConnectionString)) {
// 暂不处理密码变化问题
return connections.get(dbConnectionString);
}

URI dbUri = URI.create(dbConnectionString);
if (!(dbUri.getScheme().equalsIgnoreCase("redis"))) {
@@ -42,7 +52,9 @@ public class RedisConnectionFactory implements DbConnectionFactory {
int port = dbUri.getPort();
int dbId = retriveDbIdFromPath(dbUri.getPath());
JedisPool pool = new JedisPool(config, host, port, Protocol.DEFAULT_TIMEOUT, password, dbId, false);
return new JedisConnection(pool);
JedisConnection jedisConnection = new JedisConnection(pool);
connections.put(dbConnectionString, jedisConnection);
return jedisConnection;
}

/**
@@ -71,6 +83,11 @@ public class RedisConnectionFactory implements DbConnectionFactory {
return dbId;
}

@Override
public String dbPrefix() {
return "redis://";
}

@Override
public boolean support(String scheme) {
return RedisConsts.URI_SCHEME.equalsIgnoreCase(scheme);
@@ -79,5 +96,14 @@ public class RedisConnectionFactory implements DbConnectionFactory {
@Override
public void close() {
// TODO:  未实现连接池的关闭;
if (!connections.isEmpty()) {
for (Map.Entry<String, DbConnection> entry : connections.entrySet()) {
try {
entry.getValue().close();
} catch (IOException e) {
// 打印关闭异常日志
}
}
}
}
}

+ 6
- 1
source/storage/storage-rocksdb/src/main/java/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBConnection.java View File

@@ -8,6 +8,7 @@ import org.rocksdb.RocksDBException;

import com.jd.blockchain.storage.service.DbConnection;
import com.jd.blockchain.storage.service.KVStorageService;
import com.jd.blockchain.utils.io.FileUtils;

public class RocksDBConnection implements DbConnection {

@@ -19,6 +20,10 @@ public class RocksDBConnection implements DbConnection {

public RocksDBConnection(String dbPath, Options options) {
try {
String parentDir = FileUtils.getParent(dbPath);
if (!FileUtils.existDirectory(parentDir)) {
FileUtils.makeDirectory(parentDir);
}
this.db = RocksDB.open(options, dbPath);
} catch (RocksDBException e) {
throw new IllegalStateException(e.getMessage(), e);
@@ -43,7 +48,7 @@ public class RocksDBConnection implements DbConnection {
this.options = null;
RocksDB db = this.db;
this.db = null;
if (options != null) {
options.close();
}


+ 6
- 1
source/storage/storage-rocksdb/src/main/java/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBConnectionFactory.java View File

@@ -46,7 +46,7 @@ public class RocksDBConnectionFactory implements DbConnectionFactory {
String.format("Not supported db connection string with scheme \"%s\"!", dbUri.getScheme()));
}

String uriHead = URI_SCHEME + "://";
String uriHead = dbPrefix();
int beginIndex = dbConnectionString.indexOf(uriHead);
String dbPath = dbConnectionString.substring(beginIndex + uriHead.length());
if (!dbPath.startsWith(File.separator)) {
@@ -67,6 +67,11 @@ public class RocksDBConnectionFactory implements DbConnectionFactory {
}


@Override
public String dbPrefix() {
return URI_SCHEME + "://";
}

@Override
public boolean support(String scheme) {
return URI_SCHEME.equalsIgnoreCase(scheme);


+ 7
- 1
source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/DbConnectionFactory.java View File

@@ -3,7 +3,13 @@ package com.jd.blockchain.storage.service;
import java.io.Closeable;

public interface DbConnectionFactory extends Closeable {

/**
* 数据库连接前缀
* @return
*/
String dbPrefix();

/**
* 是否支持指定 scheme 的连接字符串;
* @param scheme


+ 5
- 0
source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryDBConnFactory.java View File

@@ -25,6 +25,11 @@ public class MemoryDBConnFactory implements DbConnectionFactory {

private Map<String, DbConnection> memMap = new ConcurrentHashMap<>();

@Override
public String dbPrefix() {
return "memory://";
}

@Override
public boolean support(String scheme) {
return true;


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save