diff --git a/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartConsensusClient.java b/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartConsensusClient.java index 25a995c7..9561263d 100644 --- a/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartConsensusClient.java +++ b/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartConsensusClient.java @@ -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); diff --git a/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartMessageService.java b/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartMessageService.java index a80375a4..53a5f0a8 100644 --- a/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartMessageService.java +++ b/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartMessageService.java @@ -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) { diff --git a/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartConsensusManageService.java b/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartConsensusManageService.java index a91f3f16..215486d0 100644 --- a/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartConsensusManageService.java +++ b/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartConsensusManageService.java @@ -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(); } diff --git a/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java b/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java index 635c0758..ce97797a 100644 --- a/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java +++ b/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java @@ -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 stateHandles = new CopyOnWriteArrayList<>(); -// private List batchConsensusListeners = new LinkedList<>(); - -// private Map> 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> 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 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 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 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 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 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, diff --git a/source/crypto/crypto-adv/pom.xml b/source/crypto/crypto-adv/pom.xml index dc01e85d..bf759175 100644 --- a/source/crypto/crypto-adv/pom.xml +++ b/source/crypto/crypto-adv/pom.xml @@ -27,20 +27,6 @@ ${project.version} - - org.powermock - powermock-module-junit4 - 1.6.2 - test - - - - org.powermock - powermock-api-mockito - 1.6.2 - test - - net.i2p.crypto eddsa @@ -52,11 +38,6 @@ 5.1.0 - - org.mockito - mockito-core - test - com.jd.blockchain crypto-framework diff --git a/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/mpc/MultiSum.java b/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/mpc/MultiSum.java index cb0316d3..45392f29 100644 --- a/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/mpc/MultiSum.java +++ b/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/mpc/MultiSum.java @@ -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); + } + } diff --git a/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/KeyPair.java b/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/KeyPair.java deleted file mode 100644 index 68fd6970..00000000 --- a/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/KeyPair.java +++ /dev/null @@ -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 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()); - } -} diff --git a/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/KeyPairBuilder.java b/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/KeyPairBuilder.java deleted file mode 100644 index c4234cae..00000000 --- a/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/KeyPairBuilder.java +++ /dev/null @@ -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. - *

- * 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. - *

- * 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. - *

- * The default is {@link SecureRandom}. - *

- * Warning: - * 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. - *

- * 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; - } -} diff --git a/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierKeyPairGenerator.java b/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierKeyPairGenerator.java new file mode 100644 index 00000000..abb72987 --- /dev/null +++ b/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierKeyPairGenerator.java @@ -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); + } +} diff --git a/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierPrivateKeyParameters.java b/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierPrivateKeyParameters.java new file mode 100644 index 00000000..5dcb2f0f --- /dev/null +++ b/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierPrivateKeyParameters.java @@ -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; + } +} diff --git a/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierPublicKeyParameters.java b/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierPublicKeyParameters.java new file mode 100644 index 00000000..3706b6b2 --- /dev/null +++ b/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierPublicKeyParameters.java @@ -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; + } +} diff --git a/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierUtils.java b/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierUtils.java index 4c199487..3d765df3 100644 --- a/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierUtils.java +++ b/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierUtils.java @@ -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 split(byte[] array, byte[] delimiter) { - List 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; } } diff --git a/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PrivateKey.java b/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PrivateKey.java deleted file mode 100644 index ac4b656a..00000000 --- a/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PrivateKey.java +++ /dev/null @@ -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 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()); - } -} diff --git a/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PublicKey.java b/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PublicKey.java deleted file mode 100644 index aa1d3f51..00000000 --- a/source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PublicKey.java +++ /dev/null @@ -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. - *

- * As in all asymmetric cryptographic systems it is responsible for the - * encryption. - *

- * 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 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()); - } -} - diff --git a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/EqualVerifyTest.java b/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/EqualVerifyTest.java index 372030a9..d310beab 100644 --- a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/EqualVerifyTest.java +++ b/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/EqualVerifyTest.java @@ -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); + } } \ No newline at end of file diff --git a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/IntCompareTest.java b/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/IntCompareTest.java index d02f668d..e018fb50 100644 --- a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/IntCompareTest.java +++ b/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/IntCompareTest.java @@ -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); } } \ No newline at end of file diff --git a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/MultiSumTest.java b/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/MultiSumTest.java index 4dff44cc..6c04a74a 100644 --- a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/MultiSumTest.java +++ b/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/MultiSumTest.java @@ -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; } } \ No newline at end of file diff --git a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/DecryptionTest.java b/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/DecryptionTest.java deleted file mode 100644 index 8994d9dc..00000000 --- a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/DecryptionTest.java +++ /dev/null @@ -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 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}; - } - -} - diff --git a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/HomomorphicPropertiesTest.java b/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/HomomorphicPropertiesTest.java deleted file mode 100644 index 2b156386..00000000 --- a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/HomomorphicPropertiesTest.java +++ /dev/null @@ -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); - } -} diff --git a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/JPaillierTest.java b/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/JPaillierTest.java deleted file mode 100644 index 12e0258d..00000000 --- a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/JPaillierTest.java +++ /dev/null @@ -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); - } -} diff --git a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/KeyPairBuilderPrivateKeyTest.java b/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/KeyPairBuilderPrivateKeyTest.java deleted file mode 100644 index ac64efda..00000000 --- a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/KeyPairBuilderPrivateKeyTest.java +++ /dev/null @@ -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); - } -} diff --git a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/KeyPairBuilderPublicKeyTest.java b/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/KeyPairBuilderPublicKeyTest.java deleted file mode 100644 index 5517c97f..00000000 --- a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/KeyPairBuilderPublicKeyTest.java +++ /dev/null @@ -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)); - } - -} diff --git a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/KeyPairBuilderTest.java b/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/KeyPairBuilderTest.java deleted file mode 100644 index 02efb028..00000000 --- a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/KeyPairBuilderTest.java +++ /dev/null @@ -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); - } - -} diff --git a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/PaillierUtilsTest.java b/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/PaillierUtilsTest.java new file mode 100644 index 00000000..8ace44d1 --- /dev/null +++ b/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/PaillierUtilsTest.java @@ -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; + } +} diff --git a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/ResolveTest.java b/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/ResolveTest.java deleted file mode 100644 index 05022dad..00000000 --- a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/ResolveTest.java +++ /dev/null @@ -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())); - - } -} diff --git a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ClassicCryptoService.java b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ClassicCryptoService.java index 164f966c..e47edd21 100644 --- a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ClassicCryptoService.java +++ b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ClassicCryptoService.java @@ -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 FUNCTIONS; static { - List funcs = Arrays.asList(AES, ED25519, RIPEMD160, SHA256, JVM_SECURE_RANDOM); + List funcs = Arrays.asList(AES, ED25519, ECDSA, RSA, RIPEMD160, SHA256, JVM_SECURE_RANDOM); FUNCTIONS = Collections.unmodifiableList(funcs); } diff --git a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ECDSASignatureFunction.java b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ECDSASignatureFunction.java index 478c7733..d7ebe0b7 100644 --- a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ECDSASignatureFunction.java +++ b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ECDSASignatureFunction.java @@ -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; } } diff --git a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ED25519SignatureFunction.java b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ED25519SignatureFunction.java index e4ae762d..555586b5 100644 --- a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ED25519SignatureFunction.java +++ b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ED25519SignatureFunction.java @@ -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)); - } } diff --git a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RIPEMD160HashFunction.java b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RIPEMD160HashFunction.java index cddda981..47172e87 100644 --- a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RIPEMD160HashFunction.java +++ b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RIPEMD160HashFunction.java @@ -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); } diff --git a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RSACryptoFunction.java b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RSACryptoFunction.java index e37c6d35..b7bd9c8d 100644 --- a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RSACryptoFunction.java +++ b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RSACryptoFunction.java @@ -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)); } } diff --git a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/SHA256HashFunction.java b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/SHA256HashFunction.java index e2ea162a..7ba4ec6a 100644 --- a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/SHA256HashFunction.java +++ b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/SHA256HashFunction.java @@ -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); } diff --git a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/AESUtils.java b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/AESUtils.java new file mode 100644 index 00000000..e1b3eaf4 --- /dev/null +++ b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/AESUtils.java @@ -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; + } +} diff --git a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/ECDSAUtils.java b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/ECDSAUtils.java index 3e3f0714..c2908f99 100644 --- a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/ECDSAUtils.java +++ b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/ECDSAUtils.java @@ -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(); diff --git a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RIPEMD160Utils.java b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RIPEMD160Utils.java new file mode 100644 index 00000000..05b11a6a --- /dev/null +++ b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RIPEMD160Utils.java @@ -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; + } +} diff --git a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java index 7724de86..3515a435 100644 --- a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java +++ b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java @@ -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; + } } diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/ECDSASignatureFunctionTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/ECDSASignatureFunctionTest.java new file mode 100644 index 00000000..030f6f47 --- /dev/null +++ b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/ECDSASignatureFunctionTest.java @@ -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())); + } +} diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/RSACryptoFunctionTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/RSACryptoFunctionTest.java new file mode 100644 index 00000000..3eefed1c --- /dev/null +++ b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/RSACryptoFunctionTest.java @@ -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())); + } + +} diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/AESUtilsTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/AESUtilsTest.java new file mode 100644 index 00000000..145229bd --- /dev/null +++ b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/AESUtilsTest.java @@ -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)); +// } +// } +} diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/ECDSAUtilsTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/ECDSAUtilsTest.java index 7cb63291..522b3584 100644 --- a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/ECDSAUtilsTest.java +++ b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/ECDSAUtilsTest.java @@ -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; } - - } diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/ED25519UtilsTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/ED25519UtilsTest.java index afbea883..8fa293a9 100644 --- a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/ED25519UtilsTest.java +++ b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/ED25519UtilsTest.java @@ -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)); + } + + } + } diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RIPEMD160UtilsTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RIPEMD160UtilsTest.java new file mode 100644 index 00000000..28285055 --- /dev/null +++ b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RIPEMD160UtilsTest.java @@ -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)); + } +} diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java new file mode 100644 index 00000000..3e68c8c6 --- /dev/null +++ b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java @@ -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); + + } +} diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/SHA256UtilsTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/SHA256UtilsTest.java index b86bdc88..498722e6 100644 --- a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/SHA256UtilsTest.java +++ b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/SHA256UtilsTest.java @@ -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 { diff --git a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/BaseCryptoKey.java b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/BaseCryptoKey.java index dd2726c7..95cfee3d 100644 --- a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/BaseCryptoKey.java +++ b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/BaseCryptoKey.java @@ -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)); diff --git a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/PrivKey.java b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/PrivKey.java index b15bb5e7..78af68c4 100644 --- a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/PrivKey.java +++ b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/PrivKey.java @@ -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) { diff --git a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/PubKey.java b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/PubKey.java index ca5b43c8..3d59dd3a 100644 --- a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/PubKey.java +++ b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/PubKey.java @@ -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); } diff --git a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/serialize/ByteArrayObjectDeserializer.java b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/serialize/ByteArrayObjectDeserializer.java deleted file mode 100644 index 42654a66..00000000 --- a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/serialize/ByteArrayObjectDeserializer.java +++ /dev/null @@ -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 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 map, ParserConfig config) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { - if (map == null || map.isEmpty()) { - return null; - } - for (Map.Entry 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; - } -} diff --git a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/serialize/ByteArrayObjectSerializer.java b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/serialize/ByteArrayObjectSerializer.java deleted file mode 100644 index 282605ed..00000000 --- a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/serialize/ByteArrayObjectSerializer.java +++ /dev/null @@ -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; - } - } -} diff --git a/source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/service/sm/SM2CryptoFunction.java b/source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/service/sm/SM2CryptoFunction.java index 8d5cba8a..344aac35 100644 --- a/source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/service/sm/SM2CryptoFunction.java +++ b/source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/service/sm/SM2CryptoFunction.java @@ -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!"); } } diff --git a/source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/utils/sm/SM4Utils.java b/source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/utils/sm/SM4Utils.java index 63295f49..323243d4 100644 --- a/source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/utils/sm/SM4Utils.java +++ b/source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/utils/sm/SM4Utils.java @@ -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); diff --git a/source/crypto/crypto-sm/src/test/java/test/com/jd/blockchain/crypto/service/sm/SM2CyptoFunctionTest.java b/source/crypto/crypto-sm/src/test/java/test/com/jd/blockchain/crypto/service/sm/SM2CyptoFunctionTest.java index cb036dfb..d9e438f3 100644 --- a/source/crypto/crypto-sm/src/test/java/test/com/jd/blockchain/crypto/service/sm/SM2CyptoFunctionTest.java +++ b/source/crypto/crypto-sm/src/test/java/test/com/jd/blockchain/crypto/service/sm/SM2CyptoFunctionTest.java @@ -484,5 +484,4 @@ public class SM2CyptoFunctionTest { assertNotNull(actualEx); assertTrue(expectedException.isAssignableFrom(actualEx.getClass())); } - } diff --git a/source/crypto/crypto-sm/src/test/java/test/com/jd/blockchain/crypto/utils/SM2UtilsTest.java b/source/crypto/crypto-sm/src/test/java/test/com/jd/blockchain/crypto/utils/SM2UtilsTest.java index a91faddf..014c1c31 100644 --- a/source/crypto/crypto-sm/src/test/java/test/com/jd/blockchain/crypto/utils/SM2UtilsTest.java +++ b/source/crypto/crypto-sm/src/test/java/test/com/jd/blockchain/crypto/utils/SM2UtilsTest.java @@ -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)); + } + } } \ No newline at end of file diff --git a/source/deployment/deployment-peer/pom.xml b/source/deployment/deployment-peer/pom.xml index 9751b803..1d5f9fc5 100644 --- a/source/deployment/deployment-peer/pom.xml +++ b/source/deployment/deployment-peer/pom.xml @@ -25,6 +25,28 @@ runtime-modular-booter ${project.version} + + + com.jd.blockchain + storage-composite + ${project.version} + + + com.jd.blockchain + storage-service + ${project.version} + + + com.jd.blockchain + storage-redis + ${project.version} + + + com.jd.blockchain + storage-rocksdb + ${project.version} + + diff --git a/source/deployment/deployment-peer/src/main/resources/assembly.xml b/source/deployment/deployment-peer/src/main/resources/assembly.xml index d445b9cb..5e64c93e 100644 --- a/source/deployment/deployment-peer/src/main/resources/assembly.xml +++ b/source/deployment/deployment-peer/src/main/resources/assembly.xml @@ -62,15 +62,6 @@ true com.jd.blockchain:tools-initializer-booter - - - libs - false - - - - true - com.jd.blockchain:tools-keygen-booter diff --git a/source/gateway/.gitignore b/source/gateway/.gitignore index 24d64373..4f496dc3 100644 --- a/source/gateway/.gitignore +++ b/source/gateway/.gitignore @@ -1 +1,2 @@ /target/ +/.apt_generated_tests/ diff --git a/source/gateway/pom.xml b/source/gateway/pom.xml index f21abfba..3150363e 100644 --- a/source/gateway/pom.xml +++ b/source/gateway/pom.xml @@ -15,6 +15,17 @@ consensus-framework ${project.version} + + com.jd.blockchain + consensus-bftsmart + ${project.version} + + + com.jd.blockchain + consensus-mq + ${project.version} + + com.jd.blockchain ledger-rpc @@ -43,11 +54,22 @@ ${project.version} + + com.jd.blockchain + crypto-framework + ${project.version} + + com.jd.blockchain crypto-classic ${project.version} - test + + + + com.jd.blockchain + crypto-sm + ${project.version} diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryService.java b/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryService.java index 73b5d64e..6cd1828c 100644 --- a/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryService.java +++ b/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryService.java @@ -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); } diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceHandler.java b/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceHandler.java new file mode 100644 index 00000000..71e34a7c --- /dev/null +++ b/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceHandler.java @@ -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); + } +} diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceImpl.java b/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceImpl.java index 4f3c5a36..24433b70 100644 --- a/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceImpl.java +++ b/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceImpl.java @@ -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; +// } +//} diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java b/source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java index 68243eb4..381cc50f 100644 --- a/source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java +++ b/source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java @@ -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); diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/web/GatewayWebServerConfigurer.java b/source/gateway/src/main/java/com/jd/blockchain/gateway/web/GatewayWebServerConfigurer.java index 5174950e..b93a8008 100644 --- a/source/gateway/src/main/java/com/jd/blockchain/gateway/web/GatewayWebServerConfigurer.java +++ b/source/gateway/src/main/java/com/jd/blockchain/gateway/web/GatewayWebServerConfigurer.java @@ -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(); } } diff --git a/source/gateway/src/main/resources/gateway.conf b/source/gateway/src/main/resources/gateway.conf index 84f00679..c8ceaf4e 100644 --- a/source/gateway/src/main/resources/gateway.conf +++ b/source/gateway/src/main/resources/gateway.conf @@ -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 \ No newline at end of file diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminAccount.java index 68f77f29..88ab790a 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminAccount.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminAccount.java @@ -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; diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdministration.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdministration.java index 79632ae4..cc09138f 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdministration.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdministration.java @@ -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 { diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerConfiguration.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerConfiguration.java index ef34122b..5605003c 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerConfiguration.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerConfiguration.java @@ -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 { diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerMetadata.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerMetadata.java index 4e8f05e5..68d51ae2 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerMetadata.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerMetadata.java @@ -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(); +// +//} diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSetting.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSetting.java index 21ce0565..6e9ad134 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSetting.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSetting.java @@ -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(); - -} \ No newline at end of file +//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(); +// +//} \ No newline at end of file diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java index e7131c5a..086b18ff 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java @@ -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; + } } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerRepositoryImpl.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerRepositoryImpl.java index 865f18d0..3182c736 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerRepositoryImpl.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerRepositoryImpl.java @@ -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), diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionalEditor.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionalEditor.java index 4277434d..5bb29512 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionalEditor.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionalEditor.java @@ -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()); diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java index 75d81904..2d51c185 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java @@ -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); diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerAdminAccountTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerAdminAccountTest.java index af06d0b1..823b3397 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerAdminAccountTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerAdminAccountTest.java @@ -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; diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerMetaDataTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerMetaDataTest.java index 19886d4b..f744780d 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerMetaDataTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerMetaDataTest.java @@ -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; diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerMetadata.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerMetadata.java new file mode 100644 index 00000000..4d7a57b0 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerMetadata.java @@ -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(); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerSetting.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerSetting.java new file mode 100644 index 00000000..1a0441bd --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerSetting.java @@ -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(); + +} \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java index 3b33a720..45301f13 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java @@ -36,6 +36,14 @@ public interface BlockchainQueryService { */ ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash); + /** + * 返回当前账本的元数据 + * + * @param ledgerHash + * @return + */ + LedgerMetadata getLedgerMetadata(HashDigest ledgerHash); + /** * 返回指定账本序号的区块; * diff --git a/source/ledger/ledger-rpc/src/main/java/com/jd/blockchain/web/serializes/ByteArrayObjectJsonDeserializer.java b/source/ledger/ledger-rpc/src/main/java/com/jd/blockchain/web/serializes/ByteArrayObjectJsonDeserializer.java new file mode 100644 index 00000000..c0384183 --- /dev/null +++ b/source/ledger/ledger-rpc/src/main/java/com/jd/blockchain/web/serializes/ByteArrayObjectJsonDeserializer.java @@ -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 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 map, ParserConfig config) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { + if (map == null || map.isEmpty()) { + return null; + } + for (Map.Entry 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; + } +} diff --git a/source/ledger/ledger-rpc/src/main/java/com/jd/blockchain/web/serializes/ByteArrayObjectJsonSerializer.java b/source/ledger/ledger-rpc/src/main/java/com/jd/blockchain/web/serializes/ByteArrayObjectJsonSerializer.java new file mode 100644 index 00000000..896e1f4a --- /dev/null +++ b/source/ledger/ledger-rpc/src/main/java/com/jd/blockchain/web/serializes/ByteArrayObjectJsonSerializer.java @@ -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; + } + } +} diff --git a/source/ledger/ledger-rpc/src/main/java/com/jd/blockchain/web/serializes/ByteArrayObjectUtil.java b/source/ledger/ledger-rpc/src/main/java/com/jd/blockchain/web/serializes/ByteArrayObjectUtil.java new file mode 100644 index 00000000..e6d23910 --- /dev/null +++ b/source/ledger/ledger-rpc/src/main/java/com/jd/blockchain/web/serializes/ByteArrayObjectUtil.java @@ -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)); + } + } +} \ No newline at end of file diff --git a/source/peer/.gitignore b/source/peer/.gitignore index 24d64373..4f496dc3 100644 --- a/source/peer/.gitignore +++ b/source/peer/.gitignore @@ -1 +1,2 @@ /target/ +/.apt_generated_tests/ diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java b/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java index e221ba98..6db9674c 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java @@ -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, diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/web/PeerWebServerConfigurer.java b/source/peer/src/main/java/com/jd/blockchain/peer/web/PeerWebServerConfigurer.java index bc286117..f0d52ac5 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/web/PeerWebServerConfigurer.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/web/PeerWebServerConfigurer.java @@ -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(); } } diff --git a/source/pom.xml b/source/pom.xml index 3b9b2efa..f8c9dfce 100644 --- a/source/pom.xml +++ b/source/pom.xml @@ -297,6 +297,25 @@ commons-collections4 4.1 + + + + org.reflections + reflections + 0.9.10 + + + com.google.guava + guava + + + + + + com.google.guava + guava + 19.0 + diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/LedgerInitSettings.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/LedgerInitSettings.java new file mode 100644 index 00000000..fa3c2cd0 --- /dev/null +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/LedgerInitSettings.java @@ -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; + } + } +} diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java index da602b9b..4dbe7bc9 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java @@ -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); } diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java index 19df6c9a..bfdc0baf 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java @@ -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); + /** * 返回指定账本序号的区块; * diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/service/NodeSigningAppender.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/service/NodeSigningAppender.java index 52f289a8..17611678 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/service/NodeSigningAppender.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/service/NodeSigningAppender.java @@ -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); diff --git a/source/sdk/sdk-client/pom.xml b/source/sdk/sdk-client/pom.xml index a33f309d..17ccdf88 100644 --- a/source/sdk/sdk-client/pom.xml +++ b/source/sdk/sdk-client/pom.xml @@ -14,5 +14,11 @@ sdk-base ${project.version} + + + com.jd.blockchain + ledger-rpc + ${project.version} + \ No newline at end of file diff --git a/source/sdk/sdk-client/src/main/java/com/jd/blockchain/sdk/client/GatewayServiceFactory.java b/source/sdk/sdk-client/src/main/java/com/jd/blockchain/sdk/client/GatewayServiceFactory.java index 49348b90..5396a430 100644 --- a/source/sdk/sdk-client/src/main/java/com/jd/blockchain/sdk/client/GatewayServiceFactory.java +++ b/source/sdk/sdk-client/src/main/java/com/jd/blockchain/sdk/client/GatewayServiceFactory.java @@ -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; diff --git a/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Query_Test_.java b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Query_Test_.java index a5343eb6..3851d6a7 100644 --- a/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Query_Test_.java +++ b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Query_Test_.java @@ -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; diff --git a/source/storage/storage-composite/pom.xml b/source/storage/storage-composite/pom.xml index a080704a..ca8012d2 100644 --- a/source/storage/storage-composite/pom.xml +++ b/source/storage/storage-composite/pom.xml @@ -14,7 +14,7 @@ storage-service ${project.version} - + + + org.reflections + reflections + + + + com.google.guava + guava + + + + org.springframework.boot + spring-boot + + + org.springframework.boot + spring-boot-autoconfigure + + + org.springframework.boot + spring-boot-configuration-processor + true + +