| @@ -1,5 +1,5 @@ | |||
| [TOC] | |||
| #JD区块链 0.8.3-SNAPSHOT | |||
| #JD区块链 0.5.0-SNAPSHOT | |||
| ------------------------------------------------------------------------ | |||
| ### 版本修订历史 | |||
| @@ -354,266 +354,325 @@ JD区块链的核心对象包括: | |||
| ## 五、编程接口 | |||
| ### 1. 服务连接 | |||
| // 区块链共识域; | |||
| String realm = "SUPPLY_CHAIN_ALLIANCE"; | |||
| // 节点地址列表; | |||
| String[] peerIPs = { "192.168.10.10", "192.168.10.11", "192.168.10.12", "192.168.10.13" }; | |||
| // 客户端的认证账户; | |||
| String clientAddress = "kkjsafieweqEkadsfaslkdslkae998232jojf=="; | |||
| String privKey = "safefsd32q34vdsvs"; | |||
| // 创建服务代理; | |||
| BlockchainService service = BlockchainServiceFactory.createServiceProxy(realm, peerIPs, clientAddress, privKey); | |||
| ### 2. 账户注册 | |||
| // 创建服务代理; | |||
| BlockchainService service = BlockchainServiceFactory.createServiceProxy(realm, peerIPs, clientAddress, privKey); | |||
| // 在本地定义注册账号的 TX; | |||
| String sponsorAddress = "kFGeafiafEeqEkadsfaslkdslkae99ds66jf=="; | |||
| String sponsorPrivKey = "privKkjwlkejflkjdsfoiajfij329323=="; | |||
| TransactionTemplate txTemp = service.newTransaction(sponsorAddress); | |||
| //-------------------------------------- | |||
| // 区块链秘钥生成器;用于在客户端生成账户的公私钥和地址; | |||
| BlockchainKeyGenerator generator = BlockchainKeyGenerator.getInstance(); | |||
| BlockchainKeyPair bcKey1 = generator.generate(KeyType.ED25519); | |||
| BlockchainKeyPair bcKey2 = generator.generate(KeyType.ED25519); | |||
| String exchangeContractScript = "function(){}"; | |||
| // 注册账户; | |||
| txTemp.registerAccount() | |||
| .register(bcKey1, AccountStateType.MAP, exchangeContractScript) | |||
| .register(bcKey2, AccountStateType.OBJECT, null); | |||
| //-------------------------------------- | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| ```java | |||
| //创建服务代理 | |||
| public static BlockchainKeyPair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate(); | |||
| final String GATEWAY_IP = "127.0.0.1"; | |||
| final int GATEWAY_PORT = 80; | |||
| final boolean SECURE = false; | |||
| GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, | |||
| CLIENT_CERT); | |||
| // 创建服务代理; | |||
| BlockchainService service = serviceFactory.getBlockchainService(); | |||
| ``` | |||
| ### 2. 用户注册 | |||
| ```java | |||
| // 创建服务代理; | |||
| BlockchainService service = serviceFactory.getBlockchainService(); | |||
| // 在本地定义注册账号的 TX; | |||
| TransactionTemplate txTemp = service.newTransaction(ledgerHash); | |||
| SignatureFunction signatureFunction = asymmetricCryptography.getSignatureFunction(CryptoAlgorithm.ED25519); | |||
| CryptoKeyPair cryptoKeyPair = signatureFunction.generateKeyPair(); | |||
| BlockchainKeyPair user = new BlockchainKeyPair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); | |||
| txTemp.users().register(user.getIdentity()); | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| // 使用私钥进行签名; | |||
| CryptoKeyPair keyPair = getSponsorKey(); | |||
| prepTx.sign(keyPair); | |||
| // 提交交易; | |||
| prepTx.commit(); | |||
| ``` | |||
| ### 3. 数据账户注册 | |||
| ```java | |||
| // 创建服务代理; | |||
| BlockchainService service = serviceFactory.getBlockchainService(); | |||
| // 在本地定义注册账号的 TX; | |||
| TransactionTemplate txTemp = service.newTransaction(ledgerHash); | |||
| SignatureFunction signatureFunction = asymmetricCryptography.getSignatureFunction(CryptoAlgorithm.ED25519); | |||
| CryptoKeyPair cryptoKeyPair = signatureFunction.generateKeyPair(); | |||
| BlockchainKeyPair dataAccount = new BlockchainKeyPair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); | |||
| txTemp.dataAccounts().register(dataAccount.getIdentity()); | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| // 使用私钥进行签名; | |||
| CryptoKeyPair keyPair = getSponsorKey(); | |||
| prepTx.sign(keyPair); | |||
| // 提交交易; | |||
| prepTx.commit(); | |||
| ``` | |||
| ### 4. 写入数据 | |||
| ```java | |||
| // 创建服务代理; | |||
| BlockchainService service = serviceFactory.getBlockchainService(); | |||
| HashDigest ledgerHash = getLedgerHash(); | |||
| // 在本地定义注册账号的 TX; | |||
| TransactionTemplate txTemp = service.newTransaction(ledgerHash); | |||
| // -------------------------------------- | |||
| // 将商品信息写入到指定的账户中; | |||
| // 对象将被序列化为 JSON 形式存储,并基于 JSON 结构建立查询索引; | |||
| String commodityDataAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; | |||
| Commodity commodity1 = new Commodity(); | |||
| txTemp.dataAccount(commodityDataAccount).set("ASSET_CODE", commodity1.getCode().getBytes(), -1); | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| String txHash = ByteArray.toBase64(prepTx.getHash().toBytes()); | |||
| // 使用私钥进行签名; | |||
| CryptoKeyPair keyPair = getSponsorKey(); | |||
| prepTx.sign(keyPair); | |||
| // 提交交易; | |||
| prepTx.commit(); | |||
| ``` | |||
| ### 5. 查询数据 | |||
| > 注:详细的查询可参考模块sdk-samples中SDK_GateWay_Query_Test_相关测试用例 | |||
| ```java | |||
| // 创建服务代理; | |||
| BlockchainService service = serviceFactory.getBlockchainService(); | |||
| // 查询区块信息; | |||
| // 区块高度; | |||
| long ledgerNumber = service.getLedger(LEDGER_HASH).getLatestBlockHeight(); | |||
| // 最新区块; | |||
| LedgerBlock latestBlock = service.getBlock(LEDGER_HASH, ledgerNumber); | |||
| // 区块中的交易的数量; | |||
| long txCount = service.getTransactionCount(LEDGER_HASH, latestBlock.getHash()); | |||
| // 获取交易列表; | |||
| LedgerTransaction[] txList = service.getTransactions(LEDGER_HASH, ledgerNumber, 0, 100); | |||
| // 遍历交易列表 | |||
| for (LedgerTransaction ledgerTransaction : txList) { | |||
| TransactionContent txContent = ledgerTransaction.getTransactionContent(); | |||
| Operation[] operations = txContent.getOperations(); | |||
| if (operations != null && operations.length > 0) { | |||
| for (Operation operation : operations) { | |||
| operation = ClientOperationUtil.read(operation); | |||
| // 操作类型:数据账户注册操作 | |||
| if (operation instanceof DataAccountRegisterOperation) { | |||
| DataAccountRegisterOperation daro = (DataAccountRegisterOperation) operation; | |||
| BlockchainIdentity blockchainIdentity = daro.getAccountID(); | |||
| } | |||
| // 操作类型:用户注册操作 | |||
| else if (operation instanceof UserRegisterOperation) { | |||
| UserRegisterOperation uro = (UserRegisterOperation) operation; | |||
| BlockchainIdentity blockchainIdentity = uro.getUserID(); | |||
| } | |||
| // 操作类型:账本注册操作 | |||
| else if (operation instanceof LedgerInitOperation) { | |||
| LedgerInitOperation ledgerInitOperation = (LedgerInitOperation)operation; | |||
| LedgerInitSetting ledgerInitSetting = ledgerInitOperation.getInitSetting(); | |||
| ParticipantNode[] participantNodes = ledgerInitSetting.getConsensusParticipants(); | |||
| } | |||
| // 操作类型:合约发布操作 | |||
| else if (operation instanceof ContractCodeDeployOperation) { | |||
| ContractCodeDeployOperation ccdo = (ContractCodeDeployOperation) operation; | |||
| BlockchainIdentity blockchainIdentity = ccdo.getContractID(); | |||
| } | |||
| // 操作类型:合约执行操作 | |||
| else if (operation instanceof ContractEventSendOperation) { | |||
| ContractEventSendOperation ceso = (ContractEventSendOperation) operation; | |||
| } | |||
| // 操作类型:KV存储操作 | |||
| else if (operation instanceof DataAccountKVSetOperation) { | |||
| DataAccountKVSetOperation.KVWriteEntry[] kvWriteEntries = | |||
| ((DataAccountKVSetOperation) operation).getWriteSet(); | |||
| if (kvWriteEntries != null && kvWriteEntries.length > 0) { | |||
| for (DataAccountKVSetOperation.KVWriteEntry kvWriteEntry : kvWriteEntries) { | |||
| BytesValue bytesValue = kvWriteEntry.getValue(); | |||
| DataType dataType = bytesValue.getType(); | |||
| Object showVal = ClientOperationUtil.readValueByBytesValue(bytesValue); | |||
| System.out.println("writeSet.key=" + kvWriteEntry.getKey()); | |||
| System.out.println("writeSet.value=" + showVal); | |||
| System.out.println("writeSet.type=" + dataType); | |||
| System.out.println("writeSet.version=" + kvWriteEntry.getExpectedVersion()); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| // 根据交易的 hash 获得交易;注:客户端生成 PrepareTransaction 时得到交易hash; | |||
| HashDigest txHash = txList[0].getTransactionContent().getHash(); | |||
| Transaction tx = service.getTransactionByContentHash(LEDGER_HASH, txHash); | |||
| // 获取数据; | |||
| String commerceAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; | |||
| String[] objKeys = new String[] { "x001", "x002" }; | |||
| KVDataEntry[] kvData = service.getDataEntries(LEDGER_HASH, commerceAccount, objKeys); | |||
| long payloadVersion = kvData[0].getVersion(); | |||
| // 获取数据账户下所有的KV列表 | |||
| KVDataEntry[] kvData = service.getDataEntries(ledgerHash, commerceAccount, 0, 100); | |||
| if (kvData != null && kvData.length > 0) { | |||
| for (KVDataEntry kvDatum : kvData) { | |||
| System.out.println("kvData.key=" + kvDatum.getKey()); | |||
| System.out.println("kvData.version=" + kvDatum.getVersion()); | |||
| System.out.println("kvData.type=" + kvDatum.getType()); | |||
| System.out.println("kvData.value=" + kvDatum.getValue()); | |||
| } | |||
| } | |||
| ``` | |||
| ### 6. 合约发布 | |||
| ```java | |||
| // 创建服务代理; | |||
| BlockchainService service = serviceFactory.getBlockchainService(); | |||
| // 在本地定义TX模板 | |||
| TransactionTemplate txTemp = service.newTransaction(ledgerHash); | |||
| // 合约内容读取 | |||
| byte[] contractBytes = FileUtils.readBytes(new File(CONTRACT_FILE)); | |||
| // 生成用户 | |||
| BlockchainIdentityData blockchainIdentity = new BlockchainIdentityData(getSponsorKey().getPubKey()); | |||
| // 发布合约 | |||
| txTemp.contracts().deploy(blockchainIdentity, contractBytes); | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| // 使用私钥进行签名; | |||
| CryptoKeyPair keyPair = getSponsorKey(); | |||
| prepTx.sign(keyPair); | |||
| // 提交交易; | |||
| TransactionResponse transactionResponse = prepTx.commit(); | |||
| assertTrue(transactionResponse.isSuccess()); | |||
| // 打印合约地址 | |||
| System.out.println(blockchainIdentity.getAddress().toBase58()); | |||
| ``` | |||
| ### 7. 合约执行 | |||
| ```java | |||
| // 创建服务代理; | |||
| BlockchainService service = serviceFactory.getBlockchainService(); | |||
| // 在本地定义TX模板 | |||
| TransactionTemplate txTemp = service.newTransaction(ledgerHash); | |||
| // 合约地址 | |||
| String contractAddressBase58 = ""; | |||
| // Event | |||
| String event = ""; | |||
| // 使用私钥进行签名; | |||
| prepTx.sign(sponsorAddress, sponsorPrivKey); | |||
| // args(注意参数的格式) | |||
| byte[] args = "20##30##abc".getBytes(); | |||
| // 提交交易; | |||
| prepTx.commit(); | |||
| ### 3. 权限设置 | |||
| // 提交合约执行代码 | |||
| txTemp.contractEvents().send(contractAddressBase58, event, args); | |||
| // 创建服务代理; | |||
| BlockchainService service = BlockchainServiceFactory.createServiceProxy(realm, peerIPs, clientAddress, privKey); | |||
| // 在本地定义注册账号的 TX; | |||
| String sponsorAddress = "kFGeafiafEeqEkadsfaslkdslkae99ds66jf=="; | |||
| String sponsorPrivKey = "privKkjwlkejflkjdsfoiajfij329323=="; | |||
| TransactionTemplate txTemp = service.newTransaction(sponsorAddress); | |||
| //-------------------------------------- | |||
| // 配置账户的权限; | |||
| String walletAccount = "Kjfe8832hfa9jjjJJDkshrFjksjdlkfj93F=="; | |||
| String user1 = "MMMEy902jkjjJJDkshreGeasdfassdfajjf=="; | |||
| String user2 = "Kjfe8832hfa9jjjJJDkshrFjksjdlkfj93F=="; | |||
| // 配置: | |||
| // “状态数据的写入权限”的阈值为 100; | |||
| // 需要 user1、user2 两个账户的联合签名才能写入; | |||
| // 当前账户仅用于表示一个业务钱包,禁止自身的写入权限,只能由业务角色的账户才能操作; | |||
| txTemp.configPrivilege(walletAccount) | |||
| .setThreshhold(PrivilegeType.STATE_WRITE, 100) | |||
| .enable(PrivilegeType.STATE_WRITE, user1, 50) | |||
| .enable(PrivilegeType.STATE_WRITE, user2, 50) | |||
| .disable(PrivilegeType.STATE_WRITE, walletAccount); | |||
| //-------------------------------------- | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| // 使用私钥进行签名; | |||
| prepTx.sign(sponsorAddress, sponsorPrivKey); | |||
| // 提交交易; | |||
| prepTx.commit(); | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| ### 4. 写入数据 | |||
| // 生成私钥并使用私钥进行签名; | |||
| CryptoKeyPair keyPair = getSponsorKey(); | |||
| // 创建服务代理; | |||
| BlockchainService service = BlockchainServiceFactory.createServiceProxy(realm, peerIPs, clientAddress, privKey); | |||
| // 在本地定义注册账号的 TX; | |||
| String sponsorAddress = "kFGeafiafEeqEkadsfaslkdslkae99ds66jf=="; | |||
| String sponsorPrivKey = "privKkjwlkejflkjdsfoiajfij329323=="; | |||
| TransactionTemplate txTemp = service.newTransaction(sponsorAddress); | |||
| // -------------------------------------- | |||
| // 将商品信息写入到指定的账户中; | |||
| // 对象将被序列化为 JSON 形式存储,并基于 JSON 结构建立查询索引; | |||
| String commodityDataAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; | |||
| Commodity commodity1 = new Commodity(); | |||
| Commodity commodity2 = new Commodity(); | |||
| txTemp.updateObjects(commodityDataAccount) | |||
| .insert(commodity1.getCode(), commodity1) | |||
| .update(commodity2.getCode(), commodity2, true); | |||
| // 在钱包账户以 KEY “RMB-ASSET” 表示一种数字资产,通过在一个 TX | |||
| // 对两个账户的同一个资产数值分别增加和减少,实现转账的功能; | |||
| String walletAccount1 = "MMMEy902jkjjJJDkshreGeasdfassdfajjf=="; | |||
| String walletAccount2 = "Kjfe8832hfa9jjjJJDkshrFjksjdlkfj93F=="; | |||
| txTemp.updateMap(walletAccount1).decreaseInt("RMB-ASSET", 1000); | |||
| txTemp.updateMap(walletAccount2).increaseInt("RMB-ASSET", 1000); | |||
| // -------------------------------------- | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| String txHash = prepTx.getHash(); | |||
| // 使用私钥进行签名; | |||
| prepTx.sign(sponsorAddress, sponsorPrivKey); | |||
| // 提交交易; | |||
| prepTx.commit(); | |||
| ### 5. 查询数据 | |||
| // 创建服务代理; | |||
| BlockchainService service = BlockchainServiceFactory.createServiceProxy(realm, peerIPs, clientAddress, privKey); | |||
| // 查询区块信息; | |||
| // 区块高度; | |||
| long ledgerNumber = service.getLedgerNumber(); | |||
| // 最新区块; | |||
| Block latestBlock = service.getBlock(ledgerNumber); | |||
| // 区块中的交易的数量; | |||
| int txCount = latestBlock.getTxCount(); | |||
| // 获取交易列表; | |||
| Transaction[] txList = service.getTransactions(ledgerNumber, 0, 100); | |||
| // 根据交易的 hash 获得交易;注:客户端生成 PrepareTransaction 时得到交易hash; | |||
| String txHash = "iikjeqke98321rjoijsdfa"; | |||
| Transaction tx = service.getTransaction(txHash); | |||
| // 获取数据; | |||
| String commerceAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; | |||
| Set<String> objKeys = ArrayUtils.asSet(new String[] { "x001", "x002" }); | |||
| PayloadMap payloadData = service.getPayload(commerceAccount, objKeys); | |||
| AccountStateType payloadType = payloadData.getPayloadType(); | |||
| long payloadVersion = payloadData.getPayloadVersion(); | |||
| boolean exist = service.containPayload(commerceAccount, "x003"); | |||
| // 按条件查询; | |||
| // 1、从保存会员信息的账户地址查询; | |||
| String condition = "female = true AND age > 18 AND address.city = 'beijing'"; | |||
| String memberInfoAccountAddress = "kkf2io39823jfIjfiIRWKQj30203fx=="; | |||
| PayloadMap memberInfo = service.queryObject(memberInfoAccountAddress, condition); | |||
| // 2、从保存会员信息的账户地址查询; | |||
| Map<String, PayloadMap> memberInfoWithAccounts = service.queryObject(condition); | |||
| ### 6. 合约调用 | |||
| // 创建服务代理; | |||
| BlockchainService service = BlockchainServiceFactory.createServiceProxy(realm, peerIPs, clientAddress, privKey); | |||
| // 发起交易; | |||
| String sponsorAddress = "kFGeafiafEeqEkadsfaslkdslkae99ds66jf=="; | |||
| String sponsorPrivKey = "privKkjwlkejflkjdsfoiajfij329323=="; | |||
| TransactionTemplate txTemp = service.newTransaction(sponsorAddress); | |||
| // -------------------------------------- | |||
| // 一个贸易账户,贸易结算后的利润将通过一个合约账户来执行利润分配; | |||
| // 合约账户被设置为通用的账户,不具备对贸易结算账户的直接权限; | |||
| // 只有当前交易发起人具备对贸易账户的直接权限,当交易发起人对交易进行签名之后,权限被间接传递给合约账户; | |||
| String commerceAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; | |||
| // 处理利润分成的通用业务逻辑的合约账户; | |||
| String profitDistributionContract = "AAdfe4346fHhefe34fwf343kaeER4678RT=="; | |||
| //收益人账户; | |||
| String receiptorAccount1 = "MMMEy902jkjjJJDkshreGeasdfassdfajjf=="; | |||
| String receiptorAccount2 = "Kjfe8832hfa9jjjJJDkshrFjksjdlkfj93F=="; | |||
| //资产编码; | |||
| String assetKey = "RMB-ASSET"; | |||
| //此次待分配利润; | |||
| long profit = 1000000; | |||
| //备注信息; | |||
| Remark remark = new Remark(); | |||
| String remarkJSON = SerializeUtils.serializeToJSON(remark); | |||
| // 合约代码的参数表; | |||
| String[] args = { commerceAccount, assetKey, profit+"", receiptorAccount1, receiptorAccount2, remarkJSON }; | |||
| // 调用合约代码的分配操作; | |||
| txTemp.executeScript(commerceAccount) | |||
| .invoke("DISTRIBUTE", args); | |||
| // -------------------------------------- | |||
| prepTx.sign(keyPair); | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| String txHash = prepTx.getHash(); | |||
| // 提交交易; | |||
| TransactionResponse transactionResponse = prepTx.commit(); | |||
| // 使用私钥进行签名; | |||
| prepTx.sign(sponsorAddress, sponsorPrivKey); | |||
| assertTrue(transactionResponse.isSuccess()); | |||
| // 提交交易; | |||
| prepTx.commit(); | |||
| ``` | |||
| ### 7. 事件监听 | |||
| // 创建服务代理; | |||
| BlockchainService service = BlockchainServiceFactory.createServiceProxy(realm, peerIPs, clientAddress, privKey); | |||
| //监听账户变动; | |||
| String walletAccount = "MMMEy902jkjjJJDkshreGeasdfassdfajjf=="; | |||
| service.addBlockchainEventListener(BlockchainEventType.PAYLOAD_UPDATED.CODE, null, walletAccount, new BlockchainEventListener() { | |||
| @Override | |||
| public void onEvent(BlockchainEventMessage eventMessage, BlockchainEventHandle eventHandle) { | |||
| //钱包余额; | |||
| PayloadMap balancePayload = service.getPayload(walletAccount, "RMB-ASSET"); | |||
| Long balance =(Long) balancePayload.get("RMB-ASSET"); | |||
| if (balance != null) { | |||
| //notify balance change; | |||
| }else{ | |||
| //wallet is empty and isn't listened any more; | |||
| eventHandle.cancel(); | |||
| } | |||
| } | |||
| }); | |||
| //销毁服务代理; | |||
| service.dispose(); | |||
| ### 8. 合约开发 | |||
| /** | |||
| * 示例:一个“资产管理”智能合约的实现; | |||
| * | |||
| * 注: 1、实现 EventProcessingAwire 接口以便合约实例在运行时可以从上下文获得合约生命周期事件的通知; 2、实现 | |||
| * AssetContract 接口定义的合约方法; | |||
| * | |||
| * @author huanghaiquan | |||
| * | |||
| */ | |||
| public class AssetContractImpl implements EventProcessingAwire, AssetContract { | |||
| // 资产管理账户的地址; | |||
| private static final String ASSET_ADDRESS = "2njZBNbFQcmKd385DxVejwSjy4driRzf9Pk"; | |||
| // 保存资产总数的键; | |||
| private static final String KEY_TOTAL = "TOTAL"; | |||
| // 合约事件上下文; | |||
| private ContractEventContext eventContext; | |||
| /** | |||
| * ------------------- 定义可以由外部用户通过提交“交易”触发的调用方法 ------------------ | |||
| */ | |||
| @Override | |||
| public void issue(long amount, String assetHolderAddress) { | |||
| checkAllOwnersAgreementPermission(); | |||
| // 新发行的资产数量; | |||
| if (amount < 0) { | |||
| throw new ContractError("The amount is negative!"); | |||
| } | |||
| if (amount == 0) { | |||
| return; | |||
| } | |||
| // 校验持有者账户的有效性; | |||
| BlockchainAccount holderAccount = eventContext.getLedger().getAccount(currentLedgerHash(), assetHolderAddress); | |||
| if (holderAccount == null) { | |||
| throw new ContractError("The holder is not exist!"); | |||
| } | |||
| // 查询当前值; | |||
| Set<String> keys = new HashSet<>(); | |||
| keys.add(KEY_TOTAL); | |||
| keys.add(assetHolderAddress); | |||
| StateMap currStates = eventContext.getLedger().getStates(currentLedgerHash(), ASSET_ADDRESS, keys); | |||
| // 计算资产的发行总数; | |||
| StateEntry currTotal = currStates.get(KEY_TOTAL); | |||
| StateEntry newTotal = currTotal.newLong(currTotal.longValue() + amount); | |||
| // 分配到持有者账户; | |||
| StateEntry holderAmount = currStates.get(assetHolderAddress); | |||
| StateEntry newHodlerAmount = holderAmount.newLong(holderAmount.longValue() + amount); | |||
| // 把数据的更改写入到账本; | |||
| SimpleStateMap newStates = new SimpleStateMap(currStates.getAccount(), currStates.getAccountVersion(), | |||
| currStates.getStateVersion()); | |||
| newStates.setValue(newTotal); | |||
| newStates.setValue(newHodlerAmount); | |||
| eventContext.getLedger().updateState(ASSET_ADDRESS).setStates(currStates); | |||
| } | |||
| @Override | |||
| public void transfer(String fromAddress, String toAddress, long amount) { | |||
| if (amount < 0) { | |||
| throw new ContractError("The amount is negative!"); | |||
| } | |||
| if (amount == 0) { | |||
| return; | |||
| } | |||
| //校验“转出账户”是否已签名; | |||
| checkSignerPermission(fromAddress); | |||
| // 查询现有的余额; | |||
| Set<String> keys = new HashSet<>(); | |||
| keys.add(fromAddress); | |||
| keys.add(toAddress); | |||
| StateMap origBalances = eventContext.getLedger().getStates(currentLedgerHash(), ASSET_ADDRESS, keys); | |||
| StateEntry fromBalance = origBalances.get(fromAddress); | |||
| StateEntry toBalance = origBalances.get(toAddress); | |||
| //检查是否余额不足; | |||
| if ((fromBalance.longValue() - amount) < 0) { | |||
| throw new ContractError("Insufficient balance!"); | |||
| } | |||
| // 把数据的更改写入到账本; | |||
| SimpleStateMap newBalances = new SimpleStateMap(origBalances.getAccount(), origBalances.getAccountVersion(), | |||
| origBalances.getStateVersion()); | |||
| StateEntry newFromBalance = fromBalance.newLong(fromBalance.longValue() - amount); | |||
| StateEntry newToBalance = toBalance.newLong(toBalance.longValue() + amount); | |||
| newBalances.setValue(newFromBalance); | |||
| newBalances.setValue(newToBalance); | |||
| eventContext.getLedger().updateState(ASSET_ADDRESS).setStates(newBalances); | |||
| } | |||
| } | |||
| @@ -8,4 +8,12 @@ | |||
| <version>0.9.0-SNAPSHOT</version> | |||
| </parent> | |||
| <artifactId>base</artifactId> | |||
| <dependencies> | |||
| <dependency> | |||
| <groupId>org.slf4j</groupId> | |||
| <artifactId>slf4j-api</artifactId> | |||
| </dependency> | |||
| </dependencies> | |||
| </project> | |||
| @@ -1,4 +1,4 @@ | |||
| package com.jd.blockchain.base.data; | |||
| package com.jd.blockchain.consts; | |||
| /** | |||
| * @author huanghaiquan | |||
| @@ -83,7 +83,7 @@ public interface TypeCodes { | |||
| public static final int ENUM_TYPE = 0xB20; | |||
| public static final int ENUM_TYPE_CRYPTO_ALGORITHM = 0xB21; | |||
| public static final int CRYPTO_ALGORITHM = 0xB21; | |||
| public static final int ENUM_TYPE_TRANSACTION_STATE = 0xB22; | |||
| @@ -0,0 +1,20 @@ | |||
| package com.jd.blockchain.provider; | |||
| import java.lang.annotation.ElementType; | |||
| import java.lang.annotation.Retention; | |||
| import java.lang.annotation.RetentionPolicy; | |||
| import java.lang.annotation.Target; | |||
| /** | |||
| * Mark a class as a named service provider; | |||
| * | |||
| * @author huanghaiquan | |||
| * | |||
| */ | |||
| @Target({ ElementType.TYPE }) | |||
| @Retention(RetentionPolicy.RUNTIME) | |||
| public @interface NamedProvider { | |||
| String value() default ""; | |||
| } | |||
| @@ -0,0 +1,11 @@ | |||
| package com.jd.blockchain.provider; | |||
| public interface Provider<S> { | |||
| String getShortName(); | |||
| String getFullName(); | |||
| S getService(); | |||
| } | |||
| @@ -0,0 +1,11 @@ | |||
| package com.jd.blockchain.provider; | |||
| public class ProviderException extends RuntimeException { | |||
| private static final long serialVersionUID = 6422628637835262811L; | |||
| public ProviderException(String message) { | |||
| super(message); | |||
| } | |||
| } | |||
| @@ -0,0 +1,247 @@ | |||
| package com.jd.blockchain.provider; | |||
| import java.security.AccessControlContext; | |||
| import java.security.AccessController; | |||
| import java.security.PrivilegedAction; | |||
| import java.util.Collection; | |||
| import java.util.LinkedHashMap; | |||
| import java.util.Map; | |||
| import java.util.ServiceLoader; | |||
| import java.util.concurrent.ConcurrentHashMap; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| /** | |||
| * The ProviderManager manages all serivce providers in the system. | |||
| * <p> | |||
| * | |||
| * The service is represented by an interface, and the provider is | |||
| * implementation class of the service. | |||
| * <p> | |||
| * | |||
| * One service can have multiple providers in the system. | |||
| * <p> | |||
| * | |||
| * A provider must have a name, and implementor can use the annotation | |||
| * {@link NamedProvider} to specify a short name, otherwise the system defaults | |||
| * to the full name of the implementation class. | |||
| * | |||
| * | |||
| * @author huanghaiquan | |||
| * | |||
| */ | |||
| public final class ProviderManager { | |||
| private final Logger LOGGER = LoggerFactory.getLogger(ProviderManager.class); | |||
| private final Object mutex = new Object(); | |||
| private ConcurrentHashMap<Class<?>, NamedProviders<?>> serviceProviders = new ConcurrentHashMap<>(); | |||
| /** | |||
| * 返回指定提供者的服务; | |||
| * | |||
| * @param serviceClazz | |||
| * @param providerName | |||
| * @return | |||
| */ | |||
| public <S> S getService(Class<S> serviceClazz, String providerName) { | |||
| NamedProviders<S> providers = getServiceProvider(serviceClazz); | |||
| return providers.getService(providerName); | |||
| } | |||
| public <S> Collection<Provider<S>> getAllProviders(Class<S> serviceClazz) { | |||
| NamedProviders<S> providers = getServiceProvider(serviceClazz); | |||
| return providers.getProviders(); | |||
| } | |||
| public <S> S installProvider(Class<S> serviceClazz, String providerFullName) { | |||
| NamedProviders<S> providers = getServiceProvider(serviceClazz); | |||
| return providers.install(providerFullName); | |||
| } | |||
| public <S> S installProvider(Class<S> service, String providerFullName, ClassLoader classLoader) { | |||
| NamedProviders<S> providers = getServiceProvider(service); | |||
| return providers.install(providerFullName, classLoader); | |||
| } | |||
| public <S> void installAllProviders(Class<S> serviceClazz, ClassLoader classLoader) { | |||
| NamedProviders<S> providers = getServiceProvider(serviceClazz); | |||
| providers.installAll(classLoader); | |||
| } | |||
| @SuppressWarnings("unchecked") | |||
| private <S> NamedProviders<S> getServiceProvider(Class<S> serviceClazz) { | |||
| NamedProviders<S> providers = (NamedProviders<S>) serviceProviders.get(serviceClazz); | |||
| if (providers == null) { | |||
| synchronized (mutex) { | |||
| providers = (NamedProviders<S>) serviceProviders.get(serviceClazz); | |||
| if (providers == null) { | |||
| providers = new NamedProviders<S>(serviceClazz); | |||
| serviceProviders.put(serviceClazz, providers); | |||
| } | |||
| } | |||
| } | |||
| return providers; | |||
| } | |||
| /** | |||
| * @author huanghaiquan | |||
| * | |||
| * @param <T> | |||
| * Type of Service | |||
| */ | |||
| private class NamedProviders<S> { | |||
| private Class<S> serviceClazz; | |||
| private Map<String, Provider<S>> namedProviders = new LinkedHashMap<>(); | |||
| private AccessControlContext acc; | |||
| public NamedProviders(Class<S> serviceClazz) { | |||
| this.serviceClazz = serviceClazz; | |||
| this.acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null; | |||
| installAll(); | |||
| } | |||
| public void installAll(ClassLoader classLoader) { | |||
| ServiceLoader<S> sl = ServiceLoader.load(serviceClazz, classLoader); | |||
| installAll(sl); | |||
| } | |||
| public void installAll() { | |||
| // 默认采用线程上下文的类加载器;避免直接采用系统的类加载器: ClassLoader.getSystemClassLoader() ; | |||
| ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); | |||
| installAll(classLoader); | |||
| } | |||
| private synchronized void installAll(ServiceLoader<S> sl) { | |||
| for (S provider : sl) { | |||
| install(provider); | |||
| } | |||
| } | |||
| /** | |||
| * 安装指定的服务提供者;<br> | |||
| * | |||
| * 如果同名的服务提供者已经存在(包括ShortName和FullName任意之一存在),则返回 false;<br> | |||
| * | |||
| * 如果同名的服务提供者不存在,则返回 false; | |||
| * | |||
| * @param service | |||
| * 提供者的服务实现; | |||
| * @return | |||
| */ | |||
| private synchronized boolean install(S service) { | |||
| String fullName = service.getClass().getName(); | |||
| if (namedProviders.containsKey(fullName)) { | |||
| LOGGER.warn(String.format("The provider[%s] already exists.", fullName)); | |||
| return false; | |||
| } | |||
| String shortName = null; | |||
| NamedProvider annoNP = service.getClass().getAnnotation(NamedProvider.class); | |||
| if (annoNP != null && annoNP.value() != null) { | |||
| String n = annoNP.value().trim(); | |||
| if (n.length() > 0) { | |||
| shortName = n; | |||
| } | |||
| } | |||
| if (shortName != null && namedProviders.containsKey(shortName)) { | |||
| return false; | |||
| } | |||
| ProviderInfo<S> provider = new ProviderInfo<>(shortName, fullName, service); | |||
| if (shortName != null) { | |||
| namedProviders.put(shortName, provider); | |||
| } | |||
| namedProviders.put(fullName, provider); | |||
| return true; | |||
| } | |||
| public S install(String providerFullName) { | |||
| return install(providerFullName, null); | |||
| } | |||
| public S install(String providerFullName, ClassLoader classLoader) { | |||
| // 默认采用线程上下文的类加载器;避免直接采用系统的类加载器: ClassLoader.getSystemClassLoader() ; | |||
| ClassLoader cl = (classLoader == null) ? Thread.currentThread().getContextClassLoader() : classLoader; | |||
| S p = null; | |||
| if (acc == null) { | |||
| p = instantiate(providerFullName, cl); | |||
| } else { | |||
| PrivilegedAction<S> action = new PrivilegedAction<S>() { | |||
| public S run() { | |||
| return instantiate(providerFullName, cl); | |||
| } | |||
| }; | |||
| p = AccessController.doPrivileged(action, acc); | |||
| } | |||
| if (!install(p)) { | |||
| throw new ProviderException( | |||
| "[" + serviceClazz.getName() + "] Provider " + providerFullName + " already exist!"); | |||
| } | |||
| return p; | |||
| } | |||
| public Collection<Provider<S>> getProviders() { | |||
| return namedProviders.values(); | |||
| } | |||
| public S getService(String name) { | |||
| Provider<S> pd = namedProviders.get(name); | |||
| return pd == null ? null : pd.getService(); | |||
| } | |||
| private S instantiate(String className, ClassLoader classLoader) { | |||
| Class<?> c = null; | |||
| try { | |||
| c = Class.forName(className, false, classLoader); | |||
| } catch (ClassNotFoundException x) { | |||
| throw new ProviderException("[" + serviceClazz.getName() + "] Provider " + className + " not found"); | |||
| } | |||
| if (!serviceClazz.isAssignableFrom(c)) { | |||
| throw new ProviderException( | |||
| "[" + serviceClazz.getName() + "] Provider " + className + " not a subtype"); | |||
| } | |||
| try { | |||
| S provider = serviceClazz.cast(c.newInstance()); | |||
| return provider; | |||
| } catch (Throwable e) { | |||
| throw new ProviderException("[" + serviceClazz.getName() + "] Provider " + className | |||
| + " could not be instantiated! --" + e.getMessage()); | |||
| } | |||
| } | |||
| } | |||
| private static class ProviderInfo<S> implements Provider<S> { | |||
| private final String shortName; | |||
| private final String fullName; | |||
| private final S service; | |||
| public ProviderInfo(String shortName, String fullName, S service) { | |||
| this.shortName = shortName; | |||
| this.fullName = fullName; | |||
| this.service = service; | |||
| } | |||
| @Override | |||
| public String getShortName() { | |||
| return shortName; | |||
| } | |||
| @Override | |||
| public String getFullName() { | |||
| return fullName; | |||
| } | |||
| @Override | |||
| public S getService() { | |||
| return service; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,6 +1,6 @@ | |||
| package com.jd.blockchain.consensus.bftsmart; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| public class BftsmartClientIncomingConfig implements BftsmartClientIncomingSettings { | |||
| @@ -1,10 +1,10 @@ | |||
| package com.jd.blockchain.consensus.bftsmart; | |||
| import com.jd.blockchain.base.data.TypeCodes; | |||
| import com.jd.blockchain.binaryproto.DataContract; | |||
| import com.jd.blockchain.binaryproto.DataField; | |||
| import com.jd.blockchain.consensus.ClientIncomingSettings; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.consts.TypeCodes; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.utils.ValueType; | |||
| @DataContract(code = TypeCodes.CONSENSUS_BFTSMART_CLI_INCOMING_SETTINGS) | |||
| @@ -1,8 +1,8 @@ | |||
| package com.jd.blockchain.consensus.bftsmart; | |||
| import com.jd.blockchain.base.data.TypeCodes; | |||
| import com.jd.blockchain.binaryproto.DataContract; | |||
| import com.jd.blockchain.binaryproto.DataField; | |||
| import com.jd.blockchain.consts.TypeCodes; | |||
| import com.jd.blockchain.utils.ValueType; | |||
| @@ -1,9 +1,9 @@ | |||
| package com.jd.blockchain.consensus.bftsmart; | |||
| import com.jd.blockchain.base.data.TypeCodes; | |||
| import com.jd.blockchain.binaryproto.DataContract; | |||
| import com.jd.blockchain.binaryproto.DataField; | |||
| import com.jd.blockchain.consensus.ConsensusSettings; | |||
| import com.jd.blockchain.consts.TypeCodes; | |||
| import com.jd.blockchain.utils.Property; | |||
| import com.jd.blockchain.utils.ValueType; | |||
| import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils; | |||
| @@ -14,7 +14,7 @@ import org.springframework.core.io.ClassPathResource; | |||
| import com.jd.blockchain.consensus.ConsensusSettings; | |||
| import com.jd.blockchain.consensus.ConsensusSettingsBuilder; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| public class BftsmartConsensusSettingsBuilder implements ConsensusSettingsBuilder { | |||
| @@ -2,7 +2,7 @@ package com.jd.blockchain.consensus.bftsmart; | |||
| import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
| import com.jd.blockchain.crypto.AddressEncoding; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.utils.net.NetworkAddress; | |||
| public class BftsmartNodeConfig implements BftsmartNodeSettings { | |||
| @@ -1,10 +1,10 @@ | |||
| package com.jd.blockchain.consensus.bftsmart; | |||
| import com.jd.blockchain.base.data.TypeCodes; | |||
| import com.jd.blockchain.binaryproto.DataContract; | |||
| import com.jd.blockchain.binaryproto.DataField; | |||
| import com.jd.blockchain.consensus.NodeSettings; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.consts.TypeCodes; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.utils.ValueType; | |||
| import com.jd.blockchain.utils.net.NetworkAddress; | |||
| @@ -2,7 +2,7 @@ package com.jd.blockchain.consensus.bftsmart.client; | |||
| import com.jd.blockchain.consensus.ConsensusSettings; | |||
| import com.jd.blockchain.consensus.bftsmart.BftsmartClientIncomingSettings; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| public class BftsmartClientConfig implements BftsmartClientSettings { | |||
| @@ -2,12 +2,8 @@ package com.jd.blockchain.consensus.bftsmart.client; | |||
| import com.jd.blockchain.consensus.ClientIdentification; | |||
| import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider; | |||
| import com.jd.blockchain.crypto.CryptoUtils; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.crypto.asymmetric.SignatureDigest; | |||
| import com.jd.blockchain.crypto.asymmetric.SignatureFunction; | |||
| import java.util.Arrays; | |||
| public class BftsmartClientIdentification implements ClientIdentification { | |||
| @@ -12,6 +12,8 @@ import com.jd.blockchain.consensus.client.ClientFactory; | |||
| import com.jd.blockchain.consensus.client.ClientSettings; | |||
| import com.jd.blockchain.consensus.client.ConsensusClient; | |||
| import com.jd.blockchain.crypto.CryptoUtils; | |||
| import com.jd.blockchain.crypto.PrivKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.crypto.asymmetric.*; | |||
| import com.jd.blockchain.utils.http.agent.HttpServiceAgent; | |||
| import com.jd.blockchain.utils.http.agent.ServiceEndpoint; | |||
| @@ -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(message); | |||
| //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); | |||
| asyncFuture.complete(result); | |||
| } catch (Exception e) { | |||
| @@ -1,15 +1,27 @@ | |||
| package com.jd.blockchain.consensus.bftsmart.service; | |||
| import java.io.ByteArrayInputStream; | |||
| import java.io.ByteArrayOutputStream; | |||
| import java.util.*; | |||
| import java.util.concurrent.ConcurrentHashMap; | |||
| import java.util.concurrent.CopyOnWriteArrayList; | |||
| import java.util.concurrent.ExecutorService; | |||
| import java.util.concurrent.Executors; | |||
| import java.util.concurrent.ScheduledExecutorService; | |||
| import java.util.concurrent.ScheduledThreadPoolExecutor; | |||
| import java.util.concurrent.TimeUnit; | |||
| import java.util.concurrent.atomic.AtomicInteger; | |||
| import java.util.concurrent.atomic.AtomicLong; | |||
| import bftsmart.tom.*; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import com.jd.blockchain.binaryproto.BinaryEncodingUtils; | |||
| import com.jd.blockchain.consensus.ConsensusManageService; | |||
| import com.jd.blockchain.consensus.NodeSettings; | |||
| import com.jd.blockchain.consensus.bftsmart.BftsmartCommitBlockSettings; | |||
| import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider; | |||
| import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusSettings; | |||
| import com.jd.blockchain.consensus.bftsmart.BftsmartNodeSettings; | |||
| @@ -19,12 +31,28 @@ import com.jd.blockchain.consensus.service.NodeServer; | |||
| import com.jd.blockchain.consensus.service.ServerSettings; | |||
| import com.jd.blockchain.consensus.service.StateHandle; | |||
| import com.jd.blockchain.consensus.service.StateMachineReplicate; | |||
| import com.jd.blockchain.crypto.CryptoAlgorithm; | |||
| import com.jd.blockchain.crypto.CryptoUtils; | |||
| import com.jd.blockchain.crypto.hash.HashDigest; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeyPair; | |||
| import com.jd.blockchain.ledger.TransactionContent; | |||
| import com.jd.blockchain.ledger.TransactionRequest; | |||
| import com.jd.blockchain.ledger.TransactionRespHandle; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionState; | |||
| import com.jd.blockchain.ledger.data.TxContentBlob; | |||
| import com.jd.blockchain.ledger.data.TxRequestMessage; | |||
| import com.jd.blockchain.utils.PropertiesUtils; | |||
| import com.jd.blockchain.utils.codec.Base58Utils; | |||
| import com.jd.blockchain.utils.concurrent.AsyncFuture; | |||
| import com.jd.blockchain.utils.concurrent.CompletableAsyncFuture; | |||
| import com.jd.blockchain.utils.io.BytesUtils; | |||
| import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils; | |||
| import bftsmart.reconfiguration.util.HostsConfig; | |||
| import bftsmart.reconfiguration.util.TOMConfiguration; | |||
| import bftsmart.reconfiguration.views.MemoryBasedViewStorage; | |||
| import bftsmart.tom.core.messages.TOMMessage; | |||
| import bftsmart.tom.server.defaultservices.DefaultRecoverable; | |||
| @@ -34,9 +62,15 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer | |||
| private List<StateHandle> stateHandles = new CopyOnWriteArrayList<>(); | |||
| // private List<BatchConsensusListener> batchConsensusListeners = new LinkedList<>(); | |||
| // private Map<ReplyContextMessage, AsyncFuture<byte[]>> replyContextMessages = new ConcurrentHashMap<>(); | |||
| // TODO 暂不处理队列溢出问题 | |||
| private ExecutorService notifyReplyExecutors = Executors.newSingleThreadExecutor(); | |||
| // private ExecutorService sendCommitExecutors = Executors.newFixedThreadPool(2); | |||
| private volatile Status status = Status.STOPPED; | |||
| private final Object mutex = new Object(); | |||
| @@ -67,6 +101,28 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer | |||
| private int serverId; | |||
| // private volatile String batchId = null; | |||
| // | |||
| //// private List<AsyncFuture<byte[]>> replyMessages ; | |||
| // | |||
| // private boolean leader_has_makedicision = false; | |||
| // | |||
| // private boolean commit_block_condition = false; | |||
| // | |||
| // private final AtomicLong txIndex = new AtomicLong(); | |||
| // | |||
| // private final AtomicLong blockIndex = new AtomicLong(); | |||
| // | |||
| // private static final AtomicInteger incrementNum = new AtomicInteger(); | |||
| // | |||
| //// private final BlockingQueue<ActionRequest> txRequestQueue = new LinkedBlockingQueue(); | |||
| // | |||
| // private final ExecutorService queueExecutor = Executors.newSingleThreadExecutor(); | |||
| // | |||
| // private final ScheduledExecutorService timerEexecutorService = new ScheduledThreadPoolExecutor(10); | |||
| // private ServiceProxy peerProxy; | |||
| public BftsmartNodeServer() { | |||
| } | |||
| @@ -83,6 +139,22 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer | |||
| initConfig(serverId, systemConfig, hostsConfig); | |||
| } | |||
| //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; | |||
| @@ -190,12 +262,214 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer | |||
| return appExecuteBatch(commands, msgCtxs, fromConsensus, null); | |||
| } | |||
| // private boolean checkLeaderId(MessageContext[] msgCtxs) { | |||
| // boolean result = false; | |||
| // | |||
| // for (int i = 0; i < msgCtxs.length - 1; i++) { | |||
| // if (msgCtxs[i].getLeader() != msgCtxs[i+1].getLeader()) | |||
| // return result; | |||
| // } | |||
| // | |||
| // result = true; | |||
| // | |||
| // return result; | |||
| // } | |||
| // | |||
| // //普通消息处理 | |||
| // private void normalMsgProcess(ReplyContextMessage replyContextMsg, byte[] msg, String realmName, String batchId) { | |||
| // AsyncFuture<byte[]> replyMsg = messageHandle.processOrdered(replyContextMsg.getMessageContext().getOperationId(), msg, realmName, batchId); | |||
| // replyContextMessages.put(replyContextMsg, replyMsg); | |||
| // } | |||
| // | |||
| // //结块消息处理 | |||
| // private void commitMsgProcess(ReplyContextMessage replyContextMsg, String realmName, String batchId) { | |||
| // try{ | |||
| // //receive messages before commitblock message, then execute commit | |||
| // if (replyContextMessages.size() != 0) { | |||
| // messageHandle.completeBatch(realmName, batchId); | |||
| // messageHandle.commitBatch(realmName, batchId); | |||
| // } | |||
| // | |||
| // // commit block msg need response too | |||
| // CompletableAsyncFuture<byte[]> asyncFuture = new CompletableAsyncFuture<>(); | |||
| // TransactionResponse transactionRespHandle = new TransactionRespHandle(newBlockCommitRequest(), | |||
| // TransactionState.SUCCESS, TransactionState.SUCCESS); | |||
| // | |||
| // asyncFuture.complete(BinaryEncodingUtils.encode(transactionRespHandle, TransactionResponse.class)); | |||
| // replyContextMessages.put(replyContextMsg, asyncFuture); | |||
| // }catch (Exception e){ | |||
| // LOGGER.error("Error occurred on commit batch transactions, so the new block is canceled! --" + e.getMessage(), e); | |||
| // messageHandle.rollbackBatch(realmName, batchId, -1); | |||
| // }finally{ | |||
| // this.batchId = null; | |||
| // } | |||
| // } | |||
| // private void sendCommitMessage() { | |||
| // | |||
| // HashDigest ledgerHash = new HashDigest(Base58Utils.decode(realmName)); | |||
| // | |||
| // BlockchainKeyPair userKeyPeer = BlockchainKeyGenerator.getInstance().generate(); | |||
| // | |||
| // TxContentBlob txContentBlob = new TxContentBlob(ledgerHash); | |||
| // | |||
| // byte[] reqBytes = BinaryEncodingUtils.encode(txContentBlob, TransactionContent.class); | |||
| // | |||
| // HashDigest reqHash = CryptoUtils.hash(CryptoAlgorithm.SHA256).hash(reqBytes); | |||
| // | |||
| // txContentBlob.setHash(reqHash); | |||
| // | |||
| // TxRequestMessage transactionRequest = new TxRequestMessage(txContentBlob); | |||
| // | |||
| // byte[] msg = BinaryEncodingUtils.encode(transactionRequest, TransactionRequest.class); | |||
| // | |||
| // byte[] type = BytesUtils.toBytes(1); | |||
| // | |||
| // byte[] wrapMsg = new byte[msg.length + 4]; | |||
| // | |||
| // System.arraycopy(type, 0, wrapMsg, 0, 4); | |||
| // System.arraycopy(msg, 0, wrapMsg, 4, msg.length); | |||
| // | |||
| // peerProxy.invokeOrdered(wrapMsg); | |||
| // | |||
| // LOGGER.info("Send commit block msg success!"); | |||
| // } | |||
| // private TransactionRequest newBlockCommitRequest() { | |||
| // | |||
| // HashDigest ledgerHash = new HashDigest(Base58Utils.decode(realmName)); | |||
| // | |||
| // TxContentBlob txContentBlob = new TxContentBlob(ledgerHash); | |||
| // | |||
| // byte[] reqBytes = BinaryEncodingUtils.encode(txContentBlob, TransactionContent.class); | |||
| // | |||
| // HashDigest reqHash = CryptoUtils.hash(CryptoAlgorithm.SHA256).hash(reqBytes); | |||
| // | |||
| // txContentBlob.setHash(reqHash); | |||
| // | |||
| // TxRequestMessage transactionRequest = new TxRequestMessage(txContentBlob); | |||
| // | |||
| // return transactionRequest; | |||
| // } | |||
| // private void checkConsensusFinish() { | |||
| // BftsmartCommitBlockSettings commitBlockSettings = ((BftsmartServerSettings)serverSettings).getConsensusSettings().getCommitBlockSettings(); | |||
| // int txSize = commitBlockSettings.getTxSizePerBlock(); | |||
| // long maxDelay = commitBlockSettings.getMaxDelayMilliSecondsPerBlock(); | |||
| // | |||
| // long currIndex = txIndex.incrementAndGet(); | |||
| // if (currIndex == txSize) { | |||
| // txIndex.set(0); | |||
| // this.blockIndex.getAndIncrement(); | |||
| // sendCommitExecutors.execute(()-> { | |||
| // sendCommitMessage(); | |||
| // }); | |||
| // } else if (currIndex == 1) { | |||
| //// System.out.printf("checkConsensusFinish schedule blockIndex = %s \r\n", this.blockIndex.get()); | |||
| // timerEexecutorService.schedule(timeTask(this.blockIndex.get()), maxDelay, TimeUnit.MILLISECONDS); | |||
| // } | |||
| // | |||
| // return; | |||
| // } | |||
| // @Override | |||
| // public byte[][] appExecuteBatch(byte[][] commands, MessageContext[] msgCtxs, boolean fromConsensus, List<ReplyContextMessage> replyList) { | |||
| // | |||
| // if (!checkLeaderId(msgCtxs)) { | |||
| // throw new IllegalArgumentException(); | |||
| // } | |||
| // | |||
| // boolean isLeader = (msgCtxs[0].getLeader() == getId()); | |||
| // | |||
| // if (isLeader) { | |||
| // for (int i = 0; i < commands.length; i++) { | |||
| // byte[] wrapMsg = commands[i]; | |||
| // byte[] type = new byte[4]; | |||
| // byte[] msg= new byte[wrapMsg.length - 4]; | |||
| // | |||
| // System.arraycopy(wrapMsg, 0, type, 0, 4); | |||
| // System.arraycopy(wrapMsg, 4, msg, 0, wrapMsg.length - 4); | |||
| // | |||
| // MessageContext messageContext = msgCtxs[i]; | |||
| // ReplyContextMessage replyContextMessage = replyList.get(i); | |||
| // replyContextMessage.setMessageContext(messageContext); | |||
| // | |||
| // if (batchId == null) { | |||
| // batchId = messageHandle.beginBatch(realmName); | |||
| // } | |||
| // | |||
| // int msgType = BytesUtils.readInt(new ByteArrayInputStream(type)); | |||
| // | |||
| // if (msgType == 0) { | |||
| // | |||
| // //only leader do it | |||
| // checkConsensusFinish(); | |||
| // //normal message process | |||
| // normalMsgProcess(replyContextMessage, msg, realmName, batchId); | |||
| // } | |||
| // if (!leader_has_makedicision) { | |||
| // if (msgType == 1) { | |||
| // LOGGER.error("Error occurred on appExecuteBatch msg process, leader confilicting error!"); | |||
| // } | |||
| // | |||
| // if (commit_block_condition) { | |||
| // leader_has_makedicision = true; | |||
| // | |||
| //// sendCommitExecutors.execute(() -> { | |||
| // commit_block_condition = false; | |||
| // LOGGER.info("Txcount execute commit block!"); | |||
| // sendCommitMessage(); | |||
| //// }); | |||
| // | |||
| // } | |||
| // } else if (msgType == 1) { | |||
| // //commit block message | |||
| // commitMsgProcess(replyContextMessage, realmName, batchId); | |||
| // leader_has_makedicision = false; | |||
| // sendReplyMessage(); | |||
| // } | |||
| // } | |||
| // } else { | |||
| // for (int i = 0; i < commands.length; i++) { | |||
| // byte[] wrapMsg = commands[i]; | |||
| // byte[] type = new byte[4]; | |||
| // byte[] msg= new byte[wrapMsg.length - 4]; | |||
| // | |||
| // System.arraycopy(wrapMsg, 0, type, 0, 4); | |||
| // System.arraycopy(wrapMsg, 4, msg, 0, wrapMsg.length - 4); | |||
| // | |||
| // MessageContext messageContext = msgCtxs[i]; | |||
| // ReplyContextMessage replyContextMessage = replyList.get(i); | |||
| // replyContextMessage.setMessageContext(messageContext); | |||
| // | |||
| // if (batchId == null) { | |||
| // batchId = messageHandle.beginBatch(realmName); | |||
| // } | |||
| // | |||
| // int msgType = BytesUtils.readInt(new ByteArrayInputStream(type)); | |||
| // | |||
| // if (msgType == 0) { | |||
| // //normal message | |||
| // normalMsgProcess(replyContextMessage, msg, realmName, batchId); | |||
| // } else if (msgType == 1) { | |||
| // // commit block message | |||
| // commitMsgProcess(replyContextMessage, realmName, batchId); | |||
| // sendReplyMessage(); | |||
| // } | |||
| // } | |||
| // } | |||
| // | |||
| // return null; | |||
| // } | |||
| @Override | |||
| public byte[][] appExecuteBatch(byte[][] commands, MessageContext[] msgCtxs, boolean fromConsensus, List<ReplyContextMessage> replyList) { | |||
| if (replyList == null || replyList.size() == 0) { | |||
| throw new IllegalArgumentException(); | |||
| } | |||
| // todo 此部分需要重新改造 | |||
| /** | |||
| * 默认BFTSmart接口提供的commands是一个或多个共识结果的顺序集合 | |||
| @@ -227,6 +501,52 @@ 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; | |||
| } | |||
| @@ -274,6 +594,46 @@ 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() + "]"); | |||
| @@ -283,6 +643,9 @@ 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(); | |||
| } | |||
| @@ -349,7 +712,34 @@ 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, | |||
| @@ -8,7 +8,7 @@ import com.jd.blockchain.consensus.bftsmart.client.BftsmartMessageService; | |||
| import com.jd.blockchain.consensus.bftsmart.service.BftsmartNodeServer; | |||
| import com.jd.blockchain.consensus.bftsmart.service.BftsmartServerSettingConfig; | |||
| import com.jd.blockchain.consensus.service.ServerSettings; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeyPair; | |||
| import com.jd.blockchain.utils.PropertiesUtils; | |||
| @@ -1,9 +1,9 @@ | |||
| package com.jd.blockchain.consensus; | |||
| import com.jd.blockchain.base.data.TypeCodes; | |||
| import com.jd.blockchain.binaryproto.DataContract; | |||
| import com.jd.blockchain.binaryproto.DataField; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.consts.TypeCodes; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.crypto.asymmetric.SignatureDigest; | |||
| import com.jd.blockchain.utils.ValueType; | |||
| @@ -8,9 +8,9 @@ | |||
| */ | |||
| package com.jd.blockchain.consensus; | |||
| import com.jd.blockchain.base.data.TypeCodes; | |||
| import com.jd.blockchain.binaryproto.DataContract; | |||
| import com.jd.blockchain.binaryproto.DataField; | |||
| import com.jd.blockchain.consts.TypeCodes; | |||
| /** | |||
| * | |||
| @@ -1,8 +1,8 @@ | |||
| package com.jd.blockchain.consensus; | |||
| import com.jd.blockchain.base.data.TypeCodes; | |||
| import com.jd.blockchain.binaryproto.DataContract; | |||
| import com.jd.blockchain.binaryproto.DataField; | |||
| import com.jd.blockchain.consts.TypeCodes; | |||
| import com.jd.blockchain.utils.ValueType; | |||
| /** | |||
| @@ -1,8 +1,8 @@ | |||
| package com.jd.blockchain.consensus; | |||
| import com.jd.blockchain.base.data.TypeCodes; | |||
| import com.jd.blockchain.binaryproto.DataContract; | |||
| import com.jd.blockchain.binaryproto.DataField; | |||
| import com.jd.blockchain.consts.TypeCodes; | |||
| /** | |||
| * 共识网络的配置参数; | |||
| @@ -1,9 +1,9 @@ | |||
| package com.jd.blockchain.consensus; | |||
| import com.jd.blockchain.base.data.TypeCodes; | |||
| import com.jd.blockchain.binaryproto.DataContract; | |||
| import com.jd.blockchain.binaryproto.DataField; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.consts.TypeCodes; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.utils.ValueType; | |||
| /** | |||
| @@ -1,8 +1,8 @@ | |||
| package com.jd.blockchain.consensus.action; | |||
| import com.jd.blockchain.base.data.TypeCodes; | |||
| import com.jd.blockchain.binaryproto.DataContract; | |||
| import com.jd.blockchain.binaryproto.DataField; | |||
| import com.jd.blockchain.consts.TypeCodes; | |||
| import com.jd.blockchain.utils.ValueType; | |||
| @DataContract(code= TypeCodes.CONSENSUS_ACTION_REQUEST) | |||
| @@ -1,8 +1,8 @@ | |||
| package com.jd.blockchain.consensus.action; | |||
| import com.jd.blockchain.base.data.TypeCodes; | |||
| import com.jd.blockchain.binaryproto.DataContract; | |||
| import com.jd.blockchain.binaryproto.DataField; | |||
| import com.jd.blockchain.consts.TypeCodes; | |||
| import com.jd.blockchain.utils.ValueType; | |||
| @DataContract(code= TypeCodes.CONSENSUS_ACTION_RESPONSE) | |||
| @@ -1,7 +1,7 @@ | |||
| package com.jd.blockchain.consensus.client; | |||
| import com.jd.blockchain.consensus.ConsensusSettings; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| /** | |||
| * 共识客户端的配置参数; | |||
| @@ -20,7 +20,7 @@ import com.jd.blockchain.consensus.mq.settings.MsgQueueConsensusSettings; | |||
| import com.jd.blockchain.consensus.mq.settings.MsgQueueNetworkSettings; | |||
| import com.jd.blockchain.consensus.mq.settings.MsgQueueNodeSettings; | |||
| import com.jd.blockchain.crypto.AddressEncoding; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.tools.keygen.KeyGenCommand; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| import com.jd.blockchain.utils.PropertiesUtils; | |||
| @@ -20,8 +20,8 @@ import com.jd.blockchain.consensus.mq.settings.MsgQueueClientIncomingSettings; | |||
| import com.jd.blockchain.consensus.mq.settings.MsgQueueClientSettings; | |||
| import com.jd.blockchain.consensus.mq.settings.MsgQueueConsensusSettings; | |||
| import com.jd.blockchain.crypto.CryptoUtils; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.crypto.asymmetric.CryptoKeyPair; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.crypto.asymmetric.SignatureDigest; | |||
| import com.jd.blockchain.crypto.asymmetric.SignatureFunction; | |||
| @@ -11,7 +11,7 @@ package com.jd.blockchain.consensus.mq.client; | |||
| import com.jd.blockchain.consensus.ClientIdentification; | |||
| import com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider; | |||
| import com.jd.blockchain.crypto.CryptoUtils; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.crypto.asymmetric.SignatureDigest; | |||
| import com.jd.blockchain.crypto.asymmetric.SignatureFunction; | |||
| @@ -11,7 +11,7 @@ package com.jd.blockchain.consensus.mq.config; | |||
| import com.jd.blockchain.consensus.mq.settings.MsgQueueClientSettings; | |||
| import com.jd.blockchain.consensus.mq.settings.MsgQueueConsensusSettings; | |||
| import com.jd.blockchain.consensus.mq.settings.MsgQueueNetworkSettings; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| /** | |||
| * | |||
| @@ -13,7 +13,7 @@ import com.jd.blockchain.consensus.ConsensusSettings; | |||
| import com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider; | |||
| import com.jd.blockchain.consensus.mq.settings.MsgQueueClientIncomingSettings; | |||
| import com.jd.blockchain.consensus.mq.settings.MsgQueueConsensusSettings; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import java.lang.reflect.Method; | |||
| @@ -11,7 +11,7 @@ package com.jd.blockchain.consensus.mq.config; | |||
| import com.jd.blockchain.consensus.ConsensusSettings; | |||
| import com.jd.blockchain.consensus.NodeSettings; | |||
| import com.jd.blockchain.consensus.mq.settings.*; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import java.lang.reflect.Method; | |||
| import java.lang.reflect.Proxy; | |||
| @@ -9,7 +9,7 @@ | |||
| package com.jd.blockchain.consensus.mq.config; | |||
| import com.jd.blockchain.consensus.mq.settings.MsgQueueNodeSettings; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| /** | |||
| * peer节点IP | |||
| @@ -17,7 +17,7 @@ import com.jd.blockchain.consensus.mq.config.MsgQueueConsensusConfig; | |||
| import com.jd.blockchain.consensus.mq.settings.MsgQueueClientIncomingSettings; | |||
| import com.jd.blockchain.consensus.mq.settings.MsgQueueConsensusSettings; | |||
| import com.jd.blockchain.crypto.CryptoUtils; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.crypto.asymmetric.SignatureFunction; | |||
| import java.lang.reflect.Proxy; | |||
| @@ -8,9 +8,9 @@ | |||
| */ | |||
| package com.jd.blockchain.consensus.mq.settings; | |||
| import com.jd.blockchain.base.data.TypeCodes; | |||
| import com.jd.blockchain.binaryproto.DataContract; | |||
| import com.jd.blockchain.binaryproto.DataField; | |||
| import com.jd.blockchain.consts.TypeCodes; | |||
| import com.jd.blockchain.utils.ValueType; | |||
| /** | |||
| @@ -8,12 +8,12 @@ | |||
| */ | |||
| package com.jd.blockchain.consensus.mq.settings; | |||
| import com.jd.blockchain.base.data.TypeCodes; | |||
| import com.jd.blockchain.binaryproto.DataContract; | |||
| import com.jd.blockchain.binaryproto.DataField; | |||
| import com.jd.blockchain.consensus.ClientIncomingSettings; | |||
| import com.jd.blockchain.consensus.ConsensusSettings; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.consts.TypeCodes; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.utils.ValueType; | |||
| /** | |||
| @@ -8,11 +8,11 @@ | |||
| */ | |||
| package com.jd.blockchain.consensus.mq.settings; | |||
| import com.jd.blockchain.base.data.TypeCodes; | |||
| import com.jd.blockchain.binaryproto.DataContract; | |||
| import com.jd.blockchain.binaryproto.DataField; | |||
| import com.jd.blockchain.consensus.ConsensusSettings; | |||
| import com.jd.blockchain.consensus.mq.config.MsgQueueBlockConfig; | |||
| import com.jd.blockchain.consts.TypeCodes; | |||
| import com.jd.blockchain.utils.Property; | |||
| import com.jd.blockchain.utils.ValueType; | |||
| @@ -8,9 +8,9 @@ | |||
| */ | |||
| package com.jd.blockchain.consensus.mq.settings; | |||
| import com.jd.blockchain.base.data.TypeCodes; | |||
| import com.jd.blockchain.binaryproto.DataContract; | |||
| import com.jd.blockchain.binaryproto.DataField; | |||
| import com.jd.blockchain.consts.TypeCodes; | |||
| import com.jd.blockchain.utils.ValueType; | |||
| /** | |||
| @@ -8,9 +8,9 @@ | |||
| */ | |||
| package com.jd.blockchain.consensus.mq.settings; | |||
| import com.jd.blockchain.base.data.TypeCodes; | |||
| import com.jd.blockchain.binaryproto.DataContract; | |||
| import com.jd.blockchain.consensus.NodeSettings; | |||
| import com.jd.blockchain.consts.TypeCodes; | |||
| /** | |||
| * | |||
| @@ -5,7 +5,7 @@ | |||
| <parent> | |||
| <artifactId>contract</artifactId> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <version>0.8.3.RELEASE</version> | |||
| <version>0.8.2.RELEASE</version> | |||
| </parent> | |||
| <modelVersion>4.0.0</modelVersion> | |||
| @@ -100,15 +100,6 @@ | |||
| </execution> | |||
| </executions> | |||
| </plugin> | |||
| <plugin> | |||
| <groupId>org.apache.maven.plugins</groupId> | |||
| <artifactId>maven-deploy-plugin</artifactId> | |||
| <version>2.8.2</version> | |||
| <configuration> | |||
| <skip>true</skip> | |||
| </configuration> | |||
| </plugin> | |||
| </plugins> | |||
| </build> | |||
| </project> | |||
| @@ -2,7 +2,7 @@ package com.jd.blockchain.contract; | |||
| import com.jd.blockchain.contract.model.*; | |||
| import com.jd.blockchain.crypto.CryptoAlgorithm; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.crypto.hash.HashDigest; | |||
| import com.jd.blockchain.ledger.*; | |||
| import com.jd.blockchain.utils.BaseConstant; | |||
| @@ -14,23 +14,23 @@ import java.util.Map; | |||
| import java.util.Set; | |||
| /** | |||
| * mock the smart contract; | |||
| * 模拟用智能合约; | |||
| */ | |||
| @Contract | |||
| public class AssetContract1 implements EventProcessingAwire { | |||
| // private static final Logger LOGGER = LoggerFactory.getLogger(AssetContract1.class); | |||
| // the address of asset manager; | |||
| // 资产管理账户的地址; | |||
| // private static String ASSET_ADDRESS = "2njZBNbFQcmKd385DxVejwSjy4driRzf9Pk"; | |||
| private static String ASSET_ADDRESS = ""; | |||
| //account address; | |||
| //账户地址; | |||
| private static final String ACCOUNT_ADDRESS = "accountAddress"; | |||
| String contractAddress = "2njZBNbFQcmKd385DxVejwSjy4driRzf9Pk"; | |||
| String userPubKeyVal = "this is user's pubKey"; | |||
| // the key of save asset; | |||
| // 保存资产总数的键; | |||
| private static final String KEY_TOTAL = "TOTAL"; | |||
| // contractEvent context; | |||
| // 合约事件上下文; | |||
| private ContractEventContext eventContext; | |||
| private Object eventContextObj; | |||
| private byte[] eventContextBytes; | |||
| @@ -59,7 +59,7 @@ public class AssetContract1 implements EventProcessingAwire { | |||
| } | |||
| /** | |||
| * issue-asset; | |||
| * 发行资产; | |||
| * @param contractEventContext | |||
| * @throws Exception | |||
| */ | |||
| @@ -83,6 +83,7 @@ public class AssetContract1 implements EventProcessingAwire { | |||
| // checkAllOwnersAgreementPermission(); | |||
| // 新发行的资产数量;在传递过程中都改为字符串,需要反转; | |||
| // long amount = BytesUtils.toLong(args[0]); | |||
| if (amount < 0) { | |||
| @@ -92,77 +93,83 @@ public class AssetContract1 implements EventProcessingAwire { | |||
| return; | |||
| } | |||
| // 校验持有者账户的有效性; | |||
| // BlockchainAccount holderAccount = eventContext.getLedger().getAccount(currentLedgerHash(), assetHolderAddress); | |||
| // if (holderAccount == null) { | |||
| // throw new ContractError("The holder is not exist!"); | |||
| // } | |||
| // 查询当前值; | |||
| HashDigest hashDigest = eventContext.getCurrentLedgerHash(); | |||
| //赋值;mock的对象直接赋值无效; | |||
| // eventContext.getLedger().dataAccount(ACCOUNT_ADDRESS).set(KEY_TOTAL,"total new dataAccount".getBytes(),2); | |||
| // KVDataEntry[] kvEntries = eventContext.getLedger().getDataEntries(hashDigest, ASSET_ADDRESS, KEY_TOTAL,assetHolderAddress); | |||
| // assert ByteArray.toHex("total new dataAccount".getBytes()).equals(kvEntries[0].getValue()) | |||
| // && ByteArray.toHex("abc new dataAccount".getBytes()).equals(kvEntries[1].getValue()) : | |||
| // "getDataEntries() test,expect!=actual;"; | |||
| // "getDataEntries() test,期望值!=设定值;"; | |||
| KVDataEntry[] kvEntries = eventContext.getLedger().getDataEntries(hashDigest, ASSET_ADDRESS, | |||
| KEY_TOTAL,assetHolderAddress,"ledgerHash"); //,"latestBlockHash" | |||
| //当前mock设定值为:TOTAL="total value,dataAccount";abc="abc value,dataAccount"; | |||
| assert ByteArray.toHex("total value,dataAccount".getBytes()).equals(kvEntries[0].getValue()) | |||
| && ByteArray.toHex("abc value,dataAccount".getBytes()).equals(kvEntries[1].getValue()) : | |||
| "getDataEntries() test,expect=actual;"; | |||
| "getDataEntries() test,期望值=设定值;"; | |||
| //get the latest block; | |||
| //高度只是一个模拟,看结果是否与期望相同;//get the latest block; | |||
| LedgerBlock ledgerBlock = eventContext.getLedger().getBlock(hashDigest, | |||
| eventContext.getLedger().getLedger(hashDigest).getLatestBlockHeight()); | |||
| // assert "zhaogw".equals(new String(ledgerBlock.getLedgerHash().getRawDigest())) && | |||
| // "lisi".equals(new String(ledgerBlock.getPreviousHash().getRawDigest())) : | |||
| // "getBlock(hash,long) test,expect!=actual;"; | |||
| // "getBlock(hash,long) test,期望值!=设定值;"; | |||
| assert ByteArray.toHex(eventContext.getCurrentLedgerHash().getRawDigest()).equals(kvEntries[2].getValue()) && | |||
| ledgerBlock.getPreviousHash().toBase58().equals(previousBlockHash) : | |||
| "getPreviousHash() test,expect!=acutal;"; | |||
| "getPreviousHash() test,期望值!=设定值;"; | |||
| //模拟:根据hash来获得区块; | |||
| LedgerBlock ledgerBlock1 = eventContext.getLedger().getBlock(hashDigest,ledgerBlock.getHash()); | |||
| assert eventContext.getLedger().getTransactionCount(hashDigest,1) == 2 : | |||
| "getTransactionCount(),expect!=acutal"; | |||
| "getTransactionCount(),期望值!=设定值"; | |||
| // assert "zhaogw".equals(new String(ledgerBlock1.getLedgerHash().getRawDigest())) && | |||
| // "lisi".equals(new String(ledgerBlock1.getPreviousHash().getRawDigest())) : | |||
| // "getBlock(hash,blockHash) test,expect!=acutal;"; | |||
| // "getBlock(hash,blockHash) test,期望值!=设定值;"; | |||
| assert ByteArray.toHex(eventContext.getCurrentLedgerHash().getRawDigest()).equals(kvEntries[2].getValue()) && | |||
| ledgerBlock1.getPreviousHash().toBase58().equals(previousBlockHash) : | |||
| "getBlock(hash,blockHash) test,expect!=acutal;"; | |||
| "getBlock(hash,blockHash) test,期望值!=设定值;"; | |||
| assert ASSET_ADDRESS.equals(eventContext.getLedger().getDataAccount(hashDigest,ASSET_ADDRESS).getAddress()) : | |||
| "getDataAccount(hash,address), expect!=acutal"; | |||
| "getDataAccount(hash,address), 期望值!=设定值"; | |||
| //mock user()等;内部赋值,验证外部是否能够得到; | |||
| PubKey pubKey = new PubKey(CryptoAlgorithm.ED25519, pubKeyVal.getBytes()); | |||
| BlockchainIdentity contractID = new BlockchainIdentityData(pubKey); | |||
| // assert contractID == contractEventContext.getLedger().dataAccounts().register(contractID).getAccountID() : | |||
| // "dataAccounts(),expect!=acutal"; | |||
| // "dataAccounts(),期望值!=设定值"; | |||
| contractEventContext.getLedger().dataAccounts().register(contractID); | |||
| contractEventContext.getLedger().dataAccount(contractID.getAddress()). | |||
| set(KEY_TOTAL,"hello".getBytes(),-1).getOperation(); | |||
| assert userAddress.equals(eventContext.getLedger().getUser(hashDigest,userAddress).getAddress()) : | |||
| "getUser(hash,address), expect!=acutal"; | |||
| "getUser(hash,address), 期望值!=设定值"; | |||
| assert contractAddress.equals(eventContext.getLedger().getContract(hashDigest,contractAddress).getAddress()) : | |||
| "getContract(hash,address), expect!=acutal"; | |||
| "getContract(hash,address), 期望值!=设定值"; | |||
| PubKey userPubKey = new PubKey(CryptoAlgorithm.ED25519, userPubKeyVal.getBytes()); | |||
| BlockchainIdentity userBlockId = new BlockchainIdentityData(userPubKey); | |||
| contractEventContext.getLedger().users().register(userBlockId); | |||
| // txRootHash | |||
| //此方法未实现;需要相关人员进一步完善; | |||
| // eventContext.getLedger().getTransactions(hashDigest,ledgerBlock1.getHash(),0,10); | |||
| HashDigest txHashDigest = new HashDigest(Base58Utils.decode(txHash)); | |||
| LedgerTransaction ledgerTransactions = eventContext.getLedger().getTransactionByContentHash(hashDigest,txHashDigest); | |||
| assert ledgerTransactions != null : "getTransactionByContentHash(hashDigest,txHashDigest),expect!=acutal"; | |||
| assert ledgerTransactions != null : "getTransactionByContentHash(hashDigest,txHashDigest),期望值!=设定值"; | |||
| System.out.println("issue(),over."); | |||
| } | |||
| @@ -185,6 +192,9 @@ public class AssetContract1 implements EventProcessingAwire { | |||
| System.out.println("transfer(),over."); | |||
| } | |||
| /** | |||
| * 只有全部的合约拥有者同意才能通过校验; | |||
| */ | |||
| private void checkAllOwnersAgreementPermission() { | |||
| Set<BlockchainIdentity> owners = eventContext.getContracOwners(); | |||
| Set<BlockchainIdentity> requestors = eventContext.getTxSigners(); | |||
| @@ -204,6 +214,11 @@ public class AssetContract1 implements EventProcessingAwire { | |||
| } | |||
| } | |||
| /** | |||
| * 校验指定的账户是否签署了当前交易; | |||
| * | |||
| * @param address | |||
| */ | |||
| private void checkSignerPermission(String address) { | |||
| Set<BlockchainIdentity> requestors = eventContext.getTxSigners(); | |||
| for (BlockchainIdentity r : requestors) { | |||
| @@ -6,7 +6,7 @@ import com.jd.blockchain.ledger.KVDataEntry; | |||
| import com.jd.blockchain.utils.BaseConstant; | |||
| /** | |||
| * mock the smart contract; | |||
| * 模拟用智能合约; | |||
| */ | |||
| @Contract | |||
| public class AssetContract2 implements EventProcessingAwire { | |||
| @@ -31,11 +31,12 @@ public class AssetContract2 implements EventProcessingAwire { | |||
| HashDigest hashDigest = eventContext.getCurrentLedgerHash(); | |||
| KVDataEntry[] kvEntries = eventContext.getLedger().getDataEntries(hashDigest, contractDataAddress, | |||
| KEY_TOTAL,LEDGER_HASH); //,"latestBlockHash" | |||
| //当前mock设定值为:TOTAL="total value,dataAccount";abc="abc value,dataAccount"; | |||
| // | |||
| // assert ByteArray.toHex("total value,dataAccount".getBytes()).equals(kvEntries[0].getValue()) | |||
| // && ByteArray.toHex("abc value,dataAccount".getBytes()).equals(kvEntries[1].getValue()) : | |||
| // "getDataEntries() test,expect=actual;"; | |||
| // "getDataEntries() test,期望值=设定值;"; | |||
| System.out.println("in dataSet,KEY_TOTAL="+new String(kvEntries[0].getValue().toString())); | |||
| System.out.println("in dataSet,LEDGER_HASH="+new String(kvEntries[1].getValue().toString())); | |||
| } | |||
| @@ -4,8 +4,8 @@ import com.jd.blockchain.contract.model.*; | |||
| import com.jd.blockchain.utils.BaseConstant; | |||
| /** | |||
| * mock the smart contract; | |||
| * Do only the simplest addition operation. | |||
| * 模拟用智能合约; | |||
| * 只做最简单的加法运算; | |||
| */ | |||
| @Contract | |||
| public class AssetContract3 implements EventProcessingAwire { | |||
| @@ -8,9 +8,8 @@ import com.jd.blockchain.utils.BaseConstant; | |||
| import com.jd.blockchain.utils.io.ByteArray; | |||
| /** | |||
| * mock the smart contract; | |||
| * The test takes data from the chain and compares it with the expected value; | |||
| * the value of param1Val should be consistent with that of Integration Test; | |||
| * 模拟用智能合约; | |||
| * 测试从链中取数据,然后对比是否与预定值一致;param1Val 的值要与IntegrationTest中保持一致; | |||
| */ | |||
| @Contract | |||
| public class AssetContract4 implements EventProcessingAwire { | |||
| @@ -32,6 +31,7 @@ public class AssetContract4 implements EventProcessingAwire { | |||
| ",contractDataAddress= "+contractDataAddress); | |||
| BlockchainKeyPair dataAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
| //TODO:register牵扯到账本中的事务处理,需要优化; | |||
| // contractEventContext.getLedger().dataAccounts().register(dataAccount.getIdentity()); | |||
| // contractEventContext.getLedger().dataAccount(dataAccount.getAddress()). | |||
| // set(param1,param1Val.getBytes(),-1).getOperation(); | |||
| @@ -55,9 +55,9 @@ public class AssetContract4 implements EventProcessingAwire { | |||
| KVDataEntry[] kvEntries = eventContext.getLedger().getDataEntries(eventContext.getCurrentLedgerHash(), | |||
| contractDataAddress, param1); | |||
| if (ByteArray.toHex(param1Val.getBytes()).equals(kvEntries[0].getValue())){ | |||
| System.out.println("getDataEntries() test,expect==actual;"); | |||
| System.out.println("getDataEntries() test,期望值==设定值;"); | |||
| } else { | |||
| System.out.println("getDataEntries() test,expect==actual;"); | |||
| System.out.println("getDataEntries() test,期望值!=设定值;"); | |||
| } | |||
| } | |||
| @@ -4,8 +4,8 @@ import com.jd.blockchain.contract.model.*; | |||
| import com.jd.blockchain.utils.BaseConstant; | |||
| /** | |||
| * mock the smart contract; | |||
| * Do only the simplest addition operation. | |||
| * 模拟用智能合约; | |||
| * 只做最简单的加法运算; | |||
| */ | |||
| @Contract | |||
| public class AssetContract5 implements EventProcessingAwire { | |||
| @@ -1,7 +1,7 @@ | |||
| package com.jd.blockchain.contract; | |||
| /** | |||
| * contract engine. | |||
| * 合约引擎; | |||
| * | |||
| * @author huanghaiquan | |||
| * | |||
| @@ -9,9 +9,9 @@ package com.jd.blockchain.contract; | |||
| public interface ContractEngine { | |||
| /** | |||
| * Returns the contract code for the specified address;<br> | |||
| * 返回指定地址的合约代码;<br> | |||
| * | |||
| * If not, return null; | |||
| * 如果不存在,则返回 null; | |||
| * | |||
| * @param address | |||
| * @return | |||
| @@ -19,9 +19,9 @@ public interface ContractEngine { | |||
| ContractCode getContract(String address, long version); | |||
| /** | |||
| * Load contract code;<br> | |||
| * 装入合约代码;<br> | |||
| * | |||
| * If it already exists, it returns the existing instance directly. | |||
| * 如果已经存在,则直接返回已有实例; | |||
| * | |||
| * @param address | |||
| * @param code | |||
| @@ -5,7 +5,7 @@ public interface ContractServiceProvider { | |||
| String getName(); | |||
| /** | |||
| * Return the contract code execution engine instance; | |||
| * 返回合约代码执行引擎实例; | |||
| * | |||
| * @return | |||
| */ | |||
| @@ -52,32 +52,31 @@ public class JavaContractCode implements ContractCode { | |||
| } | |||
| class ContractThread implements Runnable{ | |||
| @Override | |||
| public void run(){ | |||
| LOGGER.info("ContractThread execute()."); | |||
| try { | |||
| //Perform pretreatment; | |||
| //执行预处理; | |||
| long startTime = System.currentTimeMillis(); | |||
| String contractClassName = codeModule.getMainClass(); | |||
| Class myClass = codeModule.loadClass(contractClassName); | |||
| Object contractMainClassObj = myClass.newInstance(); | |||
| Object contractMainClassObj = myClass.newInstance();//合约主类生成的类实例; | |||
| Method beforeMth_ = myClass.getMethod("beforeEvent",codeModule.loadClass(ContractEventContext.class.getName())); | |||
| ReflectionUtils.invokeMethod(beforeMth_,contractMainClassObj,contractEventContext); | |||
| LOGGER.info("beforeEvent,spend time:"+(System.currentTimeMillis()-startTime)); | |||
| LOGGER.info("beforeEvent,耗时:"+(System.currentTimeMillis()-startTime)); | |||
| Method eventMethod = this.getMethodByAnno(contractMainClassObj,contractEventContext.getEvent()); | |||
| startTime = System.currentTimeMillis(); | |||
| ReflectionUtils.invokeMethod(eventMethod,contractMainClassObj,contractEventContext); | |||
| LOGGER.info("execute contract,spend time:"+(System.currentTimeMillis()-startTime)); | |||
| LOGGER.info("合约执行,耗时:"+(System.currentTimeMillis()-startTime)); | |||
| Method mth2 = myClass.getMethod("postEvent"); | |||
| startTime = System.currentTimeMillis(); | |||
| ReflectionUtils.invokeMethod(mth2,contractMainClassObj); | |||
| LOGGER.info("postEvent,spend time:"+(System.currentTimeMillis()-startTime)); | |||
| LOGGER.info("postEvent,耗时:"+(System.currentTimeMillis()-startTime)); | |||
| } catch (NoSuchMethodException e) { | |||
| e.printStackTrace(); | |||
| } catch (Exception e) { | |||
| @@ -85,7 +84,7 @@ public class JavaContractCode implements ContractCode { | |||
| } | |||
| } | |||
| //get the relation between the methods and annotations | |||
| //得到当前类中相关方法和注解对应关系; | |||
| Method getMethodByAnno(Object classObj, String eventName){ | |||
| Class<?> c = classObj.getClass(); | |||
| Class <ContractEvent> contractEventClass = null; | |||
| @@ -100,9 +99,9 @@ public class JavaContractCode implements ContractCode { | |||
| for(int i = 0;i<classMethods.length;i++){ | |||
| Annotation[] a = classMethods[i].getDeclaredAnnotations(); | |||
| methodAnnoMap.put(classMethods[i], a); | |||
| //if contain @ContractEvent in the method,then put it to the map; | |||
| //如果当前方法中包含@ContractEvent注解,则将其放入Map; | |||
| for(Annotation annotation_ : a){ | |||
| //if is the type of contractEvent,then put it to the map; | |||
| //如果是合同事件类型,则放入map; | |||
| if(classMethods[i].isAnnotationPresent(contractEventClass)){ | |||
| Object obj = classMethods[i].getAnnotation(contractEventClass); | |||
| String annoAllName = obj.toString(); | |||
| @@ -45,7 +45,7 @@ public class CheckImportsMojo extends AbstractMojo { | |||
| String importName = imp.getName().asString(); | |||
| for (String item : packageBlackList) { | |||
| if (importName.startsWith(item)) { | |||
| throw new MojoFailureException("Inclusion of this import package is not allowed in source code:" + importName); | |||
| throw new MojoFailureException("在源码中不允许包含此引入包:" + importName); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,8 +1,8 @@ | |||
| package com.jd.blockchain; | |||
| import com.jd.blockchain.contract.model.ContractDeployExeUtil; | |||
| import com.jd.blockchain.crypto.asymmetric.PrivKey; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.crypto.PrivKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.crypto.hash.HashDigest; | |||
| import com.jd.blockchain.ledger.BlockchainKeyPair; | |||
| import com.jd.blockchain.tools.keygen.KeyGenCommand; | |||
| @@ -23,12 +23,13 @@ import java.util.Properties; | |||
| /** | |||
| * for contract remote deploy; | |||
| * @phase compile | |||
| * @author zhaogw | |||
| * date 2018/10/18 10:12 | |||
| * @goal contractDeploy | |||
| * @phase process-sources | |||
| * @Author zhaogw | |||
| * @Date 2018/10/18 10:12 | |||
| */ | |||
| @Mojo(name = "contractDeploy") | |||
| @Mojo(name = "deploy") | |||
| public class ContractDeployMojo extends AbstractMojo { | |||
| Logger logger = LoggerFactory.getLogger(ContractDeployMojo.class); | |||
| @@ -64,56 +65,55 @@ public class ContractDeployMojo extends AbstractMojo { | |||
| throw new MojoFailureException("invalid port"); | |||
| } | |||
| String host = prop.getProperty("host"); | |||
| String ledger = prop.getProperty("ledgerHash"); | |||
| String ownerPubPath = prop.getProperty("ownerPubPath"); | |||
| String ownerPrvPath = prop.getProperty("ownerPrvPath"); | |||
| String ownerPassword = FileUtils.readText(prop.getProperty("ownerPassword")); | |||
| String chainCodePath = prop.getProperty("chainCodePath"); | |||
| String ledger = prop.getProperty("ledger"); | |||
| String pubKey = prop.getProperty("pubKey"); | |||
| String prvKey = prop.getProperty("prvKey"); | |||
| String password = prop.getProperty("password"); | |||
| String contractPath = prop.getProperty("contractPath"); | |||
| if(StringUtils.isEmpty(host)){ | |||
| logger.info("host can not be empty"); | |||
| logger.info("host不能为空"); | |||
| return; | |||
| } | |||
| if(StringUtils.isEmpty(ledger)){ | |||
| logger.info("ledger can not be empty."); | |||
| logger.info("ledger不能为空."); | |||
| return; | |||
| } | |||
| if(StringUtils.isEmpty(ownerPubPath)){ | |||
| logger.info("pubKey can not be empty."); | |||
| if(StringUtils.isEmpty(pubKey)){ | |||
| logger.info("pubKey不能为空."); | |||
| return; | |||
| } | |||
| if(StringUtils.isEmpty(ownerPrvPath)){ | |||
| logger.info("prvKey can not be empty."); | |||
| if(StringUtils.isEmpty(prvKey)){ | |||
| logger.info("prvKey不能为空."); | |||
| return; | |||
| } | |||
| if(StringUtils.isEmpty(chainCodePath)){ | |||
| logger.info("contractPath can not be empty."); | |||
| if(StringUtils.isEmpty(contractPath)){ | |||
| logger.info("contractPath不能为空."); | |||
| return; | |||
| } | |||
| File contract = new File(chainCodePath); | |||
| File contract = new File(contractPath); | |||
| if (!contract.isFile()){ | |||
| logger.info("file:"+chainCodePath+" is not exist"); | |||
| logger.info("文件"+contractPath+"不存在"); | |||
| return; | |||
| } | |||
| byte[] contractBytes = FileUtils.readBytes(chainCodePath); | |||
| byte[] contractBytes = FileUtils.readBytes(contractPath); | |||
| // PrivKey prv = KeyGenCommand.decodePrivKeyWithRawPassword(prvKey, password); | |||
| // PubKey pub = KeyGenCommand.decodePubKey(pubKey); | |||
| // BlockchainKeyPair blockchainKeyPair = new BlockchainKeyPair(pub, prv); | |||
| BlockchainKeyPair ownerKey = ContractDeployExeUtil.instance.getKeyPair(ownerPubPath, ownerPrvPath, ownerPassword); | |||
| PrivKey prv = KeyGenCommand.decodePrivKeyWithRawPassword(prvKey, password); | |||
| PubKey pub = KeyGenCommand.decodePubKey(pubKey); | |||
| BlockchainKeyPair blockchainKeyPair = new BlockchainKeyPair(pub, prv); | |||
| HashDigest ledgerHash = new HashDigest(Base58Utils.decode(ledger)); | |||
| StringBuffer sb = new StringBuffer(); | |||
| sb.append("host:"+ host).append(",port:"+port).append(",ledgerHash:"+ledgerHash.toBase58()). | |||
| append(",pubKey:"+ownerKey.getPubKey()).append(",prvKey:"+ownerKey.getPrivKey()).append(",contractPath:"+chainCodePath); | |||
| append(",pubKey:"+pubKey).append(",prvKey:"+prv).append(",contractPath:"+contractPath); | |||
| logger.info(sb.toString()); | |||
| if(ContractDeployExeUtil.instance.deploy(host,port,ledgerHash, ownerKey, contractBytes)){ | |||
| logger.info("deploy is OK."); | |||
| } | |||
| ContractDeployExeUtil.instance.deploy(host,port,ledgerHash, blockchainKeyPair, contractBytes); | |||
| } | |||
| } | |||
| @@ -1,7 +1,7 @@ | |||
| package com.jd.blockchain.contract.model; | |||
| /** | |||
| * The contract implements this interface to monitor the life cycle events of the contract application. | |||
| * 合约实现此接口可以监听合约应用的生命周期事件; | |||
| * | |||
| * | |||
| * @author huanghaiquan | |||
| @@ -6,8 +6,8 @@ import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
| import com.jd.blockchain.crypto.asymmetric.PrivKey; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.crypto.PrivKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.crypto.hash.HashDigest; | |||
| import com.jd.blockchain.ledger.BlockchainIdentity; | |||
| import com.jd.blockchain.ledger.BlockchainIdentityData; | |||
| @@ -130,10 +130,10 @@ public enum ContractDeployExeUtil { | |||
| txTpl.contracts().deploy(contractIdentity, chainCode); | |||
| PreparedTransaction ptx = txTpl.prepare(); | |||
| ptx.sign(ownerKey); | |||
| // Submit and wait for consensus to return; | |||
| // 提交并等待共识返回; | |||
| TransactionResponse txResp = ptx.commit(); | |||
| // Verification results; | |||
| // 验证结果; | |||
| contractAddress = contractIdentity.getAddress(); | |||
| this.setContractAddress(contractAddress); | |||
| System.out.println("contract's address="+contractAddress); | |||
| @@ -147,7 +147,7 @@ public enum ContractDeployExeUtil { | |||
| return deploy(ledgerHash, contractIdentity, ownerKey, chainCode); | |||
| } | |||
| // Generate contract addresses based on user-specified public keys | |||
| // 根据用户指定的公钥生成合约地址 | |||
| public boolean deploy(String host, int port, String ledger,String ownerPubPath, String ownerPrvPath, | |||
| String ownerPassword, String chainCodePath,String pubPath){ | |||
| PubKey pubKey = getPubKey(pubPath); | |||
| @@ -165,18 +165,18 @@ public enum ContractDeployExeUtil { | |||
| BlockchainKeyPair ownerKey = getKeyPair(ownerPubPath, ownerPrvPath, ownerPassword); | |||
| HashDigest ledgerHash = new HashDigest(Base58Utils.decode(ledger)); | |||
| // Define the transaction, transfer the simplest numbers, strings, extract the address in the contract; | |||
| // 定义交易,传输最简单的数字、字符串、提取合约中的地址; | |||
| TransactionTemplate txTpl = bcsrv.newTransaction(ledgerHash); | |||
| txTpl.contractEvents().send(getContractAddress(),event,contractArgs.getBytes()); | |||
| // sign; | |||
| // 签名; | |||
| PreparedTransaction ptx = txTpl.prepare(); | |||
| ptx.sign(ownerKey); | |||
| // Submit and wait for consensus to return; | |||
| // 提交并等待共识返回; | |||
| TransactionResponse txResp = ptx.commit(); | |||
| // Verification results; | |||
| // 验证结果; | |||
| return txResp.isSuccess(); | |||
| } | |||
| @@ -10,52 +10,52 @@ import java.util.Set; | |||
| public interface ContractEventContext { | |||
| /** | |||
| * current ledger hash; | |||
| * 当前账本哈希; | |||
| * | |||
| * @return | |||
| */ | |||
| HashDigest getCurrentLedgerHash(); | |||
| /** | |||
| * Transaction requests for execution of contract events; | |||
| * 执行合约事件的交易请求; | |||
| * | |||
| * @return | |||
| */ | |||
| TransactionRequest getTransactionRequest(); | |||
| /** | |||
| * Collection of signatories of the transaction; | |||
| * 交易的签署人集合; | |||
| * | |||
| * @return | |||
| */ | |||
| Set<BlockchainIdentity> getTxSigners(); | |||
| /** | |||
| * event name; | |||
| * 事件名称; | |||
| * | |||
| * @return | |||
| */ | |||
| String getEvent(); | |||
| /** | |||
| * param list; | |||
| * 参数列表; | |||
| * | |||
| * @return | |||
| */ | |||
| byte[] getArgs(); | |||
| /** | |||
| * ledger operation context; | |||
| * 账本操作上下文; | |||
| * | |||
| * @return | |||
| */ | |||
| LedgerContext getLedger(); | |||
| /** | |||
| * Collection of Contracts Owners; | |||
| * 合约的拥有者集合; | |||
| * | |||
| * <br> | |||
| * The owner of the contract is the signer when the contract is deployed. | |||
| * 合约的拥有者是部署合约时的签名者; | |||
| * | |||
| * @return | |||
| */ | |||
| @@ -1,7 +1,8 @@ | |||
| package com.jd.blockchain.contract.model; | |||
| /** | |||
| * The sub-interface of contract implementation {@link ContractRuntimeAwire} can listen for life cycle events at runtime. | |||
| * 合约实现 {@link ContractRuntimeAwire} 的子接口可以监听运行时的生命周期事件; | |||
| * | |||
| * @author huanghaiquan | |||
| * | |||
| */ | |||
| @@ -1,15 +1,15 @@ | |||
| package com.jd.blockchain.contract.model; | |||
| /** | |||
| * ErrorCodeEnum | |||
| * @author zhaogw | |||
| * date 2018/11/8 15:32 | |||
| * 给每个错误编码,编译快速定位; | |||
| * @Author zhaogw | |||
| * @Date 2018/11/8 15:32 | |||
| */ | |||
| public enum ErrorCodeEnum { | |||
| //<100为fatal error; | |||
| //<100为致命错误; | |||
| GATEWAY_CONNECT_ERROR(1,ErrorType.ERROR,"GatewayServiceFactory connect error.!"), | |||
| CONTRACT_CLASSPATH_NOT_SET(2,ErrorType.ERROR,"in private contract classLoader,no jar in the contract folder!"), | |||
| //Other errors are counted from 101. | |||
| //其它错误从101开始计数; | |||
| AMOUNT_NEGATIVE(101,ErrorType.ALARM,"The amount is negative!"); | |||
| @@ -40,7 +40,7 @@ public enum ErrorCodeEnum { | |||
| } | |||
| /** | |||
| * Classify the errors so that they can be summarized easily. | |||
| * 给错误分个类,便于汇总; | |||
| */ | |||
| class ErrorType { | |||
| public static final int ALARM = 0; | |||
| @@ -6,7 +6,7 @@ import java.lang.annotation.RetentionPolicy; | |||
| import java.lang.annotation.Target; | |||
| /** | |||
| * HTTP service method; | |||
| * HTTP 服务方法; | |||
| * | |||
| * @author haiq | |||
| * | |||
| @@ -7,35 +7,33 @@ package com.jd.blockchain.contract.model; | |||
| public interface EventProcessingAwire extends ContractRuntimeAwire { | |||
| /** | |||
| * Called before the event handling method is executed; | |||
| * 在事件处理方法执行之前调用; | |||
| * | |||
| * @param eventContext | |||
| */ | |||
| void beforeEvent(ContractEventContext eventContext); | |||
| /** | |||
| * Called after the event handling method is successfully executed; | |||
| * 在事件处理方法成功执行之后调用; | |||
| * | |||
| * @param eventContext | |||
| * evenet; | |||
| * 事件上下文; | |||
| * @param error | |||
| * Error; if the event processing ends normally, this parameter is null; | |||
| * if an event processing error occurs, this parameter is not empty; | |||
| * 错误;如果事件处理正常结束,则此参数为 null;如果事件处理发生了错误,此参数非空; | |||
| */ | |||
| void postEvent(ContractEventContext eventContext, ContractException error); | |||
| /** | |||
| * Called after the event handling method is successfully executed; | |||
| * 在事件处理方法成功执行之后调用; | |||
| * | |||
| * @param error | |||
| * Error; if the event processing ends normally, this parameter is null; | |||
| * if an event processing error occurs, this parameter is not empty; | |||
| * 错误;如果事件处理正常结束,则此参数为 null;如果事件处理发生了错误,此参数非空; | |||
| */ | |||
| void postEvent(ContractException error); | |||
| /** | |||
| * Called after the event handling method is successfully executed; | |||
| * 在事件处理方法成功执行之后调用; | |||
| */ | |||
| void postEvent(); | |||
| } | |||
| @@ -1,15 +1,22 @@ | |||
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
| <modelVersion>4.0.0</modelVersion> | |||
| <parent> | |||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | |||
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
| <modelVersion>4.0.0</modelVersion> | |||
| <parent> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>crypto</artifactId> | |||
| <version>0.9.0-SNAPSHOT</version> | |||
| <version>0.9.0-SNAPSHOT</version> | |||
| </parent> | |||
| <artifactId>crypto-adv</artifactId> | |||
| <artifactId>crypto-adv</artifactId> | |||
| <dependencies> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>crypto-sm</artifactId> | |||
| <version>${project.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.bouncycastle</groupId> | |||
| <artifactId>bcprov-jdk15on</artifactId> | |||
| @@ -48,28 +55,14 @@ | |||
| <dependency> | |||
| <groupId>org.mockito</groupId> | |||
| <artifactId>mockito-core</artifactId> | |||
| <version>1.10.19</version> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>crypto-framework</artifactId> | |||
| <version>${project.version}</version> | |||
| <scope>compile</scope> | |||
| </dependency> | |||
| </dependencies> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>crypto-framework</artifactId> | |||
| <version>${project.version}</version> | |||
| <scope>compile</scope> | |||
| </dependency> | |||
| <build> | |||
| <plugins> | |||
| <plugin> | |||
| <groupId>org.apache.maven.plugins</groupId> | |||
| <artifactId>maven-deploy-plugin</artifactId> | |||
| <version>2.8.2</version> | |||
| <configuration> | |||
| <skip>true</skip> | |||
| </configuration> | |||
| </plugin> | |||
| </plugins> | |||
| </build> | |||
| </dependencies> | |||
| </project> | |||
| @@ -1,6 +1,7 @@ | |||
| package com.jd.blockchain.crypto.ecvrf; | |||
| import com.jd.blockchain.crypto.CryptoException; | |||
| import com.sun.jna.Library; | |||
| import com.sun.jna.Native; | |||
| @@ -27,7 +28,9 @@ public class VRF { | |||
| } | |||
| // unsupported OS | |||
| else throw new IllegalArgumentException("The VRF implementation is not supported in this Operation System!"); | |||
| else { | |||
| throw new CryptoException("The VRF implementation is not supported in this Operation System!"); | |||
| } | |||
| path = Objects.requireNonNull(VRF.class.getClassLoader().getResource(lib)).getPath(); | |||
| return path; | |||
| @@ -1,5 +1,6 @@ | |||
| package com.jd.blockchain.crypto.mpc; | |||
| import com.jd.blockchain.crypto.CryptoException; | |||
| import com.jd.blockchain.crypto.elgamal.ElGamalUtils; | |||
| import com.jd.blockchain.utils.io.BytesUtils; | |||
| import org.bouncycastle.crypto.AsymmetricCipherKeyPair; | |||
| @@ -56,8 +57,9 @@ public class EqualVerify { | |||
| public static byte[] responder(int responderInput, byte[] sponsorOutput, byte[] responderEPubKeyBytes, | |||
| byte[] responderEPrivKeyBytes) { | |||
| if (sponsorOutput.length != ELEMENTLENGTH) | |||
| throw new IllegalArgumentException("The sponsorOutput' length is not 64!"); | |||
| if (sponsorOutput.length != ELEMENTLENGTH) { | |||
| throw new CryptoException("The sponsorOutput' length is not 64!"); | |||
| } | |||
| BigInteger responderBigInt = BigInteger.valueOf(responderInput); | |||
| BigInteger responderEPubKey = new BigInteger(1,responderEPubKeyBytes); | |||
| @@ -72,8 +74,9 @@ public class EqualVerify { | |||
| public static boolean sponsorCheck(int sponsorInput, byte[] responderOutput, byte[] sponsorEPrivKeyBytes){ | |||
| if (responderOutput.length != 2 * ELEMENTLENGTH) | |||
| throw new IllegalArgumentException("The responderOutput's length is not 128!"); | |||
| if (responderOutput.length != 2 * ELEMENTLENGTH) { | |||
| throw new CryptoException("The responderOutput's length is not 128!"); | |||
| } | |||
| byte[] responderCipherBytes = new byte[ELEMENTLENGTH]; | |||
| byte[] dhValueBytes = new byte[ELEMENTLENGTH]; | |||
| @@ -99,9 +102,12 @@ public class EqualVerify { | |||
| private static byte[] bigIntegerTo64Bytes(BigInteger b){ | |||
| byte[] tmp = b.toByteArray(); | |||
| byte[] result = new byte[64]; | |||
| 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); | |||
| 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; | |||
| } | |||
| } | |||
| @@ -1,5 +1,6 @@ | |||
| package com.jd.blockchain.crypto.mpc; | |||
| import com.jd.blockchain.crypto.CryptoException; | |||
| import com.jd.blockchain.crypto.elgamal.ElGamalUtils; | |||
| import com.jd.blockchain.utils.io.BytesUtils; | |||
| import org.bouncycastle.crypto.AsymmetricCipherKeyPair; | |||
| @@ -67,13 +68,15 @@ public class IntCompare { | |||
| public static byte[][] responder(int responderInt, byte[][] cipherArray, byte[] pubKeyBytes){ | |||
| if (cipherArray.length != 2 * INTLENGTH) | |||
| throw new IllegalArgumentException("The cipherArray has wrong format!"); | |||
| if (cipherArray.length != 2 * INTLENGTH) { | |||
| throw new CryptoException("The cipherArray has wrong format!"); | |||
| } | |||
| int i,j; | |||
| for (i = 0; i < cipherArray.length; i++){ | |||
| if(cipherArray[i].length != CIPHERLENGTH) | |||
| throw new IllegalArgumentException("The cipherArray has wrong format!"); | |||
| if(cipherArray[i].length != CIPHERLENGTH) { | |||
| throw new CryptoException("The cipherArray has wrong format!"); | |||
| } | |||
| } | |||
| String[] responderStrSet = encoding(responderInt, false); | |||
| @@ -131,16 +134,18 @@ public class IntCompare { | |||
| public static int sponsorOutput(byte[][] aggregatedCipherArray, byte[] privKeyBytes){ | |||
| if (aggregatedCipherArray.length != INTLENGTH) | |||
| throw new IllegalArgumentException("The aggregatedCipherArray has wrong format!"); | |||
| if (aggregatedCipherArray.length != INTLENGTH) { | |||
| throw new CryptoException("The aggregatedCipherArray has wrong format!"); | |||
| } | |||
| int i; | |||
| byte[] plaintext; | |||
| for (i = 0; i < aggregatedCipherArray.length; i++){ | |||
| if(aggregatedCipherArray[i].length != CIPHERLENGTH) | |||
| throw new IllegalArgumentException("The aggregatedCipherArray has wrong format!"); | |||
| if(aggregatedCipherArray[i].length != CIPHERLENGTH) { | |||
| throw new CryptoException("The aggregatedCipherArray has wrong format!"); | |||
| } | |||
| plaintext = ElGamalUtils.decrypt(aggregatedCipherArray[i], privKeyBytes); | |||
| @@ -186,8 +191,9 @@ public class IntCompare { | |||
| private static String to32BinaryString(int integer) { | |||
| if (integer < 0) | |||
| throw new IllegalArgumentException("integer must be non-negative!"); | |||
| if (integer < 0) { | |||
| throw new CryptoException("integer must be non-negative!"); | |||
| } | |||
| int i; | |||
| String str = Integer.toBinaryString(integer); | |||
| @@ -204,16 +210,19 @@ public class IntCompare { | |||
| * @return the next pseudorandom, uniformly distributed {@code int} | |||
| * value between min (inclusive) and max (inclusive) | |||
| * from this random number generator's sequence | |||
| * @throws IllegalArgumentException if min is not non-negative, | |||
| * @throws CryptoException if min is not non-negative, | |||
| * max is not positive, or min is bigger than max | |||
| */ | |||
| private static int randInt(int min, int max) { | |||
| if (min < 0) | |||
| throw new IllegalArgumentException("min must be non-negative!"); | |||
| if (max <= 0) | |||
| throw new IllegalArgumentException("max must be positive!"); | |||
| if (min > max) | |||
| throw new IllegalArgumentException("min must not be greater than max"); | |||
| if (min < 0) { | |||
| throw new CryptoException("min must be non-negative!"); | |||
| } | |||
| if (max <= 0) { | |||
| throw new CryptoException("max must be positive!"); | |||
| } | |||
| if (min > max) { | |||
| throw new CryptoException("min must not be greater than max"); | |||
| } | |||
| Random random = new Random(); | |||
| return random.nextInt(max) % (max - min + 1) + min; | |||
| @@ -244,23 +253,28 @@ public class IntCompare { | |||
| private static byte[] bigIntegerTo64Bytes(BigInteger b){ | |||
| byte[] tmp = b.toByteArray(); | |||
| byte[] result = new byte[64]; | |||
| 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); | |||
| 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; | |||
| } | |||
| private static BigInteger getLeftBigIntegerFrom128Bytes(byte[] byteArray){ | |||
| if (byteArray.length != 128) | |||
| throw new IllegalArgumentException("The byteArray's length must be 128!"); | |||
| if (byteArray.length != 128) { | |||
| throw new CryptoException("The byteArray's length must be 128!"); | |||
| } | |||
| byte[] tmp = new byte[64]; | |||
| System.arraycopy(byteArray, 0, tmp, 0, tmp.length); | |||
| return new BigInteger(1, tmp); | |||
| } | |||
| private static BigInteger getRightBigIntegerFrom128Bytes(byte[] byteArray){ | |||
| if (byteArray.length != 128) | |||
| throw new IllegalArgumentException("The byteArray's length must be 128!"); | |||
| if (byteArray.length != 128) { | |||
| throw new CryptoException("The byteArray's length must be 128!"); | |||
| } | |||
| byte[] tmp = new byte[64]; | |||
| System.arraycopy(byteArray, 64, tmp, 0, tmp.length); | |||
| return new BigInteger(1, tmp); | |||
| @@ -1,11 +1,6 @@ | |||
| package com.jd.blockchain.crypto.mpc; | |||
| 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.smutils.asymmetric.SM2Utils; | |||
| import com.jd.blockchain.crypto.smutils.hash.SM3Utils; | |||
| import com.jd.blockchain.utils.io.BytesUtils; | |||
| import java.math.BigInteger; | |||
| import org.bouncycastle.crypto.AsymmetricCipherKeyPair; | |||
| import org.bouncycastle.crypto.CipherParameters; | |||
| @@ -17,7 +12,12 @@ import org.bouncycastle.math.ec.ECCurve; | |||
| import org.bouncycastle.math.ec.ECPoint; | |||
| import org.bouncycastle.util.encoders.Hex; | |||
| import java.math.BigInteger; | |||
| 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 { | |||
| @@ -11,9 +11,12 @@ public class PaillierUtils { | |||
| public static byte[] BigIntegerToLBytes(BigInteger b, int l){ | |||
| byte[] tmp = b.toByteArray(); | |||
| byte[] result = new byte[l]; | |||
| 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); | |||
| 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; | |||
| } | |||
| @@ -1,5 +1,6 @@ | |||
| package test.com.jd.blockchain.crypto.ecvrf; | |||
| import com.jd.blockchain.crypto.CryptoException; | |||
| import com.jd.blockchain.crypto.ecvrf.VRF; | |||
| import org.junit.Test; | |||
| @@ -66,7 +67,7 @@ public class VRFTest { | |||
| } | |||
| else { | |||
| assertNotNull(actualEx); | |||
| Class<?> expectedException = IllegalArgumentException.class; | |||
| Class<?> expectedException = CryptoException.class; | |||
| assertTrue(expectedException.isAssignableFrom(actualEx.getClass())); | |||
| } | |||
| } | |||
| @@ -0,0 +1,20 @@ | |||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | |||
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
| <modelVersion>4.0.0</modelVersion> | |||
| <parent> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>crypto</artifactId> | |||
| <version>0.9.0-SNAPSHOT</version> | |||
| </parent> | |||
| <artifactId>crypto-classic</artifactId> | |||
| <dependencies> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>crypto-framework</artifactId> | |||
| <version>${project.version}</version> | |||
| </dependency> | |||
| </dependencies> | |||
| </project> | |||
| @@ -0,0 +1,216 @@ | |||
| package com.jd.blockchain.crypto.service.classic; | |||
| 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.SYMMETRIC_KEY; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.io.OutputStream; | |||
| import com.jd.blockchain.crypto.*; | |||
| import com.jd.blockchain.crypto.SymmetricKey; | |||
| import com.jd.blockchain.crypto.symmetric.SymmetricCiphertext; | |||
| import com.jd.blockchain.crypto.symmetric.SymmetricEncryptionFunction; | |||
| import com.jd.blockchain.utils.security.AESUtils; | |||
| public class AESEncryptionFunction implements SymmetricEncryptionFunction { | |||
| public static final CryptoAlgorithm AES = ClassicCryptoService.AES_ALGORITHM; | |||
| private static final int KEY_SIZE = 128 / 8; | |||
| private static final int BLOCK_SIZE = 128 / 8; | |||
| private static final int PLAINTEXT_BUFFER_LENGTH = 256; | |||
| private static final int CIPHERTEXT_BUFFER_LENGTH = 256 + 16 + 2; | |||
| private static final int SYMMETRICKEY_LENGTH = ALGORYTHM_CODE_SIZE + KEY_TYPE_BYTES + KEY_SIZE; | |||
| AESEncryptionFunction() { | |||
| } | |||
| @Override | |||
| public Ciphertext encrypt(SymmetricKey key, byte[] data) { | |||
| byte[] rawKeyBytes = key.getRawKeyBytes(); | |||
| // 验证原始密钥长度为128比特,即16字节 | |||
| if (rawKeyBytes.length != KEY_SIZE) { | |||
| throw new CryptoException("This key has wrong format!"); | |||
| } | |||
| // 验证密钥数据的算法标识对应AES算法 | |||
| if (key.getAlgorithm().code() != AES.code()) { | |||
| throw new CryptoException("The is not AES symmetric key!"); | |||
| } | |||
| // 调用底层AES128算法并计算密文数据 | |||
| return new SymmetricCiphertext(AES, AESUtils.encrypt(data, rawKeyBytes)); | |||
| } | |||
| @Override | |||
| public void encrypt(SymmetricKey key, InputStream in, OutputStream out) { | |||
| // 读输入流得到明文,加密,密文数据写入输出流 | |||
| try { | |||
| // TODO: 错误地使用 available 方法; | |||
| byte[] buffBytes = new byte[PLAINTEXT_BUFFER_LENGTH]; | |||
| // The final byte of plaintextWithPadding represents the length of padding in the first 256 bytes, | |||
| // and the padded value in hexadecimal | |||
| byte[] plaintextWithPadding = new byte[buffBytes.length + 1]; | |||
| byte padding; | |||
| int len; | |||
| int i; | |||
| while((len=in.read(buffBytes)) > 0){ | |||
| padding = (byte) (PLAINTEXT_BUFFER_LENGTH - len); | |||
| i = len; | |||
| while (i < plaintextWithPadding.length){ | |||
| plaintextWithPadding[i] = padding; | |||
| i++; | |||
| } | |||
| out.write(encrypt(key,plaintextWithPadding).toBytes()); | |||
| } | |||
| // int size = in.available(); | |||
| // if (size < 1){ | |||
| // throw new CryptoException("The input is null!"); | |||
| // } | |||
| // | |||
| // byte[] aesData = new byte[size]; | |||
| // | |||
| // if (in.read(aesData) != -1) { | |||
| // out.write(encrypt(key, aesData).); | |||
| // } | |||
| // | |||
| // in.close(); | |||
| // out.close(); | |||
| } catch (IOException e) { | |||
| throw new CryptoException(e.getMessage(), e); | |||
| } | |||
| } | |||
| @Override | |||
| public byte[] decrypt(SymmetricKey key, Ciphertext ciphertext) { | |||
| byte[] rawKeyBytes = key.getRawKeyBytes(); | |||
| byte[] rawCiphertextBytes = ciphertext.getRawCiphertext(); | |||
| // 验证原始密钥长度为128比特,即16字节 | |||
| if (rawKeyBytes.length != KEY_SIZE) { | |||
| throw new CryptoException("This key has wrong format!"); | |||
| } | |||
| // 验证密钥数据的算法标识对应AES算法 | |||
| if (key.getAlgorithm().code() != AES.code()) { | |||
| throw new CryptoException("The is not AES symmetric key!"); | |||
| } | |||
| // 验证原始密文长度为分组长度的整数倍 | |||
| if (rawCiphertextBytes.length % BLOCK_SIZE != 0) { | |||
| throw new CryptoException("This ciphertext has wrong format!"); | |||
| } | |||
| // 验证密文数据算法标识对应AES算法 | |||
| if (ciphertext.getAlgorithm().code() != AES.code()) { | |||
| throw new CryptoException("This is not AES ciphertext!"); | |||
| } | |||
| // 调用底层AES128算法解密,得到明文 | |||
| return AESUtils.decrypt(rawCiphertextBytes, rawKeyBytes); | |||
| } | |||
| @Override | |||
| public void decrypt(SymmetricKey key, InputStream in, OutputStream out) { | |||
| // 读输入流得到密文数据,解密,明文写入输出流 | |||
| try { | |||
| byte[] buffBytes = new byte[CIPHERTEXT_BUFFER_LENGTH]; | |||
| byte[] plaintextWithPadding = new byte[PLAINTEXT_BUFFER_LENGTH + 1]; | |||
| byte padding; | |||
| byte[] plaintext; | |||
| int len,i; | |||
| while ((len = in.read(buffBytes)) > 0){ | |||
| if (len != CIPHERTEXT_BUFFER_LENGTH){ | |||
| throw new CryptoException("inputStream's length is wrong!"); | |||
| } | |||
| if (!supportCiphertext(buffBytes)) { | |||
| throw new CryptoException("InputStream is not valid AES ciphertext!"); | |||
| } | |||
| plaintextWithPadding = decrypt(key,resolveCiphertext(buffBytes)); | |||
| if (plaintextWithPadding.length != (PLAINTEXT_BUFFER_LENGTH +1)){ | |||
| throw new CryptoException("The decrypted plaintext is valid"); | |||
| } | |||
| padding = plaintextWithPadding[PLAINTEXT_BUFFER_LENGTH]; | |||
| i = PLAINTEXT_BUFFER_LENGTH; | |||
| while ((PLAINTEXT_BUFFER_LENGTH - padding) < i){ | |||
| i--; | |||
| } | |||
| plaintext = new byte[PLAINTEXT_BUFFER_LENGTH - padding]; | |||
| System.arraycopy(plaintextWithPadding,0,plaintext,0,plaintext.length); | |||
| out.write(plaintext); | |||
| } | |||
| // // TODO: 错误地使用 available 方法; | |||
| // byte[] aesData = new byte[in.available()]; | |||
| // in.read(aesData); | |||
| // in.close(); | |||
| // | |||
| // if (!supportCiphertext(aesData)) { | |||
| // throw new CryptoException("InputStream is not valid AES ciphertext!"); | |||
| // } | |||
| // | |||
| // out.write(decrypt(key, resolveCiphertext(aesData))); | |||
| // out.close(); | |||
| } catch (IOException e) { | |||
| throw new CryptoException(e.getMessage(), e); | |||
| } | |||
| } | |||
| @Override | |||
| public boolean supportSymmetricKey(byte[] symmetricKeyBytes) { | |||
| // 验证输入字节数组长度=算法标识长度+密钥类型长度+密钥长度,字节数组的算法标识对应AES算法且密钥密钥类型是对称密钥 | |||
| return symmetricKeyBytes.length == SYMMETRICKEY_LENGTH && CryptoAlgorithm.match(AES, symmetricKeyBytes) | |||
| && symmetricKeyBytes[ALGORYTHM_CODE_SIZE] == SYMMETRIC_KEY.CODE; | |||
| } | |||
| @Override | |||
| public SymmetricKey resolveSymmetricKey(byte[] symmetricKeyBytes) { | |||
| // 由框架调用 support 方法检查有效性,在此不做重复检查; | |||
| return new SymmetricKey(symmetricKeyBytes); | |||
| } | |||
| @Override | |||
| public boolean supportCiphertext(byte[] ciphertextBytes) { | |||
| // 验证(输入字节数组长度-算法标识长度)是分组长度的整数倍,字节数组的算法标识对应AES算法 | |||
| return (ciphertextBytes.length - ALGORYTHM_CODE_SIZE) % BLOCK_SIZE == 0 | |||
| && CryptoAlgorithm.match(AES, ciphertextBytes); | |||
| } | |||
| @Override | |||
| public SymmetricCiphertext resolveCiphertext(byte[] ciphertextBytes) { | |||
| // 由框架调用 support 方法检查有效性,在此不做重复检查; | |||
| return new SymmetricCiphertext(ciphertextBytes); | |||
| } | |||
| @Override | |||
| public CryptoAlgorithm getAlgorithm() { | |||
| return AES; | |||
| } | |||
| @Override | |||
| public CryptoKey generateSymmetricKey() { | |||
| // 根据对应的标识和原始密钥生成相应的密钥数据 | |||
| return new SymmetricKey(AES, AESUtils.generateKey128_Bytes()); | |||
| } | |||
| } | |||
| @@ -0,0 +1,62 @@ | |||
| package com.jd.blockchain.crypto.service.classic; | |||
| import java.util.Arrays; | |||
| import java.util.Collection; | |||
| import java.util.Collections; | |||
| import java.util.List; | |||
| import com.jd.blockchain.crypto.CryptoAlgorithm; | |||
| import com.jd.blockchain.crypto.CryptoAlgorithmDefinition; | |||
| import com.jd.blockchain.crypto.CryptoFunction; | |||
| import com.jd.blockchain.crypto.CryptoService; | |||
| import com.jd.blockchain.provider.NamedProvider; | |||
| @NamedProvider("CLASSIC") | |||
| public class ClassicCryptoService implements CryptoService { | |||
| public static final CryptoAlgorithm ED25519_ALGORITHM = CryptoAlgorithmDefinition.defineSignature("ED25519", | |||
| false, (byte) 21); | |||
| public static final CryptoAlgorithm ECDSA_ALGORITHM = CryptoAlgorithmDefinition.defineSignature("ECDSA", | |||
| false, (byte) 22); | |||
| public static final CryptoAlgorithm RSA_ALGORITHM = CryptoAlgorithmDefinition.defineSignature("RSA", | |||
| true, (byte) 23); | |||
| public static final CryptoAlgorithm SHA256_ALGORITHM = CryptoAlgorithmDefinition.defineHash("SHA256", | |||
| (byte) 24); | |||
| public static final CryptoAlgorithm RIPEMD160_ALGORITHM = CryptoAlgorithmDefinition.defineHash("RIPEMD160", | |||
| (byte) 25); | |||
| public static final CryptoAlgorithm AES_ALGORITHM = CryptoAlgorithmDefinition.defineSymmetricEncryption("AES", | |||
| (byte) 26); | |||
| public static final CryptoAlgorithm JVM_SECURE_RANDOM_ALGORITHM = CryptoAlgorithmDefinition | |||
| .defineRandom("JVM-SECURE-RANDOM", (byte) 27); | |||
| public static final AESEncryptionFunction AES = new AESEncryptionFunction(); | |||
| public static final ED25519SignatureFunction ED25519 = new ED25519SignatureFunction(); | |||
| public static final RIPEMD160HashFunction RIPEMD160 = new RIPEMD160HashFunction(); | |||
| public static final SHA256HashFunction SHA256 = new SHA256HashFunction(); | |||
| public static final JVMSecureRandomFunction JVM_SECURE_RANDOM = new JVMSecureRandomFunction(); | |||
| // public static final ECDSASignatureFunction ECDSA = new | |||
| // ECDSASignatureFunction(); | |||
| private static final Collection<CryptoFunction> FUNCTIONS; | |||
| static { | |||
| List<CryptoFunction> funcs = Arrays.asList(AES, ED25519, RIPEMD160, SHA256, JVM_SECURE_RANDOM); | |||
| FUNCTIONS = Collections.unmodifiableList(funcs); | |||
| } | |||
| @Override | |||
| public Collection<CryptoFunction> getFunctions() { | |||
| return FUNCTIONS; | |||
| } | |||
| } | |||
| @@ -0,0 +1,67 @@ | |||
| package com.jd.blockchain.crypto.service.classic; | |||
| import com.jd.blockchain.crypto.CryptoAlgorithm; | |||
| import com.jd.blockchain.crypto.PrivKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.crypto.asymmetric.*; | |||
| public class ECDSASignatureFunction implements SignatureFunction { | |||
| ECDSASignatureFunction() { | |||
| } | |||
| @Override | |||
| public SignatureDigest sign(PrivKey privKey, byte[] data) { | |||
| return null; | |||
| } | |||
| @Override | |||
| public boolean verify(SignatureDigest digest, PubKey pubKey, byte[] data) { | |||
| return false; | |||
| } | |||
| @Override | |||
| public byte[] retrievePubKeyBytes(byte[] privKeyBytes) { | |||
| return new byte[0]; | |||
| } | |||
| @Override | |||
| public boolean supportPrivKey(byte[] privKeyBytes) { | |||
| return false; | |||
| } | |||
| @Override | |||
| public PrivKey resolvePrivKey(byte[] privKeyBytes) { | |||
| return null; | |||
| } | |||
| @Override | |||
| public boolean supportPubKey(byte[] pubKeyBytes) { | |||
| return false; | |||
| } | |||
| @Override | |||
| public PubKey resolvePubKey(byte[] pubKeyBytes) { | |||
| return null; | |||
| } | |||
| @Override | |||
| public boolean supportDigest(byte[] digestBytes) { | |||
| return false; | |||
| } | |||
| @Override | |||
| public SignatureDigest resolveDigest(byte[] digestBytes) { | |||
| return null; | |||
| } | |||
| @Override | |||
| public CryptoAlgorithm getAlgorithm() { | |||
| return ClassicCryptoService.ECDSA_ALGORITHM; | |||
| } | |||
| @Override | |||
| public CryptoKeyPair generateKeyPair() { | |||
| return null; | |||
| } | |||
| } | |||
| @@ -1,7 +1,19 @@ | |||
| package com.jd.blockchain.crypto.impl.def.asymmetric; | |||
| package com.jd.blockchain.crypto.service.classic; | |||
| 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.PRIV_KEY; | |||
| import static com.jd.blockchain.crypto.CryptoKeyType.PUB_KEY; | |||
| import java.security.KeyPair; | |||
| import com.jd.blockchain.crypto.CryptoAlgorithm; | |||
| import com.jd.blockchain.crypto.asymmetric.*; | |||
| import com.jd.blockchain.crypto.CryptoException; | |||
| import com.jd.blockchain.crypto.PrivKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.crypto.asymmetric.CryptoKeyPair; | |||
| import com.jd.blockchain.crypto.asymmetric.SignatureDigest; | |||
| import com.jd.blockchain.crypto.asymmetric.SignatureFunction; | |||
| import com.jd.blockchain.utils.security.Ed25519Utils; | |||
| import net.i2p.crypto.eddsa.EdDSAPrivateKey; | |||
| @@ -11,25 +23,19 @@ import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable; | |||
| import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec; | |||
| import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec; | |||
| import java.security.KeyPair; | |||
| import static com.jd.blockchain.crypto.CryptoAlgorithm.ED25519; | |||
| import static com.jd.blockchain.crypto.CryptoBytes.ALGORYTHM_BYTES; | |||
| import static com.jd.blockchain.crypto.CryptoKeyType.PRIV_KEY; | |||
| import static com.jd.blockchain.crypto.CryptoKeyType.PUB_KEY; | |||
| import static com.jd.blockchain.crypto.base.BaseCryptoKey.KEY_TYPE_BYTES; | |||
| public class ED25519SignatureFunction implements SignatureFunction { | |||
| private static final CryptoAlgorithm ED25519 = ClassicCryptoService.ED25519_ALGORITHM; | |||
| private static final int PUBKEY_SIZE = 32; | |||
| private static final int PRIVKEY_SIZE = 32; | |||
| private static final int DIGEST_SIZE = 64; | |||
| private static final int SIGNATUREDIGEST_SIZE = 64; | |||
| private static final int PUBKEY_LENGTH = ALGORYTHM_BYTES + KEY_TYPE_BYTES + PUBKEY_SIZE; | |||
| private static final int PRIVKEY_LENGTH = ALGORYTHM_BYTES + KEY_TYPE_BYTES + PRIVKEY_SIZE; | |||
| private static final int SIGNATUREDIGEST_LENGTH = ALGORYTHM_BYTES + DIGEST_SIZE; | |||
| 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; | |||
| public ED25519SignatureFunction() { | |||
| ED25519SignatureFunction() { | |||
| } | |||
| @Override | |||
| @@ -38,12 +44,14 @@ public class ED25519SignatureFunction implements SignatureFunction { | |||
| byte[] rawPrivKeyBytes = privKey.getRawKeyBytes(); | |||
| // 验证原始私钥长度为256比特,即32字节 | |||
| if (rawPrivKeyBytes.length != PRIVKEY_SIZE) | |||
| throw new IllegalArgumentException("This key has wrong format!"); | |||
| if (rawPrivKeyBytes.length != PRIVKEY_SIZE) { | |||
| throw new CryptoException("This key has wrong format!"); | |||
| } | |||
| // 验证密钥数据的算法标识对应ED25519签名算法 | |||
| if (privKey.getAlgorithm() != ED25519) | |||
| throw new IllegalArgumentException("This key is not ED25519 private key!"); | |||
| if (privKey.getAlgorithm().code() != ED25519.code()) { | |||
| throw new CryptoException("This key is not ED25519 private key!"); | |||
| } | |||
| // 调用ED25519签名算法计算签名结果 | |||
| return new SignatureDigest(ED25519, Ed25519Utils.sign_512(data, rawPrivKeyBytes)); | |||
| @@ -56,16 +64,19 @@ public class ED25519SignatureFunction implements SignatureFunction { | |||
| byte[] rawDigestBytes = digest.getRawDigest(); | |||
| // 验证原始公钥长度为256比特,即32字节 | |||
| if (rawPubKeyBytes.length != PUBKEY_SIZE) | |||
| throw new IllegalArgumentException("This key has wrong format!"); | |||
| if (rawPubKeyBytes.length != PUBKEY_SIZE) { | |||
| throw new CryptoException("This key has wrong format!"); | |||
| } | |||
| // 验证密钥数据的算法标识对应ED25519签名算法 | |||
| if (pubKey.getAlgorithm() != ED25519) | |||
| throw new IllegalArgumentException("This key is not ED25519 public key!"); | |||
| if (pubKey.getAlgorithm().code() != ED25519.code()) { | |||
| throw new CryptoException("This key is not ED25519 public key!"); | |||
| } | |||
| // 验证密文数据的算法标识对应ED25519签名算法,并且原始摘要长度为64字节 | |||
| if (digest.getAlgorithm() != ED25519 || rawDigestBytes.length != DIGEST_SIZE) | |||
| throw new IllegalArgumentException("This is not ED25519 signature digest!"); | |||
| if (digest.getAlgorithm().code() != ED25519.code() || rawDigestBytes.length != SIGNATUREDIGEST_SIZE) { | |||
| throw new CryptoException("This is not ED25519 signature digest!"); | |||
| } | |||
| // 调用ED25519验签算法验证签名结果 | |||
| return Ed25519Utils.verify(data, rawPubKeyBytes, rawDigestBytes); | |||
| @@ -78,13 +89,14 @@ public class ED25519SignatureFunction implements SignatureFunction { | |||
| 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(); | |||
| return new PubKey(ED25519, rawPubKeyBytes).toBytes(); | |||
| } | |||
| @Override | |||
| public boolean supportPrivKey(byte[] privKeyBytes) { | |||
| // 验证输入字节数组长度=算法标识长度+密钥类型长度+密钥长度,密钥数据的算法标识对应ED25519签名算法,并且密钥类型是私钥 | |||
| return privKeyBytes.length == PRIVKEY_LENGTH && privKeyBytes[0] == ED25519.CODE && privKeyBytes[1] == PRIV_KEY.CODE; | |||
| return privKeyBytes.length == PRIVKEY_LENGTH && CryptoAlgorithm.match(ED25519, privKeyBytes) | |||
| && privKeyBytes[ALGORYTHM_CODE_SIZE] == PRIV_KEY.CODE; | |||
| } | |||
| @Override | |||
| @@ -96,7 +108,8 @@ public class ED25519SignatureFunction implements SignatureFunction { | |||
| @Override | |||
| public boolean supportPubKey(byte[] pubKeyBytes) { | |||
| // 验证输入字节数组长度=算法标识长度+密钥类型长度+密钥长度,密钥数据的算法标识对应ED25519签名算法,并且密钥类型是公钥 | |||
| return pubKeyBytes.length == PUBKEY_LENGTH && pubKeyBytes[0] == ED25519.CODE && pubKeyBytes[1] == PUB_KEY.CODE; | |||
| return pubKeyBytes.length == PUBKEY_LENGTH && CryptoAlgorithm.match(ED25519, pubKeyBytes) | |||
| && pubKeyBytes[ALGORYTHM_CODE_SIZE] == PUB_KEY.CODE; | |||
| } | |||
| @@ -109,7 +122,7 @@ public class ED25519SignatureFunction implements SignatureFunction { | |||
| @Override | |||
| public boolean supportDigest(byte[] digestBytes) { | |||
| // 验证输入字节数组长度=算法标识长度+摘要长度,字节数组的算法标识对应ED25519算法 | |||
| return digestBytes.length == SIGNATUREDIGEST_LENGTH && digestBytes[0] == ED25519.CODE; | |||
| return digestBytes.length == SIGNATUREDIGEST_LENGTH && CryptoAlgorithm.match(ED25519, digestBytes); | |||
| } | |||
| @Override | |||
| @@ -0,0 +1,54 @@ | |||
| package com.jd.blockchain.crypto.service.classic; | |||
| import java.security.SecureRandom; | |||
| import com.jd.blockchain.crypto.CryptoAlgorithm; | |||
| import com.jd.blockchain.crypto.RandomFunction; | |||
| import com.jd.blockchain.crypto.RandomGenerator; | |||
| public class JVMSecureRandomFunction implements RandomFunction { | |||
| private static final CryptoAlgorithm JVM_SECURE_RANDOM = ClassicCryptoService.JVM_SECURE_RANDOM_ALGORITHM; | |||
| JVMSecureRandomFunction() { | |||
| } | |||
| @Override | |||
| public CryptoAlgorithm getAlgorithm() { | |||
| return JVM_SECURE_RANDOM; | |||
| } | |||
| @Override | |||
| public RandomGenerator generate(byte[] seed) { | |||
| return new SecureRandomGenerator(seed); | |||
| } | |||
| private static class SecureRandomGenerator implements RandomGenerator{ | |||
| private SecureRandom sr; | |||
| public SecureRandomGenerator(byte[] seed) { | |||
| if (seed == null || seed.length == 0) { | |||
| // 随机; | |||
| sr = new SecureRandom(); | |||
| } else { | |||
| sr = new SecureRandom(seed); | |||
| } | |||
| } | |||
| @Override | |||
| public byte[] nextBytes(int size) { | |||
| byte[] randomBytes = new byte[size]; | |||
| sr.nextBytes(randomBytes); | |||
| return randomBytes; | |||
| } | |||
| @Override | |||
| public void nextBytes(byte[] buffer) { | |||
| sr.nextBytes(buffer); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,20 +1,25 @@ | |||
| package com.jd.blockchain.crypto.impl.def.hash; | |||
| package com.jd.blockchain.crypto.service.classic; | |||
| import static com.jd.blockchain.crypto.CryptoAlgorithm.RIPEMD160; | |||
| import static com.jd.blockchain.crypto.CryptoBytes.ALGORYTHM_BYTES; | |||
| import static com.jd.blockchain.crypto.CryptoBytes.ALGORYTHM_CODE_SIZE; | |||
| import java.util.Arrays; | |||
| import com.jd.blockchain.crypto.CryptoAlgorithm; | |||
| import com.jd.blockchain.crypto.CryptoException; | |||
| import com.jd.blockchain.crypto.hash.HashDigest; | |||
| import com.jd.blockchain.crypto.hash.HashFunction; | |||
| import com.jd.blockchain.utils.security.RipeMD160Utils; | |||
| public class RIPEMD160HashFunction implements HashFunction { | |||
| private static final CryptoAlgorithm RIPEMD160 = ClassicCryptoService.RIPEMD160_ALGORITHM; | |||
| private static final int DIGEST_BYTES = 160 / 8; | |||
| private static final int DIGEST_LENGTH = ALGORYTHM_BYTES + DIGEST_BYTES; | |||
| private static final int DIGEST_LENGTH = ALGORYTHM_CODE_SIZE + DIGEST_BYTES; | |||
| RIPEMD160HashFunction() { | |||
| } | |||
| @Override | |||
| public CryptoAlgorithm getAlgorithm() { | |||
| @@ -23,6 +28,11 @@ public class RIPEMD160HashFunction implements HashFunction { | |||
| @Override | |||
| public HashDigest hash(byte[] data) { | |||
| if (data == null) { | |||
| throw new CryptoException("The input is null!"); | |||
| } | |||
| byte[] digestBytes = RipeMD160Utils.hash(data); | |||
| return new HashDigest(RIPEMD160, digestBytes); | |||
| } | |||
| @@ -36,7 +46,7 @@ public class RIPEMD160HashFunction implements HashFunction { | |||
| @Override | |||
| public boolean supportHashDigest(byte[] digestBytes) { | |||
| // 验证输入字节数组长度=算法标识长度+摘要长度,以及算法标识; | |||
| return RIPEMD160.CODE == digestBytes[0] && DIGEST_LENGTH == digestBytes.length; | |||
| return DIGEST_LENGTH == digestBytes.length && CryptoAlgorithm.match(RIPEMD160, digestBytes); | |||
| } | |||
| @Override | |||
| @@ -1,9 +1,27 @@ | |||
| package com.jd.blockchain.crypto.impl.def.asymmetric; | |||
| package com.jd.blockchain.crypto.service.classic; | |||
| import com.jd.blockchain.crypto.Ciphertext; | |||
| import com.jd.blockchain.crypto.CryptoAlgorithm; | |||
| import com.jd.blockchain.crypto.PrivKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.crypto.asymmetric.*; | |||
| public class ECDSASignatureFunction implements SignatureFunction { | |||
| /** | |||
| * @author zhanglin33 | |||
| * @title: RSACryptoFunction | |||
| * @description: Interfaces for RSA crypto functions, including key generation, encryption, signature, and so on | |||
| * @date 2019-03-25, 17:28 | |||
| */ | |||
| public class RSACryptoFunction implements AsymmetricEncryptionFunction, SignatureFunction { | |||
| @Override | |||
| public Ciphertext encrypt(PubKey pubKey, byte[] data) { | |||
| return null; | |||
| } | |||
| @Override | |||
| public byte[] decrypt(PrivKey privKey, Ciphertext ciphertext) { | |||
| return new byte[0]; | |||
| } | |||
| @Override | |||
| public SignatureDigest sign(PrivKey privKey, byte[] data) { | |||
| @@ -50,9 +68,19 @@ public class ECDSASignatureFunction implements SignatureFunction { | |||
| return null; | |||
| } | |||
| @Override | |||
| public boolean supportCiphertext(byte[] ciphertextBytes) { | |||
| return false; | |||
| } | |||
| @Override | |||
| public AsymmetricCiphertext resolveCiphertext(byte[] ciphertextBytes) { | |||
| return null; | |||
| } | |||
| @Override | |||
| public CryptoAlgorithm getAlgorithm() { | |||
| return CryptoAlgorithm.ECDSA; | |||
| return null; | |||
| } | |||
| @Override | |||
| @@ -1,20 +1,25 @@ | |||
| package com.jd.blockchain.crypto.impl.def.hash; | |||
| package com.jd.blockchain.crypto.service.classic; | |||
| import static com.jd.blockchain.crypto.CryptoAlgorithm.SHA256; | |||
| import static com.jd.blockchain.crypto.CryptoBytes.ALGORYTHM_BYTES; | |||
| import static com.jd.blockchain.crypto.CryptoBytes.ALGORYTHM_CODE_SIZE; | |||
| import java.util.Arrays; | |||
| import com.jd.blockchain.crypto.CryptoAlgorithm; | |||
| import com.jd.blockchain.crypto.CryptoException; | |||
| import com.jd.blockchain.crypto.hash.HashDigest; | |||
| import com.jd.blockchain.crypto.hash.HashFunction; | |||
| import com.jd.blockchain.utils.security.ShaUtils; | |||
| public class SHA256HashFunction implements HashFunction { | |||
| private static final CryptoAlgorithm SHA256 = ClassicCryptoService.SHA256_ALGORITHM; | |||
| private static final int DIGEST_BYTES = 256 / 8; | |||
| private static final int DIGEST_LENGTH = ALGORYTHM_BYTES + DIGEST_BYTES; | |||
| private static final int DIGEST_LENGTH = ALGORYTHM_CODE_SIZE + DIGEST_BYTES; | |||
| SHA256HashFunction() { | |||
| } | |||
| @Override | |||
| public CryptoAlgorithm getAlgorithm() { | |||
| @@ -23,6 +28,11 @@ public class SHA256HashFunction implements HashFunction { | |||
| @Override | |||
| public HashDigest hash(byte[] data) { | |||
| if (data == null) { | |||
| throw new CryptoException("The input is null!"); | |||
| } | |||
| byte[] digestBytes = ShaUtils.hash_256(data); | |||
| return new HashDigest(SHA256, digestBytes); | |||
| } | |||
| @@ -36,7 +46,7 @@ public class SHA256HashFunction implements HashFunction { | |||
| @Override | |||
| public boolean supportHashDigest(byte[] digestBytes) { | |||
| // 验证输入字节数组长度=算法标识长度+摘要长度,以及算法标识; | |||
| return SHA256.CODE == digestBytes[0] && DIGEST_LENGTH == digestBytes.length; | |||
| return DIGEST_LENGTH == digestBytes.length && CryptoAlgorithm.match(SHA256, digestBytes); | |||
| } | |||
| @Override | |||
| @@ -46,4 +56,3 @@ public class SHA256HashFunction implements HashFunction { | |||
| } | |||
| } | |||
| @@ -0,0 +1,10 @@ | |||
| package com.jd.blockchain.crypto.utils.classic; | |||
| /** | |||
| * @author zhanglin33 | |||
| * @title: ECDSAUtils | |||
| * @description: ECDSA signature algorithm | |||
| * @date 2019-03-25, 17:21 | |||
| */ | |||
| public class ECDSAUtils { | |||
| } | |||
| @@ -0,0 +1,10 @@ | |||
| package com.jd.blockchain.crypto.utils.classic; | |||
| /** | |||
| * @author zhanglin33 | |||
| * @title: RSAUtils | |||
| * @description: RSA encryption and signature algorithms | |||
| * @date 2019-03-25, 17:20 | |||
| */ | |||
| public class RSAUtils { | |||
| } | |||
| @@ -0,0 +1 @@ | |||
| com.jd.blockchain.crypto.service.classic.ClassicCryptoService | |||
| @@ -0,0 +1,953 @@ | |||
| //package test.com.jd.blockchain.crypto.asymmetric; | |||
| // | |||
| //import static com.jd.blockchain.crypto.CryptoKeyType.PRIV_KEY; | |||
| //import static com.jd.blockchain.crypto.CryptoKeyType.PUB_KEY; | |||
| //import static org.junit.Assert.assertArrayEquals; | |||
| //import static org.junit.Assert.assertEquals; | |||
| //import static org.junit.Assert.assertNotNull; | |||
| //import static org.junit.Assert.assertNull; | |||
| //import static org.junit.Assert.assertTrue; | |||
| // | |||
| //import java.util.Random; | |||
| // | |||
| //import org.junit.Test; | |||
| // | |||
| //import com.jd.blockchain.crypto.Ciphertext; | |||
| //import com.jd.blockchain.crypto.CryptoAlgorithm; | |||
| //import com.jd.blockchain.crypto.CryptoException; | |||
| //import com.jd.blockchain.crypto.CryptoKeyType; | |||
| //import com.jd.blockchain.crypto.PrivKey; | |||
| //import com.jd.blockchain.crypto.PubKey; | |||
| //import com.jd.blockchain.crypto.asymmetric.AsymmetricCryptography; | |||
| //import com.jd.blockchain.crypto.asymmetric.AsymmetricEncryptionFunction; | |||
| //import com.jd.blockchain.crypto.asymmetric.CryptoKeyPair; | |||
| //import com.jd.blockchain.crypto.asymmetric.SignatureDigest; | |||
| //import com.jd.blockchain.crypto.asymmetric.SignatureFunction; | |||
| //import com.jd.blockchain.crypto.impl.AsymmtricCryptographyImpl; | |||
| //import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; | |||
| //import com.jd.blockchain.utils.io.BytesUtils; | |||
| // | |||
| //public class AsymmtricCryptographyImplTest { | |||
| // | |||
| // @Test | |||
| // public void testGenerateKeyPair() { | |||
| // | |||
| // //test ED25519 | |||
| // CryptoAlgorithm algorithm = ClassicCryptoService.ED25519.getAlgorithm(); | |||
| // CryptoKeyPair keyPair = ClassicCryptoService.ED25519.generateKeyPair(); | |||
| // | |||
| // PubKey pubKey = keyPair.getPubKey(); | |||
| // PrivKey privKey = keyPair.getPrivKey(); | |||
| // | |||
| // assertNotNull(pubKey); | |||
| // assertNotNull(privKey); | |||
| // | |||
| // assertEquals(ClassicCryptoService.ED25519.getAlgorithm().code(),pubKey.getAlgorithm().code()); | |||
| // assertEquals(ClassicCryptoService.ED25519.getAlgorithm().code(),privKey.getAlgorithm().code()); | |||
| // | |||
| // assertEquals(32,pubKey.getRawKeyBytes().length); | |||
| // assertEquals(32,privKey.getRawKeyBytes().length); | |||
| // | |||
| // byte[] pubKeyBytes = pubKey.toBytes(); | |||
| // byte[] privKeyBytes = privKey.toBytes(); | |||
| // | |||
| // assertEquals(32+1+1,pubKeyBytes.length); | |||
| // assertEquals(32+1+1,privKeyBytes.length); | |||
| // | |||
| // byte[] algorithmBytes = CryptoAlgorithm.toBytes(ClassicCryptoService.ED25519.getAlgorithm()); | |||
| // assertEquals(algorithmBytes[0],pubKeyBytes[0]); | |||
| // assertEquals(algorithmBytes[1],pubKeyBytes[1]); | |||
| // assertEquals(algorithmBytes[0],privKeyBytes[0]); | |||
| // assertEquals(algorithmBytes[1],privKeyBytes[1]); | |||
| // | |||
| // assertEquals(pubKey.getKeyType().CODE,pubKeyBytes[CryptoAlgorithm.CODE_SIZE]); | |||
| // assertEquals(privKey.getKeyType().CODE,privKeyBytes[CryptoAlgorithm.CODE_SIZE]); | |||
| // | |||
| // | |||
| // //test SM2 | |||
| // algorithm = CryptoAlgorithm.SM2; | |||
| // keyPair = asymmetricCrypto.generateKeyPair(algorithm); | |||
| // | |||
| // assertNotNull(keyPair); | |||
| // | |||
| // pubKey = keyPair.getPubKey(); | |||
| // privKey = keyPair.getPrivKey(); | |||
| // | |||
| // assertNotNull(pubKey); | |||
| // assertNotNull(privKey); | |||
| // | |||
| // assertEquals(algorithm,pubKey.getAlgorithm()); | |||
| // assertEquals(algorithm,privKey.getAlgorithm()); | |||
| // | |||
| // assertEquals(65,pubKey.getRawKeyBytes().length); | |||
| // assertEquals(32,privKey.getRawKeyBytes().length); | |||
| // | |||
| // pubKeyBytes = pubKey.toBytes(); | |||
| // privKeyBytes = privKey.toBytes(); | |||
| // | |||
| // assertEquals(32+1+1,privKeyBytes.length); | |||
| // assertEquals(65+1+1,pubKeyBytes.length); | |||
| // | |||
| // assertEquals(CryptoAlgorithm.SM2.CODE,pubKeyBytes[0]); | |||
| // assertEquals(CryptoAlgorithm.SM2.CODE,privKeyBytes[0]); | |||
| // assertEquals(CryptoAlgorithm.SM2, CryptoAlgorithm.valueOf(pubKey.getAlgorithm().CODE)); | |||
| // assertEquals(CryptoAlgorithm.SM2, CryptoAlgorithm.valueOf(privKey.getAlgorithm().CODE)); | |||
| // | |||
| // assertEquals(pubKey.getKeyType().CODE,pubKeyBytes[1]); | |||
| // assertEquals(privKey.getKeyType().CODE,privKeyBytes[1]); | |||
| // | |||
| // | |||
| // //test JNIED25519 | |||
| // algorithm = CryptoAlgorithm.JNIED25519; | |||
| // keyPair = asymmetricCrypto.generateKeyPair(algorithm); | |||
| // | |||
| // assertNotNull(keyPair); | |||
| // | |||
| // pubKey = keyPair.getPubKey(); | |||
| // privKey = keyPair.getPrivKey(); | |||
| // | |||
| // assertNotNull(pubKey); | |||
| // assertNotNull(privKey); | |||
| // | |||
| // assertEquals(algorithm,pubKey.getAlgorithm()); | |||
| // assertEquals(algorithm,privKey.getAlgorithm()); | |||
| // | |||
| // assertEquals(32,pubKey.getRawKeyBytes().length); | |||
| // assertEquals(32,privKey.getRawKeyBytes().length); | |||
| // | |||
| // pubKeyBytes = pubKey.toBytes(); | |||
| // privKeyBytes = privKey.toBytes(); | |||
| // | |||
| // assertEquals(32+1+1,pubKeyBytes.length); | |||
| // assertEquals(32+1+1,privKeyBytes.length); | |||
| // | |||
| // assertEquals(CryptoAlgorithm.JNIED25519.CODE,pubKeyBytes[0]); | |||
| // assertEquals(CryptoAlgorithm.JNIED25519.CODE,privKeyBytes[0]); | |||
| // assertEquals(CryptoAlgorithm.JNIED25519, CryptoAlgorithm.valueOf(pubKey.getAlgorithm().CODE)); | |||
| // assertEquals(CryptoAlgorithm.JNIED25519, CryptoAlgorithm.valueOf(privKey.getAlgorithm().CODE)); | |||
| // | |||
| // assertEquals(pubKey.getKeyType().CODE,pubKeyBytes[1]); | |||
| // assertEquals(privKey.getKeyType().CODE,privKeyBytes[1]); | |||
| // } | |||
| // | |||
| // @Test | |||
| // public void testGetSignatureFunction() { | |||
| // | |||
| // AsymmetricCryptography asymmetricCrypto = new AsymmtricCryptographyImpl(); | |||
| // Random random = new Random(); | |||
| // | |||
| // | |||
| // //test ED25519 | |||
| // CryptoAlgorithm algorithm = CryptoAlgorithm.ED25519; | |||
| // | |||
| // // 测试256字节的消息进行签名 | |||
| // byte[] data = new byte[256]; | |||
| // random.nextBytes(data); | |||
| // verifyGetSignatureFunction(asymmetricCrypto,algorithm,data,32,32,64,null); | |||
| // | |||
| // //错误的算法标识 | |||
| // verifyGetSignatureFunction(asymmetricCrypto,CryptoAlgorithm.AES,data,32,32,64,IllegalArgumentException.class); | |||
| // | |||
| // data = null; | |||
| // verifyGetSignatureFunction(asymmetricCrypto,algorithm,data,32,32,64,NullPointerException.class); | |||
| // | |||
| // | |||
| // //test SM2 | |||
| // algorithm = CryptoAlgorithm.SM2; | |||
| // | |||
| // // 测试256字节的消息进行签名 | |||
| // data = new byte[256]; | |||
| // random.nextBytes(data); | |||
| // verifyGetSignatureFunction(asymmetricCrypto,algorithm,data,65,32,64,null); | |||
| // | |||
| // //错误的算法标识 | |||
| // verifyGetSignatureFunction(asymmetricCrypto,CryptoAlgorithm.AES,data,65,32,64,IllegalArgumentException.class); | |||
| // | |||
| // data = null; | |||
| // verifyGetSignatureFunction(asymmetricCrypto,algorithm,data,65,32,64,NullPointerException.class); | |||
| // | |||
| // | |||
| // //test JNNIED25519 | |||
| // algorithm = CryptoAlgorithm.JNIED25519; | |||
| // | |||
| // // 测试256字节的消息进行签名 | |||
| // data = new byte[256]; | |||
| // random.nextBytes(data); | |||
| // verifyGetSignatureFunction(asymmetricCrypto,algorithm,data,32,32,64,null); | |||
| // | |||
| // //错误的算法标识 | |||
| // verifyGetSignatureFunction(asymmetricCrypto,CryptoAlgorithm.AES,data,32,32,64,IllegalArgumentException.class); | |||
| // | |||
| // data = null; | |||
| // verifyGetSignatureFunction(asymmetricCrypto,algorithm,data,32,32,64,IllegalArgumentException.class); | |||
| // } | |||
| // | |||
| // private void verifyGetSignatureFunction(AsymmetricCryptography asymmetricCrypto, CryptoAlgorithm algorithm, byte[] data, | |||
| // int expectedPubKeyLength, int expectedPrivKeyLength, | |||
| // int expectedSignatureDigestLength, Class<?> expectedException){ | |||
| // | |||
| // //初始化一个异常 | |||
| // Exception actualEx = null; | |||
| // | |||
| // try { | |||
| // SignatureFunction sf = asymmetricCrypto.getSignatureFunction(algorithm); | |||
| // | |||
| // assertNotNull(sf); | |||
| // | |||
| // CryptoKeyPair keyPair = sf.generateKeyPair(); | |||
| // PubKey pubKey = keyPair.getPubKey(); | |||
| // PrivKey privKey = keyPair.getPrivKey(); | |||
| // byte[] rawPubKeyBytes = pubKey.getRawKeyBytes(); | |||
| // byte[] rawPrivKeyBytes = privKey.getRawKeyBytes(); | |||
| // byte[] pubKeyBytes = pubKey.toBytes(); | |||
| // byte[] privKeyBytes = privKey.toBytes(); | |||
| // | |||
| // assertEquals(algorithm, pubKey.getAlgorithm()); | |||
| // assertEquals(algorithm, privKey.getAlgorithm()); | |||
| // assertEquals(expectedPubKeyLength,rawPubKeyBytes.length); | |||
| // assertEquals(expectedPrivKeyLength,rawPrivKeyBytes.length); | |||
| // | |||
| // assertArrayEquals(BytesUtils.concat(new byte[]{algorithm.CODE},new byte[]{CryptoKeyType.PUB_KEY.CODE},rawPubKeyBytes), pubKeyBytes); | |||
| // assertArrayEquals(BytesUtils.concat(new byte[]{algorithm.CODE},new byte[]{CryptoKeyType.PRIV_KEY.CODE},rawPrivKeyBytes), privKeyBytes); | |||
| // | |||
| // SignatureDigest signatureDigest = sf.sign(privKey,data); | |||
| // byte[] rawDigest = signatureDigest.getRawDigest(); | |||
| // | |||
| // assertEquals(algorithm,signatureDigest.getAlgorithm()); | |||
| // assertEquals(expectedSignatureDigestLength,rawDigest.length); | |||
| // byte[] signatureDigestBytes = signatureDigest.toBytes(); | |||
| // assertArrayEquals(BytesUtils.concat(new byte[]{algorithm.CODE},rawDigest),signatureDigestBytes); | |||
| // | |||
| // assertTrue(signatureDigest.equals(signatureDigest)); | |||
| // assertEquals(signatureDigest.hashCode(),signatureDigest.hashCode()); | |||
| // | |||
| // assertTrue(sf.verify(signatureDigest,pubKey,data)); | |||
| // | |||
| // assertTrue(sf.supportPubKey(pubKeyBytes)); | |||
| // assertTrue(sf.supportPrivKey(privKeyBytes)); | |||
| // assertTrue(sf.supportDigest(signatureDigestBytes)); | |||
| // | |||
| // assertEquals(pubKey,sf.resolvePubKey(pubKeyBytes)); | |||
| // assertEquals(privKey,sf.resolvePrivKey(privKeyBytes)); | |||
| // assertEquals(signatureDigest,sf.resolveDigest(signatureDigestBytes)); | |||
| // | |||
| // assertEquals(algorithm,sf.getAlgorithm()); | |||
| // | |||
| // } catch (Exception e){ | |||
| // actualEx = e; | |||
| // } | |||
| // | |||
| // if (expectedException == null) { | |||
| // assertNull(actualEx); | |||
| // } | |||
| // else { | |||
| // assertNotNull(actualEx); | |||
| // assertTrue(expectedException.isAssignableFrom(actualEx.getClass())); | |||
| // } | |||
| // } | |||
| // | |||
| // @Test | |||
| // public void testVerify() { | |||
| // | |||
| // AsymmetricCryptography asymmetricCrypto = new AsymmtricCryptographyImpl(); | |||
| // Random randomData = new Random(); | |||
| // | |||
| // //test ED25519 | |||
| // CryptoAlgorithm algorithm = CryptoAlgorithm.ED25519; | |||
| // | |||
| // // 测试256字节的消息进行签名 | |||
| // byte[] data = new byte[256]; | |||
| // randomData.nextBytes(data); | |||
| // SignatureFunction sf = asymmetricCrypto.getSignatureFunction(algorithm); | |||
| // CryptoKeyPair keyPair = sf.generateKeyPair(); | |||
| // byte[] pubKeyBytes = keyPair.getPubKey().toBytes(); | |||
| // | |||
| // byte[] signatureDigestBytes = sf.sign(keyPair.getPrivKey(),data).toBytes(); | |||
| // verifyVerify(asymmetricCrypto,true,data,pubKeyBytes,signatureDigestBytes,null); | |||
| // | |||
| // //签名数据末尾两个字节丢失情况下,抛出异常 | |||
| // byte[] truncatedSignatureDigestBytes = new byte[signatureDigestBytes.length-2]; | |||
| // System.arraycopy(signatureDigestBytes,0,truncatedSignatureDigestBytes,0,truncatedSignatureDigestBytes.length); | |||
| // verifyVerify(asymmetricCrypto,false,data,pubKeyBytes,truncatedSignatureDigestBytes,IllegalArgumentException.class); | |||
| // | |||
| // byte[] signatureDigestBytesWithWrongAlgCode = signatureDigestBytes; | |||
| // signatureDigestBytesWithWrongAlgCode[0] = CryptoAlgorithm.SHA256.CODE; | |||
| // verifyVerify(asymmetricCrypto,false,data,pubKeyBytes,signatureDigestBytesWithWrongAlgCode,IllegalArgumentException.class); | |||
| // | |||
| // signatureDigestBytes = null; | |||
| // verifyVerify(asymmetricCrypto,false,data,pubKeyBytes,signatureDigestBytes,NullPointerException.class); | |||
| // | |||
| // | |||
| // //test SM2 | |||
| // algorithm = CryptoAlgorithm.SM2; | |||
| // | |||
| // // 测试256字节的消息进行签名 | |||
| // data = new byte[256]; | |||
| // randomData.nextBytes(data); | |||
| // sf = asymmetricCrypto.getSignatureFunction(algorithm); | |||
| // keyPair = sf.generateKeyPair(); | |||
| // pubKeyBytes = keyPair.getPubKey().toBytes(); | |||
| // | |||
| // signatureDigestBytes = sf.sign(keyPair.getPrivKey(),data).toBytes(); | |||
| // verifyVerify(asymmetricCrypto,true,data,pubKeyBytes,signatureDigestBytes,null); | |||
| // | |||
| // //签名数据末尾两个字节丢失情况下,抛出异常 | |||
| // truncatedSignatureDigestBytes = new byte[signatureDigestBytes.length-2]; | |||
| // System.arraycopy(signatureDigestBytes,0,truncatedSignatureDigestBytes,0,truncatedSignatureDigestBytes.length); | |||
| // verifyVerify(asymmetricCrypto,false,data,pubKeyBytes,truncatedSignatureDigestBytes,IllegalArgumentException.class); | |||
| // | |||
| // signatureDigestBytesWithWrongAlgCode = signatureDigestBytes; | |||
| // signatureDigestBytesWithWrongAlgCode[0] = CryptoAlgorithm.SHA256.CODE; | |||
| // verifyVerify(asymmetricCrypto,false,data,pubKeyBytes,signatureDigestBytesWithWrongAlgCode,IllegalArgumentException.class); | |||
| // | |||
| // signatureDigestBytes = null; | |||
| // verifyVerify(asymmetricCrypto,false,data,pubKeyBytes,signatureDigestBytes,NullPointerException.class); | |||
| // | |||
| // //test JNIED25519 | |||
| // algorithm = CryptoAlgorithm.JNIED25519; | |||
| // | |||
| // // 测试256字节的消息进行签名 | |||
| // data = new byte[256]; | |||
| // randomData.nextBytes(data); | |||
| // sf = asymmetricCrypto.getSignatureFunction(algorithm); | |||
| // keyPair = sf.generateKeyPair(); | |||
| // pubKeyBytes = keyPair.getPubKey().toBytes(); | |||
| // | |||
| // signatureDigestBytes = sf.sign(keyPair.getPrivKey(),data).toBytes(); | |||
| // verifyVerify(asymmetricCrypto,true,data,pubKeyBytes,signatureDigestBytes,null); | |||
| // | |||
| // //签名数据末尾两个字节丢失情况下,抛出异常 | |||
| // truncatedSignatureDigestBytes = new byte[signatureDigestBytes.length-2]; | |||
| // System.arraycopy(signatureDigestBytes,0,truncatedSignatureDigestBytes,0,truncatedSignatureDigestBytes.length); | |||
| // verifyVerify(asymmetricCrypto,false,data,pubKeyBytes,truncatedSignatureDigestBytes,IllegalArgumentException.class); | |||
| // | |||
| // signatureDigestBytesWithWrongAlgCode = signatureDigestBytes; | |||
| // signatureDigestBytesWithWrongAlgCode[0] = CryptoAlgorithm.SHA256.CODE; | |||
| // verifyVerify(asymmetricCrypto,false,data,pubKeyBytes,signatureDigestBytesWithWrongAlgCode,IllegalArgumentException.class); | |||
| // | |||
| // signatureDigestBytes = null; | |||
| // verifyVerify(asymmetricCrypto,false,data,pubKeyBytes,signatureDigestBytes,NullPointerException.class); | |||
| // } | |||
| // | |||
| // private void verifyVerify(AsymmetricCryptography asymmetricCrypto,boolean expectedResult,byte[] data, | |||
| // byte[] pubKeyBytes, byte[] signatureDigestBytes, Class<?> expectedException){ | |||
| // | |||
| // //初始化一个异常 | |||
| // Exception actualEx = null; | |||
| // boolean pass = false; | |||
| // | |||
| // try { | |||
| // | |||
| // pass = asymmetricCrypto.verify(signatureDigestBytes,pubKeyBytes,data); | |||
| // | |||
| // } | |||
| // catch (Exception e){ | |||
| // actualEx = e; | |||
| // } | |||
| // | |||
| // assertEquals(expectedResult, pass); | |||
| // | |||
| // if (expectedException == null) { | |||
| // assertNull(actualEx); | |||
| // } | |||
| // else { | |||
| // assertNotNull(actualEx); | |||
| // assertTrue(expectedException.isAssignableFrom(actualEx.getClass())); | |||
| // } | |||
| // } | |||
| // | |||
| // @Test | |||
| // public void testGetAsymmetricEncryptionFunction() { | |||
| // | |||
| // AsymmetricCryptography asymmetricCrypto = new AsymmtricCryptographyImpl(); | |||
| // Random random = new Random(); | |||
| // | |||
| // | |||
| // //test SM2 | |||
| // CryptoAlgorithm algorithm = CryptoAlgorithm.SM2; | |||
| // | |||
| // //Case 1: SM2Encryption with 16 bytes data | |||
| // byte[] data = new byte[16]; | |||
| // random.nextBytes(data); | |||
| // verifyGetAsymmetricEncryptionFunction(asymmetricCrypto, algorithm,65,32,65+16+32,data,null); | |||
| // | |||
| // //Case 2: SM2Encryption with 256 bytes data | |||
| // data = new byte[256]; | |||
| // random.nextBytes(data); | |||
| // verifyGetAsymmetricEncryptionFunction(asymmetricCrypto, algorithm,65,32,65+256+32,data,null); | |||
| // | |||
| // //Case 3: SM2Encryption with 1 bytes data | |||
| // data = new byte[3]; | |||
| // random.nextBytes(data); | |||
| // verifyGetAsymmetricEncryptionFunction(asymmetricCrypto, algorithm,65,32,65+3+32,data,null); | |||
| // | |||
| // //Case 4: SM2Encryption with wrong algorithm | |||
| // verifyGetAsymmetricEncryptionFunction(asymmetricCrypto,CryptoAlgorithm.AES,65,32,65+3+32,data,IllegalArgumentException.class); | |||
| // | |||
| // //Case 5: SM2Encryption with null data | |||
| // data = null; | |||
| // verifyGetAsymmetricEncryptionFunction(asymmetricCrypto,algorithm,65,32,65+32,data,NullPointerException.class); | |||
| // } | |||
| // | |||
| // private void verifyGetAsymmetricEncryptionFunction(AsymmetricCryptography asymmetricCrypto, CryptoAlgorithm algorithm, | |||
| // int expectedPubKeyLength, int expectedPrivKeyLength, | |||
| // int expectedCiphertextLength, byte[] data, Class<?> expectedException){ | |||
| // | |||
| // //初始化一个异常 | |||
| // Exception actualEx = null; | |||
| // | |||
| // try { | |||
| // AsymmetricEncryptionFunction aef = asymmetricCrypto.getAsymmetricEncryptionFunction(algorithm); | |||
| // //验证获取的算法实例非空 | |||
| // assertNotNull(aef); | |||
| // | |||
| // CryptoKeyPair keyPair = aef.generateKeyPair(); | |||
| // PubKey pubKey = keyPair.getPubKey(); | |||
| // PrivKey privKey = keyPair.getPrivKey(); | |||
| // byte[] rawPubKeyBytes = pubKey.getRawKeyBytes(); | |||
| // byte[] rawPrivKeyBytes = privKey.getRawKeyBytes(); | |||
| // byte[] pubKeyBytes = pubKey.toBytes(); | |||
| // byte[] privKeyBytes = privKey.toBytes(); | |||
| // | |||
| // assertEquals(algorithm, pubKey.getAlgorithm()); | |||
| // assertEquals(algorithm, privKey.getAlgorithm()); | |||
| // assertEquals(expectedPubKeyLength,rawPubKeyBytes.length); | |||
| // assertEquals(expectedPrivKeyLength,rawPrivKeyBytes.length); | |||
| // | |||
| // assertArrayEquals(BytesUtils.concat(new byte[]{algorithm.CODE},new byte[]{CryptoKeyType.PUB_KEY.CODE},rawPubKeyBytes), pubKeyBytes); | |||
| // assertArrayEquals(BytesUtils.concat(new byte[]{algorithm.CODE},new byte[]{CryptoKeyType.PRIV_KEY.CODE},rawPrivKeyBytes), privKeyBytes); | |||
| // | |||
| // Ciphertext ciphertext = aef.encrypt(pubKey,data); | |||
| // byte[] rawCiphertextBytes = ciphertext.getRawCiphertext(); | |||
| // | |||
| // assertEquals(algorithm,ciphertext.getAlgorithm()); | |||
| // assertEquals(expectedCiphertextLength,rawCiphertextBytes.length); | |||
| // byte[] ciphertextBytes = ciphertext.toBytes(); | |||
| // assertArrayEquals(BytesUtils.concat(new byte[]{algorithm.CODE},rawCiphertextBytes),ciphertextBytes); | |||
| // | |||
| // assertArrayEquals(data,aef.decrypt(privKey,ciphertext)); | |||
| // | |||
| // assertTrue(aef.supportPubKey(pubKeyBytes)); | |||
| // assertTrue(aef.supportPrivKey(privKeyBytes)); | |||
| // assertTrue(aef.supportCiphertext(ciphertextBytes)); | |||
| // | |||
| // assertEquals(pubKey,aef.resolvePubKey(pubKeyBytes)); | |||
| // assertEquals(privKey,aef.resolvePrivKey(privKeyBytes)); | |||
| // assertEquals(ciphertext,aef.resolveCiphertext(ciphertextBytes)); | |||
| // | |||
| // assertEquals(algorithm,aef.getAlgorithm()); | |||
| // | |||
| // | |||
| // }catch (Exception e){ | |||
| // actualEx = e; | |||
| // } | |||
| // | |||
| // if(expectedException == null){ | |||
| // assertNull(actualEx); | |||
| // } | |||
| // else { | |||
| // assertNotNull(actualEx); | |||
| // assertTrue(expectedException.isAssignableFrom(actualEx.getClass())); | |||
| // } | |||
| // } | |||
| // | |||
| // @Test | |||
| // public void testDecrypt() { | |||
| // | |||
| // AsymmetricCryptography asymmetricCrypto = new AsymmtricCryptographyImpl(); | |||
| // Random random = new Random(); | |||
| // | |||
| // byte[] data = new byte[16]; | |||
| // random.nextBytes(data); | |||
| // | |||
| // //test SM2 | |||
| // CryptoAlgorithm algorithm = CryptoAlgorithm.SM2; | |||
| // AsymmetricEncryptionFunction aef = asymmetricCrypto.getAsymmetricEncryptionFunction(algorithm); | |||
| // CryptoKeyPair keyPair = aef.generateKeyPair(); | |||
| // PubKey pubKey = keyPair.getPubKey(); | |||
| // PrivKey privKey = keyPair.getPrivKey(); | |||
| // byte[] rawPrivKeyBytes = privKey.getRawKeyBytes(); | |||
| // Ciphertext ciphertext = aef.encrypt(pubKey,data); | |||
| // byte[] ciphertextBytes = ciphertext.toBytes(); | |||
| // | |||
| // verifyDecrypt(asymmetricCrypto, algorithm, rawPrivKeyBytes, data, ciphertextBytes, null); | |||
| // | |||
| // //密钥的算法标识与密文的算法标识不一致情况 | |||
| // verifyDecrypt(asymmetricCrypto, CryptoAlgorithm.AES, rawPrivKeyBytes, data, ciphertextBytes, IllegalArgumentException.class); | |||
| // | |||
| // //密文末尾两个字节丢失情况下,抛出异常 | |||
| // byte[] truncatedCiphertextBytes = new byte[ciphertextBytes.length-2]; | |||
| // System.arraycopy(ciphertextBytes,0,truncatedCiphertextBytes,0,truncatedCiphertextBytes.length); | |||
| // verifyDecrypt(asymmetricCrypto, algorithm, rawPrivKeyBytes, data, truncatedCiphertextBytes, com.jd.blockchain.crypto.CryptoException.class); | |||
| // | |||
| // byte[] ciphertextBytesWithWrongAlgCode = ciphertextBytes; | |||
| // ciphertextBytesWithWrongAlgCode[0] = CryptoAlgorithm.SHA256.CODE; | |||
| // verifyDecrypt(asymmetricCrypto,algorithm,rawPrivKeyBytes,data,ciphertextBytesWithWrongAlgCode,IllegalArgumentException.class); | |||
| // | |||
| // ciphertextBytes = null; | |||
| // verifyDecrypt(asymmetricCrypto,algorithm,rawPrivKeyBytes,data,ciphertextBytes,NullPointerException.class); | |||
| // } | |||
| // | |||
| // private void verifyDecrypt(AsymmetricCryptography asymmetricCrypto, CryptoAlgorithm algorithm, | |||
| // byte[] key, byte[] data, byte[] ciphertextBytes, Class<?> expectedException){ | |||
| // Exception actualEx = null; | |||
| // | |||
| // try { | |||
| // PrivKey privKey = new PrivKey(algorithm,key); | |||
| // | |||
| // byte[] plaintext = asymmetricCrypto.decrypt(privKey.toBytes(), ciphertextBytes); | |||
| // | |||
| // //解密后的明文与初始的明文一致 | |||
| // assertArrayEquals(data,plaintext); | |||
| // } | |||
| // catch (Exception e){ | |||
| // actualEx = e; | |||
| // } | |||
| // | |||
| // if (expectedException == null) { | |||
| // assertNull(actualEx); | |||
| // } | |||
| // else { | |||
| // assertNotNull(actualEx); | |||
| // assertTrue(expectedException.isAssignableFrom(actualEx.getClass())); | |||
| // } | |||
| // } | |||
| // | |||
| // @Test | |||
| // public void testResolveCiphertext() { | |||
| // | |||
| // | |||
| // AsymmetricCryptography asymmetricCrypto = new AsymmtricCryptographyImpl(); | |||
| // Random random = new Random(); | |||
| // | |||
| // byte[] data = new byte[16]; | |||
| // random.nextBytes(data); | |||
| // | |||
| // //test SM2 | |||
| // CryptoAlgorithm algorithm = CryptoAlgorithm.SM2; | |||
| // AsymmetricEncryptionFunction aef = asymmetricCrypto.getAsymmetricEncryptionFunction(algorithm); | |||
| // CryptoKeyPair keyPair = aef.generateKeyPair(); | |||
| // PubKey pubKey = keyPair.getPubKey(); | |||
| // PrivKey privKey = keyPair.getPrivKey(); | |||
| // byte[] rawPrivKeyBytes = privKey.getRawKeyBytes(); | |||
| // Ciphertext ciphertext = aef.encrypt(pubKey,data); | |||
| // byte[] ciphertextBytes = ciphertext.toBytes(); | |||
| // | |||
| // verifyResolveCiphertext(asymmetricCrypto, algorithm, ciphertextBytes, null); | |||
| // | |||
| // | |||
| // //密文末尾两个字节丢失情况下,抛出异常 | |||
| // byte[] truncatedCiphertextBytes = new byte[ciphertextBytes.length-2]; | |||
| // System.arraycopy(ciphertextBytes,0,truncatedCiphertextBytes,0,truncatedCiphertextBytes.length); | |||
| // verifyDecrypt(asymmetricCrypto, algorithm, rawPrivKeyBytes, data, truncatedCiphertextBytes, CryptoException.class); | |||
| // | |||
| // byte[] ciphertextBytesWithWrongAlgCode = ciphertextBytes; | |||
| // ciphertextBytesWithWrongAlgCode[0] = CryptoAlgorithm.SHA256.CODE; | |||
| // verifyResolveCiphertext(asymmetricCrypto,algorithm,ciphertextBytesWithWrongAlgCode,IllegalArgumentException.class); | |||
| // | |||
| // ciphertextBytes = null; | |||
| // verifyResolveCiphertext(asymmetricCrypto,algorithm,ciphertextBytes,NullPointerException.class); | |||
| // } | |||
| // | |||
| // private void verifyResolveCiphertext(AsymmetricCryptography asymmetricCrypto, CryptoAlgorithm algorithm, byte[] ciphertextBytes, | |||
| // Class<?> expectedException){ | |||
| // Exception actualEx = null; | |||
| // | |||
| // try { | |||
| // | |||
| // Ciphertext ciphertext = asymmetricCrypto.resolveCiphertext(ciphertextBytes); | |||
| // | |||
| // assertNotNull(ciphertext); | |||
| // | |||
| // assertEquals(algorithm, ciphertext.getAlgorithm()); | |||
| // | |||
| // assertArrayEquals(ciphertextBytes, ciphertext.toBytes()); | |||
| // } | |||
| // catch (Exception e){ | |||
| // actualEx = e; | |||
| // } | |||
| // | |||
| // if (expectedException == null) { | |||
| // assertNull(actualEx); | |||
| // } | |||
| // else { | |||
| // assertNotNull(actualEx); | |||
| // assertTrue(expectedException.isAssignableFrom(actualEx.getClass())); | |||
| // } | |||
| // } | |||
| // | |||
| // @Test | |||
| // public void testTryResolveCiphertext() { | |||
| // } | |||
| // | |||
| // @Test | |||
| // public void testResolveSignatureDigest() { | |||
| // | |||
| // AsymmetricCryptography asymmetricCrypto = new AsymmtricCryptographyImpl(); | |||
| // Random randomData = new Random(); | |||
| // | |||
| // //test ED25519 | |||
| // CryptoAlgorithm algorithm = CryptoAlgorithm.ED25519; | |||
| // | |||
| // // 测试256字节的消息进行签名 | |||
| // byte[] data = new byte[256]; | |||
| // randomData.nextBytes(data); | |||
| // SignatureFunction sf = asymmetricCrypto.getSignatureFunction(algorithm); | |||
| // CryptoKeyPair keyPair = sf.generateKeyPair(); | |||
| // | |||
| // byte[] signatureDigestBytes = sf.sign(keyPair.getPrivKey(),data).toBytes(); | |||
| // verifyResolveSignatureDigest(asymmetricCrypto,algorithm,64,signatureDigestBytes,null); | |||
| // | |||
| // //签名数据末尾两个字节丢失情况下,抛出异常 | |||
| // byte[] truncatedSignatureDigestBytes = new byte[signatureDigestBytes.length-2]; | |||
| // System.arraycopy(signatureDigestBytes,0,truncatedSignatureDigestBytes,0,truncatedSignatureDigestBytes.length); | |||
| // verifyResolveSignatureDigest(asymmetricCrypto,algorithm,64,truncatedSignatureDigestBytes,IllegalArgumentException.class); | |||
| // | |||
| // signatureDigestBytes = null; | |||
| // verifyResolveSignatureDigest(asymmetricCrypto,algorithm,64,signatureDigestBytes,NullPointerException.class); | |||
| // | |||
| // | |||
| // //test SM2 | |||
| // algorithm = CryptoAlgorithm.SM2; | |||
| // | |||
| // // 测试256字节的消息进行签名 | |||
| // data = new byte[256]; | |||
| // randomData.nextBytes(data); | |||
| // sf = asymmetricCrypto.getSignatureFunction(algorithm); | |||
| // keyPair = sf.generateKeyPair(); | |||
| // | |||
| // signatureDigestBytes = sf.sign(keyPair.getPrivKey(),data).toBytes(); | |||
| // verifyResolveSignatureDigest(asymmetricCrypto,algorithm,64,signatureDigestBytes,null); | |||
| // | |||
| // //签名数据末尾两个字节丢失情况下,抛出异常 | |||
| // truncatedSignatureDigestBytes = new byte[signatureDigestBytes.length-2]; | |||
| // System.arraycopy(signatureDigestBytes,0,truncatedSignatureDigestBytes,0,truncatedSignatureDigestBytes.length); | |||
| // verifyResolveSignatureDigest(asymmetricCrypto,algorithm,64,truncatedSignatureDigestBytes,IllegalArgumentException.class); | |||
| // | |||
| // signatureDigestBytes = null; | |||
| // verifyResolveSignatureDigest(asymmetricCrypto,algorithm,64,signatureDigestBytes,NullPointerException.class); | |||
| // | |||
| // //test JNIED25519 | |||
| // algorithm = CryptoAlgorithm.JNIED25519; | |||
| // | |||
| // // 测试256字节的消息进行签名 | |||
| // data = new byte[256]; | |||
| // randomData.nextBytes(data); | |||
| // sf = asymmetricCrypto.getSignatureFunction(algorithm); | |||
| // keyPair = sf.generateKeyPair(); | |||
| // | |||
| // signatureDigestBytes = sf.sign(keyPair.getPrivKey(),data).toBytes(); | |||
| // verifyResolveSignatureDigest(asymmetricCrypto,algorithm,64,signatureDigestBytes,null); | |||
| // | |||
| // //签名数据末尾两个字节丢失情况下,抛出异常 | |||
| // truncatedSignatureDigestBytes = new byte[signatureDigestBytes.length-2]; | |||
| // System.arraycopy(signatureDigestBytes,0,truncatedSignatureDigestBytes,0,truncatedSignatureDigestBytes.length); | |||
| // verifyResolveSignatureDigest(asymmetricCrypto,algorithm,64,truncatedSignatureDigestBytes,IllegalArgumentException.class); | |||
| // | |||
| // signatureDigestBytes = null; | |||
| // verifyResolveSignatureDigest(asymmetricCrypto,algorithm,64,signatureDigestBytes,NullPointerException.class); | |||
| // } | |||
| // | |||
| // private void verifyResolveSignatureDigest(AsymmetricCryptography asymmetricCrypto, CryptoAlgorithm algorithm, | |||
| // int expectedSignatureDigestLength, | |||
| // byte[] signatureDigestBytes, Class<?> expectedException){ | |||
| // | |||
| // //初始化一个异常 | |||
| // Exception actualEx = null; | |||
| // | |||
| // try { | |||
| // | |||
| // SignatureDigest signatureDigest = asymmetricCrypto.resolveSignatureDigest(signatureDigestBytes); | |||
| // | |||
| // assertNotNull(signatureDigest); | |||
| // | |||
| // assertEquals(algorithm,signatureDigest.getAlgorithm()); | |||
| // | |||
| // assertEquals(expectedSignatureDigestLength,signatureDigest.getRawDigest().length); | |||
| // | |||
| // assertArrayEquals(signatureDigestBytes,signatureDigest.toBytes()); | |||
| // | |||
| // } | |||
| // catch (Exception e){ | |||
| // actualEx = e; | |||
| // } | |||
| // | |||
| // if (expectedException == null) { | |||
| // assertNull(actualEx); | |||
| // } | |||
| // else { | |||
| // assertNotNull(actualEx); | |||
| // assertTrue(expectedException.isAssignableFrom(actualEx.getClass())); | |||
| // } | |||
| // } | |||
| // | |||
| // @Test | |||
| // public void testTryResolveSignatureDigest() { | |||
| // } | |||
| // | |||
| // @Test | |||
| // public void testRetrievePubKeyBytes() { | |||
| // | |||
| // AsymmetricCryptography asymmetricCrypto = new AsymmtricCryptographyImpl(); | |||
| // | |||
| // //test ED25519 | |||
| // CryptoAlgorithm algorithm = CryptoAlgorithm.ED25519; | |||
| // | |||
| // CryptoKeyPair keyPair = asymmetricCrypto.generateKeyPair(algorithm); | |||
| // | |||
| // byte[] expectedPrivKeyBytes = keyPair.getPrivKey().toBytes(); | |||
| // byte[] expectedPubKeyBytes = keyPair.getPubKey().toBytes(); | |||
| // | |||
| // byte[] pubKeyBytes = asymmetricCrypto.retrievePubKeyBytes(expectedPrivKeyBytes); | |||
| // | |||
| // assertArrayEquals(expectedPubKeyBytes,pubKeyBytes); | |||
| // | |||
| // | |||
| // //test SM2 | |||
| // algorithm = CryptoAlgorithm.SM2; | |||
| // | |||
| // keyPair = asymmetricCrypto.generateKeyPair(algorithm); | |||
| // | |||
| // expectedPrivKeyBytes = keyPair.getPrivKey().toBytes(); | |||
| // expectedPubKeyBytes = keyPair.getPubKey().toBytes(); | |||
| // | |||
| // pubKeyBytes = asymmetricCrypto.retrievePubKeyBytes(expectedPrivKeyBytes); | |||
| // | |||
| // assertArrayEquals(expectedPubKeyBytes,pubKeyBytes); | |||
| // | |||
| // | |||
| // //test JNIED25519 | |||
| // algorithm = CryptoAlgorithm.JNIED25519; | |||
| // | |||
| // keyPair = asymmetricCrypto.generateKeyPair(algorithm); | |||
| // | |||
| // expectedPrivKeyBytes = keyPair.getPrivKey().toBytes(); | |||
| // expectedPubKeyBytes = keyPair.getPubKey().toBytes(); | |||
| // | |||
| // pubKeyBytes = asymmetricCrypto.retrievePubKeyBytes(expectedPrivKeyBytes); | |||
| // | |||
| // assertArrayEquals(expectedPubKeyBytes,pubKeyBytes); | |||
| // | |||
| // } | |||
| // | |||
| // | |||
| // @Test | |||
| // public void testResolvePubKey() { | |||
| // | |||
| // AsymmetricCryptography asymmetricCrypto = new AsymmtricCryptographyImpl(); | |||
| // | |||
| // //test ED25519 | |||
| // CryptoAlgorithm algorithm = CryptoAlgorithm.ED25519; | |||
| // | |||
| // CryptoKeyPair keyPair = asymmetricCrypto.generateKeyPair(algorithm); | |||
| // | |||
| // byte[] pubKeyBytes = keyPair.getPubKey().toBytes(); | |||
| // verifyResolvePubKey(asymmetricCrypto,algorithm,32,pubKeyBytes,null); | |||
| // | |||
| // byte[] truncatedPubKeyBytes = new byte[pubKeyBytes.length-2]; | |||
| // System.arraycopy(pubKeyBytes,0,truncatedPubKeyBytes,0,truncatedPubKeyBytes.length); | |||
| // verifyResolvePubKey(asymmetricCrypto,algorithm,32,truncatedPubKeyBytes,IllegalArgumentException.class); | |||
| // | |||
| // byte[] pubKeyBytesWithWrongAlgCode = pubKeyBytes; | |||
| // pubKeyBytesWithWrongAlgCode[0] = CryptoAlgorithm.SHA256.CODE; | |||
| // verifyResolvePubKey(asymmetricCrypto,algorithm,32,pubKeyBytesWithWrongAlgCode,IllegalArgumentException.class); | |||
| // | |||
| // byte[] pubKeyBytesWithWrongKeyType= pubKeyBytes; | |||
| // pubKeyBytesWithWrongKeyType[1] = PRIV_KEY.CODE; | |||
| // verifyResolvePubKey(asymmetricCrypto,algorithm,32,pubKeyBytesWithWrongKeyType,IllegalArgumentException.class); | |||
| // | |||
| // pubKeyBytes = null; | |||
| // verifyResolvePubKey(asymmetricCrypto,algorithm,32,pubKeyBytes,NullPointerException.class); | |||
| // | |||
| // | |||
| // //test SM2 | |||
| // algorithm = CryptoAlgorithm.SM2; | |||
| // | |||
| // keyPair = asymmetricCrypto.generateKeyPair(algorithm); | |||
| // | |||
| // pubKeyBytes = keyPair.getPubKey().toBytes(); | |||
| // verifyResolvePubKey(asymmetricCrypto,algorithm,65,pubKeyBytes,null); | |||
| // | |||
| // truncatedPubKeyBytes = new byte[pubKeyBytes.length-2]; | |||
| // System.arraycopy(pubKeyBytes,0,truncatedPubKeyBytes,0,truncatedPubKeyBytes.length); | |||
| // verifyResolvePubKey(asymmetricCrypto,algorithm,65,truncatedPubKeyBytes,IllegalArgumentException.class); | |||
| // | |||
| // pubKeyBytesWithWrongAlgCode = pubKeyBytes; | |||
| // pubKeyBytesWithWrongAlgCode[0] = CryptoAlgorithm.SHA256.CODE; | |||
| // verifyResolvePubKey(asymmetricCrypto,algorithm,65,pubKeyBytesWithWrongAlgCode,IllegalArgumentException.class); | |||
| // | |||
| // pubKeyBytesWithWrongKeyType= pubKeyBytes; | |||
| // pubKeyBytesWithWrongKeyType[1] = PRIV_KEY.CODE; | |||
| // verifyResolvePubKey(asymmetricCrypto,algorithm,65,pubKeyBytesWithWrongKeyType,IllegalArgumentException.class); | |||
| // | |||
| // pubKeyBytes = null; | |||
| // verifyResolvePubKey(asymmetricCrypto,algorithm,65,pubKeyBytes,NullPointerException.class); | |||
| // | |||
| // //test JNIED25519 | |||
| // algorithm = CryptoAlgorithm.JNIED25519; | |||
| // | |||
| // keyPair = asymmetricCrypto.generateKeyPair(algorithm); | |||
| // | |||
| // pubKeyBytes = keyPair.getPubKey().toBytes(); | |||
| // verifyResolvePubKey(asymmetricCrypto,algorithm,32,pubKeyBytes,null); | |||
| // | |||
| // truncatedPubKeyBytes = new byte[pubKeyBytes.length-2]; | |||
| // System.arraycopy(pubKeyBytes,0,truncatedPubKeyBytes,0,truncatedPubKeyBytes.length); | |||
| // verifyResolvePubKey(asymmetricCrypto,algorithm,32,truncatedPubKeyBytes,IllegalArgumentException.class); | |||
| // | |||
| // pubKeyBytesWithWrongAlgCode = pubKeyBytes; | |||
| // pubKeyBytesWithWrongAlgCode[0] = CryptoAlgorithm.SHA256.CODE; | |||
| // verifyResolvePubKey(asymmetricCrypto,algorithm,32,pubKeyBytesWithWrongAlgCode,IllegalArgumentException.class); | |||
| // | |||
| // pubKeyBytesWithWrongKeyType= pubKeyBytes; | |||
| // pubKeyBytesWithWrongKeyType[1] = PRIV_KEY.CODE; | |||
| // verifyResolvePubKey(asymmetricCrypto,algorithm,32,pubKeyBytesWithWrongKeyType,IllegalArgumentException.class); | |||
| // | |||
| // pubKeyBytes = null; | |||
| // verifyResolvePubKey(asymmetricCrypto,algorithm,32,pubKeyBytes,NullPointerException.class); | |||
| // } | |||
| // | |||
| // private void verifyResolvePubKey(AsymmetricCryptography asymmetricCrypto, CryptoAlgorithm algorithm, | |||
| // int expectedPubKeyLength, byte[] pubKeyBytes,Class<?> expectedException){ | |||
| // | |||
| // Exception actualEx = null; | |||
| // | |||
| // try { | |||
| // PubKey pubKey = asymmetricCrypto.resolvePubKey(pubKeyBytes); | |||
| // | |||
| // assertNotNull(pubKey); | |||
| // | |||
| // assertEquals(algorithm, pubKey.getAlgorithm()); | |||
| // | |||
| // assertEquals(expectedPubKeyLength, pubKey.getRawKeyBytes().length); | |||
| // | |||
| // assertArrayEquals(pubKeyBytes, pubKey.toBytes()); | |||
| // | |||
| // } | |||
| // catch (Exception e){ | |||
| // actualEx = e; | |||
| // } | |||
| // | |||
| // if (expectedException == null) { | |||
| // assertNull(actualEx); | |||
| // } | |||
| // else { | |||
| // assertNotNull(actualEx); | |||
| // assertTrue(expectedException.isAssignableFrom(actualEx.getClass())); | |||
| // } | |||
| // } | |||
| // | |||
| // @Test | |||
| // public void testTryResolvePubKey() { | |||
| // } | |||
| // | |||
| // @Test | |||
| // public void testResolvePrivKey() { | |||
| // | |||
| // AsymmetricCryptography asymmetricCrypto = new AsymmtricCryptographyImpl(); | |||
| // | |||
| // //test ED25519 | |||
| // CryptoAlgorithm algorithm = CryptoAlgorithm.ED25519; | |||
| // | |||
| // CryptoKeyPair keyPair = asymmetricCrypto.generateKeyPair(algorithm); | |||
| // | |||
| // byte[] privKeyBytes = keyPair.getPrivKey().toBytes(); | |||
| // verifyResolvePrivKey(asymmetricCrypto,algorithm,32,privKeyBytes,null); | |||
| // | |||
| // byte[] truncatedPrivKeyBytes = new byte[privKeyBytes.length-2]; | |||
| // System.arraycopy(privKeyBytes,0,truncatedPrivKeyBytes,0,truncatedPrivKeyBytes.length); | |||
| // verifyResolvePrivKey(asymmetricCrypto,algorithm,32,truncatedPrivKeyBytes,IllegalArgumentException.class); | |||
| // | |||
| // byte[] privKeyBytesWithWrongAlgCode = privKeyBytes; | |||
| // privKeyBytesWithWrongAlgCode[0] = CryptoAlgorithm.SHA256.CODE; | |||
| // verifyResolvePrivKey(asymmetricCrypto,algorithm,32,privKeyBytesWithWrongAlgCode,IllegalArgumentException.class); | |||
| // | |||
| // byte[] privKeyBytesWithWrongKeyType = privKeyBytes; | |||
| // privKeyBytesWithWrongKeyType[1] = PUB_KEY.CODE; | |||
| // verifyResolvePrivKey(asymmetricCrypto,algorithm,32,privKeyBytesWithWrongKeyType,IllegalArgumentException.class); | |||
| // | |||
| // privKeyBytes = null; | |||
| // verifyResolvePrivKey(asymmetricCrypto,algorithm,32,privKeyBytes,NullPointerException.class); | |||
| // | |||
| // | |||
| // //test SM2 | |||
| // algorithm = CryptoAlgorithm.SM2; | |||
| // | |||
| // keyPair = asymmetricCrypto.generateKeyPair(algorithm); | |||
| // | |||
| // privKeyBytes = keyPair.getPrivKey().toBytes(); | |||
| // verifyResolvePrivKey(asymmetricCrypto,algorithm,32,privKeyBytes,null); | |||
| // | |||
| // truncatedPrivKeyBytes = new byte[privKeyBytes.length-2]; | |||
| // System.arraycopy(privKeyBytes,0,truncatedPrivKeyBytes,0,truncatedPrivKeyBytes.length); | |||
| // verifyResolvePrivKey(asymmetricCrypto,algorithm,32,truncatedPrivKeyBytes,IllegalArgumentException.class); | |||
| // | |||
| // privKeyBytesWithWrongAlgCode = privKeyBytes; | |||
| // privKeyBytesWithWrongAlgCode[0] = CryptoAlgorithm.SHA256.CODE; | |||
| // verifyResolvePrivKey(asymmetricCrypto,algorithm,32,privKeyBytesWithWrongAlgCode,IllegalArgumentException.class); | |||
| // | |||
| // privKeyBytesWithWrongKeyType = privKeyBytes; | |||
| // privKeyBytesWithWrongKeyType[1] = PUB_KEY.CODE; | |||
| // verifyResolvePrivKey(asymmetricCrypto,algorithm,32,privKeyBytesWithWrongKeyType,IllegalArgumentException.class); | |||
| // | |||
| // privKeyBytes = null; | |||
| // verifyResolvePrivKey(asymmetricCrypto,algorithm,32,privKeyBytes,NullPointerException.class); | |||
| // | |||
| // //test JNIED25519 | |||
| // algorithm = CryptoAlgorithm.JNIED25519; | |||
| // | |||
| // keyPair = asymmetricCrypto.generateKeyPair(algorithm); | |||
| // | |||
| // privKeyBytes = keyPair.getPrivKey().toBytes(); | |||
| // verifyResolvePrivKey(asymmetricCrypto,algorithm,32,privKeyBytes,null); | |||
| // | |||
| // truncatedPrivKeyBytes = new byte[privKeyBytes.length-2]; | |||
| // System.arraycopy(privKeyBytes,0,truncatedPrivKeyBytes,0,truncatedPrivKeyBytes.length); | |||
| // verifyResolvePrivKey(asymmetricCrypto,algorithm,32,truncatedPrivKeyBytes,IllegalArgumentException.class); | |||
| // | |||
| // privKeyBytesWithWrongAlgCode = privKeyBytes; | |||
| // privKeyBytesWithWrongAlgCode[0] = CryptoAlgorithm.SHA256.CODE; | |||
| // verifyResolvePrivKey(asymmetricCrypto,algorithm,32,privKeyBytesWithWrongAlgCode,IllegalArgumentException.class); | |||
| // | |||
| // privKeyBytesWithWrongKeyType = privKeyBytes; | |||
| // privKeyBytesWithWrongKeyType[1] = PUB_KEY.CODE; | |||
| // verifyResolvePrivKey(asymmetricCrypto,algorithm,32,privKeyBytesWithWrongKeyType,IllegalArgumentException.class); | |||
| // | |||
| // privKeyBytes = null; | |||
| // verifyResolvePrivKey(asymmetricCrypto,algorithm,32,privKeyBytes,NullPointerException.class); | |||
| // } | |||
| // | |||
| // private void verifyResolvePrivKey(AsymmetricCryptography asymmetricCrypto, CryptoAlgorithm algorithm, | |||
| // int expectedPrivKeyLength, byte[] privKeyBytes,Class<?> expectedException){ | |||
| // | |||
| // Exception actualEx = null; | |||
| // | |||
| // try { | |||
| // PrivKey privKey = asymmetricCrypto.resolvePrivKey(privKeyBytes); | |||
| // | |||
| // assertNotNull(privKey); | |||
| // | |||
| // assertEquals(algorithm, privKey.getAlgorithm()); | |||
| // | |||
| // assertEquals(expectedPrivKeyLength, privKey.getRawKeyBytes().length); | |||
| // | |||
| // assertArrayEquals(privKeyBytes, privKey.toBytes()); | |||
| // | |||
| // } | |||
| // catch (Exception e){ | |||
| // actualEx = e; | |||
| // } | |||
| // | |||
| // if (expectedException == null) { | |||
| // assertNull(actualEx); | |||
| // } | |||
| // else { | |||
| // assertNotNull(actualEx); | |||
| // assertTrue(expectedException.isAssignableFrom(actualEx.getClass())); | |||
| // } | |||
| // } | |||
| // | |||
| // @Test | |||
| // public void testTryResolvePrivKey() { | |||
| // } | |||
| //} | |||
| @@ -0,0 +1,334 @@ | |||
| //package test.com.jd.blockchain.crypto.hash; | |||
| // | |||
| //import static org.junit.Assert.*; | |||
| // | |||
| //import java.util.Random; | |||
| // | |||
| //import com.jd.blockchain.crypto.smutils.hash.SM3Utils; | |||
| //import com.jd.blockchain.utils.io.BytesUtils; | |||
| //import com.jd.blockchain.utils.security.RipeMD160Utils; | |||
| //import com.jd.blockchain.utils.security.ShaUtils; | |||
| // | |||
| //import org.junit.Test; | |||
| // | |||
| //import com.jd.blockchain.crypto.CryptoAlgorithm; | |||
| //import com.jd.blockchain.crypto.CryptoUtils; | |||
| //import com.jd.blockchain.crypto.hash.HashCryptography; | |||
| //import com.jd.blockchain.crypto.hash.HashDigest; | |||
| //import com.jd.blockchain.crypto.hash.HashFunction; | |||
| //import com.jd.blockchain.crypto.impl.HashCryptographyImpl; | |||
| // | |||
| //public class HashCryptographyImplTest { | |||
| // | |||
| // @Test | |||
| // public void testGetFunction() { | |||
| // HashCryptography hashCrypto = CryptoUtils.hashCrypto(); | |||
| // Random rand = new Random(); | |||
| // // test SHA256 | |||
| // CryptoAlgorithm algorithm = CryptoAlgorithm.SHA256; | |||
| // byte[] data = new byte[256]; | |||
| // rand.nextBytes(data); | |||
| // verifyGetFunction(hashCrypto, algorithm, data, 256 / 8,null); | |||
| // | |||
| // data = new byte[0]; | |||
| // verifyGetFunction(hashCrypto, algorithm, data, 256 / 8,null); | |||
| // | |||
| // data = new byte[1056]; | |||
| // rand.nextBytes(data); | |||
| // verifyGetFunction(hashCrypto, algorithm, data, 256 / 8,null); | |||
| // | |||
| // data = null; | |||
| // verifyGetFunction(hashCrypto, algorithm, data, 256 / 8,NullPointerException.class); | |||
| // | |||
| // | |||
| // // test RIPEMD160 | |||
| // algorithm = CryptoAlgorithm.RIPEMD160; | |||
| // data=new byte[256]; | |||
| // rand.nextBytes(data); | |||
| // verifyGetFunction(hashCrypto, algorithm, data, 160 / 8,null); | |||
| // | |||
| // data = new byte[0]; | |||
| // verifyGetFunction(hashCrypto, algorithm, data, 160/ 8,null); | |||
| // | |||
| // data = new byte[1056]; | |||
| // rand.nextBytes(data); | |||
| // verifyGetFunction(hashCrypto, algorithm, data, 160 / 8,null); | |||
| // | |||
| // data = null; | |||
| // verifyGetFunction(hashCrypto, algorithm, data, 160 / 8,NullPointerException.class); | |||
| // | |||
| // // test SM3 | |||
| // algorithm = CryptoAlgorithm.SM3; | |||
| // data = new byte[256]; | |||
| // rand.nextBytes(data); | |||
| // verifyGetFunction(hashCrypto, algorithm, data, 256 / 8,null); | |||
| // | |||
| // data = new byte[0]; | |||
| // verifyGetFunction(hashCrypto, algorithm, data, 256 / 8,null); | |||
| // | |||
| // data = new byte[1056]; | |||
| // rand.nextBytes(data); | |||
| // verifyGetFunction(hashCrypto, algorithm, data, 256 / 8,null); | |||
| // | |||
| // data = null; | |||
| // verifyGetFunction(hashCrypto, algorithm, data, 256 / 8,NullPointerException.class); | |||
| // | |||
| // // test AES | |||
| // data = new byte[0]; | |||
| // algorithm = CryptoAlgorithm.AES; | |||
| // verifyGetFunction(hashCrypto, algorithm, data, 256 / 8,IllegalArgumentException.class); | |||
| // | |||
| // // test JNISHA256 | |||
| // algorithm = CryptoAlgorithm.JNISHA256; | |||
| // data = new byte[256]; | |||
| // rand.nextBytes(data); | |||
| // verifyGetFunction(hashCrypto, algorithm, data, 256 / 8,null); | |||
| // | |||
| // data = new byte[0]; | |||
| // verifyGetFunction(hashCrypto, algorithm, data, 256 / 8,null); | |||
| // | |||
| // data = new byte[1056]; | |||
| // rand.nextBytes(data); | |||
| // verifyGetFunction(hashCrypto, algorithm, data, 256 / 8,null); | |||
| // | |||
| // data = null; | |||
| // verifyGetFunction(hashCrypto, algorithm, data, 256 / 8,IllegalArgumentException.class); | |||
| // | |||
| // // test JNIRIPEMD160 | |||
| // algorithm = CryptoAlgorithm.JNIRIPEMD160; | |||
| // data=new byte[256]; | |||
| // rand.nextBytes(data); | |||
| // verifyGetFunction(hashCrypto, algorithm, data, 160 / 8,null); | |||
| // | |||
| // data = new byte[0]; | |||
| // verifyGetFunction(hashCrypto, algorithm, data, 160/ 8,null); | |||
| // | |||
| // data = new byte[1056]; | |||
| // rand.nextBytes(data); | |||
| // verifyGetFunction(hashCrypto, algorithm, data, 160 / 8,null); | |||
| // | |||
| // data = null; | |||
| // verifyGetFunction(hashCrypto, algorithm, data, 160 / 8,IllegalArgumentException.class); | |||
| // } | |||
| // | |||
| // private void verifyGetFunction(HashCryptography hashCrypto, CryptoAlgorithm algorithm, byte[] data, | |||
| // int expectedRawBytes,Class<?> expectedException) { | |||
| // Exception actualEx = null; | |||
| // try { | |||
| // HashFunction hf = hashCrypto.getFunction(algorithm); | |||
| // assertNotNull(hf); | |||
| // | |||
| // HashDigest hd = hf.hash(data); | |||
| // | |||
| // assertEquals(algorithm, hd.getAlgorithm()); | |||
| // | |||
| // assertEquals(expectedRawBytes, hd.getRawDigest().length); | |||
| // | |||
| // // verify encoding; | |||
| // byte[] encodedHash = hd.toBytes(); | |||
| // assertEquals(expectedRawBytes + 1, encodedHash.length); | |||
| // | |||
| // | |||
| // assertEquals(algorithm.CODE, encodedHash[0]); | |||
| // | |||
| // //verify equals | |||
| // assertEquals(true, hd.equals(hf.hash(data))); | |||
| // | |||
| // //verify verify | |||
| // assertTrue( hf.verify(hd, data)); | |||
| // | |||
| // } catch (Exception e) { | |||
| // actualEx = e; | |||
| // } | |||
| // | |||
| // if(expectedException==null){ | |||
| // assertNull(actualEx); | |||
| // } | |||
| // else { | |||
| // assertNotNull(actualEx); | |||
| // assertTrue(expectedException.isAssignableFrom(actualEx.getClass())); | |||
| // } | |||
| // } | |||
| // | |||
| // @Test | |||
| // public void testVerifyHashDigestByteArray() { | |||
| // HashCryptography hashCrypto = CryptoUtils.hashCrypto(); | |||
| // //test SHA256 | |||
| // byte[] data=new byte[256]; | |||
| // Random rand = new Random(); | |||
| // rand.nextBytes(data); | |||
| // CryptoAlgorithm algorithm=CryptoAlgorithm.SHA256; | |||
| // verifyHashDigestByteArray(hashCrypto,algorithm,data,null); | |||
| // data=null; | |||
| // verifyHashDigestByteArray(hashCrypto,algorithm,data,NullPointerException.class); | |||
| // | |||
| // //test RIPEMD160 | |||
| // algorithm=CryptoAlgorithm.RIPEMD160; | |||
| // data=new byte[896]; | |||
| // rand.nextBytes(data); | |||
| // verifyHashDigestByteArray(hashCrypto,algorithm,data,null); | |||
| // data=null; | |||
| // verifyHashDigestByteArray(hashCrypto,algorithm,data,NullPointerException.class); | |||
| // | |||
| // //test SM3 | |||
| // algorithm=CryptoAlgorithm.SM3; | |||
| // data=new byte[896]; | |||
| // rand.nextBytes(data); | |||
| // verifyHashDigestByteArray(hashCrypto,algorithm,data,null); | |||
| // data=null; | |||
| // verifyHashDigestByteArray(hashCrypto,algorithm,data,NullPointerException.class); | |||
| // | |||
| // | |||
| // //test AES | |||
| // algorithm=CryptoAlgorithm.AES; | |||
| // data=new byte[277]; | |||
| // rand.nextBytes(data); | |||
| // verifyHashDigestByteArray(hashCrypto,algorithm,data,IllegalArgumentException.class); | |||
| // | |||
| // //test JNISHA256 | |||
| // data=new byte[256]; | |||
| // rand = new Random(); | |||
| // rand.nextBytes(data); | |||
| // algorithm=CryptoAlgorithm.JNISHA256; | |||
| // verifyHashDigestByteArray(hashCrypto,algorithm,data,null); | |||
| // data=null; | |||
| // verifyHashDigestByteArray(hashCrypto,algorithm,data,IllegalArgumentException.class); | |||
| // | |||
| // //test JNIRIPEMD160 | |||
| // algorithm=CryptoAlgorithm.JNIRIPEMD160; | |||
| // data=new byte[896]; | |||
| // rand.nextBytes(data); | |||
| // verifyHashDigestByteArray(hashCrypto,algorithm,data,null); | |||
| // data=null; | |||
| // verifyHashDigestByteArray(hashCrypto,algorithm,data,IllegalArgumentException.class); | |||
| // } | |||
| // | |||
| // private void verifyHashDigestByteArray(HashCryptography hashCrypto,CryptoAlgorithm algorithm,byte[] data,Class<?> expectedException){ | |||
| // Exception actualEx=null; | |||
| // try { | |||
| // HashFunction hf = hashCrypto.getFunction(algorithm); | |||
| // assertNotNull(hf); | |||
| // HashDigest hd = hf.hash(data); | |||
| // hashCrypto.verify(hd,data); | |||
| // }catch (Exception e) | |||
| // { | |||
| // actualEx=e; | |||
| // } | |||
| // if (expectedException==null) | |||
| // { | |||
| // assertNull(actualEx); | |||
| // } | |||
| // else{ | |||
| // assertNotNull(actualEx); | |||
| // assertTrue(expectedException.isAssignableFrom(actualEx.getClass())); | |||
| // } | |||
| // } | |||
| // | |||
| // @Test | |||
| // public void testResolveHashDigest() { | |||
| // Random rand = new Random(); | |||
| // HashCryptography hashCrypto = CryptoUtils.hashCrypto(); | |||
| // | |||
| // //test SHA256 | |||
| // CryptoAlgorithm algorithm = CryptoAlgorithm.SHA256; | |||
| // byte[] data = new byte[256]; | |||
| // rand.nextBytes(data); | |||
| // byte[] hashDigestBytes = hashCrypto.getFunction(algorithm).hash(data).toBytes(); | |||
| // verifyResolveHashDigest(algorithm, hashCrypto,hashDigestBytes,32+1,null); | |||
| // | |||
| // byte[] truncatedHashDigestBytes = new byte[hashDigestBytes.length-2]; | |||
| // System.arraycopy(hashDigestBytes,0,truncatedHashDigestBytes,0,truncatedHashDigestBytes.length); | |||
| // verifyResolveHashDigest(algorithm, hashCrypto,truncatedHashDigestBytes,32+1,IllegalArgumentException.class); | |||
| // | |||
| // hashDigestBytes = null; | |||
| // verifyResolveHashDigest(algorithm, hashCrypto,hashDigestBytes,32+1,NullPointerException.class); | |||
| // | |||
| // | |||
| // //test RIPEMD160 | |||
| // algorithm = CryptoAlgorithm.RIPEMD160; | |||
| // data = new byte[256]; | |||
| // rand.nextBytes(data); | |||
| // hashDigestBytes = hashCrypto.getFunction(algorithm).hash(data).toBytes(); | |||
| // verifyResolveHashDigest(algorithm, hashCrypto,hashDigestBytes,20+1,null); | |||
| // | |||
| // truncatedHashDigestBytes = new byte[hashDigestBytes.length-2]; | |||
| // System.arraycopy(hashDigestBytes,0,truncatedHashDigestBytes,0,truncatedHashDigestBytes.length); | |||
| // verifyResolveHashDigest(algorithm, hashCrypto,truncatedHashDigestBytes,20+1,IllegalArgumentException.class); | |||
| // | |||
| // hashDigestBytes = null; | |||
| // verifyResolveHashDigest(algorithm, hashCrypto,hashDigestBytes,20+1,NullPointerException.class); | |||
| // | |||
| // | |||
| // //test SM3 | |||
| // algorithm = CryptoAlgorithm.SM3; | |||
| // data = new byte[256]; | |||
| // rand.nextBytes(data); | |||
| // hashDigestBytes = hashCrypto.getFunction(algorithm).hash(data).toBytes(); | |||
| // verifyResolveHashDigest(algorithm, hashCrypto,hashDigestBytes,32+1,null); | |||
| // | |||
| // truncatedHashDigestBytes = new byte[hashDigestBytes.length-2]; | |||
| // System.arraycopy(hashDigestBytes,0,truncatedHashDigestBytes,0,truncatedHashDigestBytes.length); | |||
| // verifyResolveHashDigest(algorithm, hashCrypto,truncatedHashDigestBytes,32+1,IllegalArgumentException.class); | |||
| // | |||
| // hashDigestBytes = null; | |||
| // verifyResolveHashDigest(algorithm, hashCrypto,hashDigestBytes,32+1,NullPointerException.class); | |||
| // | |||
| // | |||
| // //test JNISHA256 | |||
| // algorithm = CryptoAlgorithm.JNISHA256; | |||
| // data = new byte[256]; | |||
| // rand.nextBytes(data); | |||
| // hashDigestBytes = hashCrypto.getFunction(algorithm).hash(data).toBytes(); | |||
| // verifyResolveHashDigest(algorithm, hashCrypto,hashDigestBytes,32+1,null); | |||
| // | |||
| // truncatedHashDigestBytes = new byte[hashDigestBytes.length-2]; | |||
| // System.arraycopy(hashDigestBytes,0,truncatedHashDigestBytes,0,truncatedHashDigestBytes.length); | |||
| // verifyResolveHashDigest(algorithm, hashCrypto,truncatedHashDigestBytes,32+1,IllegalArgumentException.class); | |||
| // | |||
| // hashDigestBytes = null; | |||
| // verifyResolveHashDigest(algorithm, hashCrypto,hashDigestBytes,32+1,NullPointerException.class); | |||
| // | |||
| // //test JNIRIPEMD160 | |||
| // algorithm = CryptoAlgorithm.JNIRIPEMD160; | |||
| // data = new byte[256]; | |||
| // rand.nextBytes(data); | |||
| // hashDigestBytes = hashCrypto.getFunction(algorithm).hash(data).toBytes(); | |||
| // verifyResolveHashDigest(algorithm, hashCrypto,hashDigestBytes,20+1,null); | |||
| // | |||
| // truncatedHashDigestBytes = new byte[hashDigestBytes.length-2]; | |||
| // System.arraycopy(hashDigestBytes,0,truncatedHashDigestBytes,0,truncatedHashDigestBytes.length); | |||
| // verifyResolveHashDigest(algorithm, hashCrypto,truncatedHashDigestBytes,20+1,IllegalArgumentException.class); | |||
| // | |||
| // hashDigestBytes = null; | |||
| // verifyResolveHashDigest(algorithm, hashCrypto,hashDigestBytes,20+1,NullPointerException.class); | |||
| // } | |||
| // | |||
| // private void verifyResolveHashDigest(CryptoAlgorithm algorithm,HashCryptography | |||
| // hashCrypto,byte[] hashDigestBytes,int expectedLength,Class<?>expectedException){ | |||
| // | |||
| // Exception actualEx=null; | |||
| // | |||
| // try { | |||
| // | |||
| // HashDigest hashDigest=hashCrypto.resolveHashDigest(hashDigestBytes); | |||
| // assertNotNull(hashDigest); | |||
| // assertEquals(algorithm,hashDigest.getAlgorithm()); | |||
| // byte[] algBytes = new byte[1]; | |||
| // algBytes[0] = algorithm.CODE; | |||
| // assertArrayEquals(hashDigestBytes,BytesUtils.concat(algBytes,hashDigest.getRawDigest())); | |||
| // assertEquals(expectedLength,hashDigestBytes.length); | |||
| // | |||
| // }catch (Exception e) | |||
| // { | |||
| // actualEx = e; | |||
| // } | |||
| // if (expectedException==null) | |||
| // { | |||
| // assertNull(actualEx); | |||
| // } | |||
| // else { | |||
| // assertNotNull(actualEx); | |||
| // assertTrue(expectedException.isAssignableFrom(actualEx.getClass())); | |||
| // } | |||
| // } | |||
| // } | |||
| @@ -0,0 +1,471 @@ | |||
| //package test.com.jd.blockchain.crypto.symmetric; | |||
| // | |||
| //import com.jd.blockchain.crypto.Ciphertext; | |||
| //import com.jd.blockchain.crypto.CryptoAlgorithm; | |||
| //import com.jd.blockchain.crypto.SymmetricKey; | |||
| //import com.jd.blockchain.crypto.impl.SymmetricCryptographyImpl; | |||
| //import com.jd.blockchain.crypto.symmetric.SymmetricCryptography; | |||
| //import com.jd.blockchain.crypto.symmetric.SymmetricEncryptionFunction; | |||
| //import com.jd.blockchain.utils.io.BytesUtils; | |||
| // | |||
| //import org.junit.Test; | |||
| // | |||
| //import java.io.ByteArrayInputStream; | |||
| //import java.io.ByteArrayOutputStream; | |||
| //import java.io.InputStream; | |||
| //import java.io.OutputStream; | |||
| //import java.util.Random; | |||
| // | |||
| //import static com.jd.blockchain.crypto.CryptoKeyType.PRIV_KEY; | |||
| //import static com.jd.blockchain.crypto.CryptoKeyType.SYMMETRIC_KEY; | |||
| //import static org.junit.Assert.*; | |||
| // | |||
| //public class SymmetricCryptographyImplTest { | |||
| // | |||
| // @Test | |||
| // public void testGenerateKey() { | |||
| // | |||
| // SymmetricCryptography symmetricCrypto = new SymmetricCryptographyImpl(); | |||
| // | |||
| // //test AES | |||
| // CryptoAlgorithm algorithm = CryptoAlgorithm.AES; | |||
| // verifyGenerateKey(symmetricCrypto,algorithm); | |||
| // | |||
| // //test SM4 | |||
| // algorithm = CryptoAlgorithm.SM4; | |||
| // verifyGenerateKey(symmetricCrypto,algorithm); | |||
| // } | |||
| // | |||
| // private void verifyGenerateKey(SymmetricCryptography symmetricCrypto, CryptoAlgorithm algorithm){ | |||
| // | |||
| // SymmetricKey symmetricKey= symmetricCrypto.generateKey(algorithm); | |||
| // | |||
| // assertNotNull(symmetricKey); | |||
| // assertEquals(algorithm, symmetricKey.getAlgorithm()); | |||
| // assertEquals(128/8,symmetricKey.getRawKeyBytes().length); | |||
| // | |||
| // byte[] symmetricKeyBytes = symmetricKey.toBytes(); | |||
| // //判断密钥数据长度=算法标识长度+密钥掩码长度+原始密钥长度 | |||
| // assertEquals(1 + 1 + 128 / 8, symmetricKeyBytes.length); | |||
| // | |||
| // assertEquals(algorithm.CODE,symmetricKeyBytes[0]); | |||
| // assertEquals(algorithm,CryptoAlgorithm.valueOf(symmetricKeyBytes[0])); | |||
| // } | |||
| // | |||
| // @Test | |||
| // public void testGetSymmetricEncryptionFunction() { | |||
| // | |||
| // SymmetricCryptography symmetricCrypto = new SymmetricCryptographyImpl(); | |||
| // Random random = new Random(); | |||
| // | |||
| // | |||
| // //test AES | |||
| // CryptoAlgorithm algorithm = CryptoAlgorithm.AES; | |||
| // | |||
| // //Case 1: AES with 16 bytes data | |||
| // //刚好一个分组长度,随机生成明文数据 | |||
| // byte[] data = new byte[16]; | |||
| // random.nextBytes(data); | |||
| // verifyGetSymmetricEncryptionFunction(symmetricCrypto, algorithm, data, 2*16, null); | |||
| // | |||
| // //Case 2: AES with 33 bytes data | |||
| // //明文长度大于两倍分组长度,生成的密文是三倍分组长度 | |||
| // data = new byte[33]; | |||
| // random.nextBytes(data); | |||
| // verifyGetSymmetricEncryptionFunction(symmetricCrypto, algorithm, data, 3*16,null); | |||
| // | |||
| // //Case 3: AES with 3 bytes data | |||
| // //明文长度小于分组长度,生成的密文是一倍分组长度 | |||
| // data = new byte[3]; | |||
| // random.nextBytes(data); | |||
| // verifyGetSymmetricEncryptionFunction(symmetricCrypto, algorithm, data, 16,null); | |||
| // | |||
| // //Case 4: AES with 0 bytes data | |||
| // //明文长度小于分组长度,生成的密文是一倍分组长度 | |||
| // data = new byte[0]; | |||
| // random.nextBytes(data); | |||
| // verifyGetSymmetricEncryptionFunction(symmetricCrypto, algorithm, data, 16,null); | |||
| // | |||
| // //Case 5 AES with null | |||
| // //明文为空,可以捕获到异常异常 | |||
| // data = null; | |||
| // verifyGetSymmetricEncryptionFunction(symmetricCrypto, algorithm, data, 16,IllegalArgumentException.class); | |||
| // | |||
| // | |||
| // //test ED25519 | |||
| // algorithm = CryptoAlgorithm.ED25519; | |||
| // data = new byte[16]; | |||
| // random.nextBytes(data); | |||
| // verifyGetSymmetricEncryptionFunction(symmetricCrypto, algorithm, data, 16,IllegalArgumentException.class); | |||
| // | |||
| // | |||
| // //test SM4 | |||
| // algorithm = CryptoAlgorithm.SM4; | |||
| // | |||
| // //Case 1: SM4 with 16 bytes data | |||
| // data = new byte[16]; | |||
| // random.nextBytes(data); | |||
| // //密文长度 = IV长度 + 真实密文长度 | |||
| // verifyGetSymmetricEncryptionFunction(symmetricCrypto, algorithm, data, 3*16, null); | |||
| // | |||
| // //Case 2: SM4 with 33 bytes data | |||
| // data = new byte[33]; | |||
| // random.nextBytes(data); | |||
| // verifyGetSymmetricEncryptionFunction(symmetricCrypto, algorithm, data, 4*16,null); | |||
| // | |||
| // //Case 3: SM4 with 3 bytes data | |||
| // data = new byte[3]; | |||
| // random.nextBytes(data); | |||
| // verifyGetSymmetricEncryptionFunction(symmetricCrypto, algorithm, data, 2*16,null); | |||
| // | |||
| // //Case 4: SM4 with 0 bytes data | |||
| // data = new byte[0]; | |||
| // random.nextBytes(data); | |||
| // verifyGetSymmetricEncryptionFunction(symmetricCrypto, algorithm, data, 2*16,null); | |||
| // | |||
| // //Case 5 SM4 with null | |||
| // data = null; | |||
| // verifyGetSymmetricEncryptionFunction(symmetricCrypto, algorithm, data, 16,IllegalArgumentException.class); | |||
| // } | |||
| // | |||
| // //不同明文输入下,用来简化加解密过程的method | |||
| // private void verifyGetSymmetricEncryptionFunction(SymmetricCryptography symmetricCrypto, CryptoAlgorithm algorithm, | |||
| // byte[] data, int expectedCiphertextLength, Class<?> expectedException){ | |||
| // | |||
| // //初始化一个异常 | |||
| // Exception actualEx = null; | |||
| // | |||
| // try { | |||
| // SymmetricEncryptionFunction sef = symmetricCrypto.getSymmetricEncryptionFunction(algorithm); | |||
| // //验证获取的算法实例非空 | |||
| // assertNotNull(sef); | |||
| // | |||
| // SymmetricKey symmetricKey = (SymmetricKey) sef.generateSymmetricKey(); | |||
| // | |||
| // //验证SymmetricKey的getAlgorithm方法 | |||
| // assertEquals(algorithm, symmetricKey.getAlgorithm()); | |||
| // //验证SymmetricKey的getRawKeyBytes方法 | |||
| // assertEquals(16, symmetricKey.getRawKeyBytes().length); | |||
| // //验证SymmetricKey的toBytes方法 | |||
| // assertArrayEquals(BytesUtils.concat(new byte[]{algorithm.CODE},new byte[]{SYMMETRIC_KEY.CODE},symmetricKey.getRawKeyBytes()), symmetricKey.toBytes()); | |||
| // | |||
| // | |||
| // Ciphertext ciphertext = sef.encrypt(symmetricKey,data); | |||
| // | |||
| // //Ciphertext中算法标识与入参算法一致 | |||
| // assertEquals(algorithm, ciphertext.getAlgorithm()); | |||
| // //验证原始密文长度与预期长度一致 | |||
| // assertEquals(expectedCiphertextLength, ciphertext.getRawCiphertext().length); | |||
| // //验证密文数据长度=算法标识长度+预期长度 | |||
| // byte[] ciphertextBytes = ciphertext.toBytes(); | |||
| // assertArrayEquals(BytesUtils.concat(new byte[]{algorithm.CODE},ciphertext.getRawCiphertext()), ciphertextBytes); | |||
| // | |||
| // | |||
| // //验证equal | |||
| // assertTrue(ciphertext.equals(ciphertext)); | |||
| // assertEquals(ciphertext.hashCode(),ciphertext.hashCode()); | |||
| // | |||
| // //验证SymmetricEncryptionFunction的decrypt | |||
| // assertArrayEquals(data, sef.decrypt(symmetricKey,ciphertext)); | |||
| // | |||
| // //测试SymmetricEncryptionFunction的输入输出流的加解密方法 | |||
| // InputStream inPlaintext = new ByteArrayInputStream(data); | |||
| // //16字节的明文输入,将会产生32字节的密文 | |||
| // OutputStream outCiphertext = new ByteArrayOutputStream(ciphertext.toBytes().length); | |||
| // InputStream inCiphertext = new ByteArrayInputStream(ciphertext.toBytes()); | |||
| // OutputStream outPlaintext = new ByteArrayOutputStream(data.length); | |||
| // sef.encrypt(symmetricKey, inPlaintext, outCiphertext); | |||
| // sef.decrypt(symmetricKey, inCiphertext, outPlaintext); | |||
| // | |||
| // //验证SymmetricEncryptionFunction的supportCiphertext方法 | |||
| // assertTrue(sef.supportCiphertext(ciphertextBytes)); | |||
| // | |||
| // //验证SymmetricEncryptionFunction的resolveCiphertext方法 | |||
| // assertEquals(ciphertext, sef.resolveCiphertext(ciphertextBytes)); | |||
| // | |||
| // //验证SymmetricEncryptionFunction的supportSymmetricKey方法 | |||
| // assertTrue(sef.supportSymmetricKey(symmetricKey.toBytes())); | |||
| // | |||
| // //验证SymmetricEncryptionFunction的resolveSymmetricKey方法 | |||
| // assertEquals(symmetricKey, sef.resolveSymmetricKey(symmetricKey.toBytes())); | |||
| // | |||
| // //验证SymmetricEncryptionFunction的getAlgorithm | |||
| // assertEquals(algorithm, sef.getAlgorithm()); | |||
| // | |||
| // } catch (Exception e){ | |||
| // actualEx = e; | |||
| // } | |||
| // | |||
| // if (expectedException == null) { | |||
| // assertNull(actualEx); | |||
| // } | |||
| // else { | |||
| // assertNotNull(actualEx); | |||
| // assertTrue(expectedException.isAssignableFrom(actualEx.getClass())); | |||
| // } | |||
| // } | |||
| // | |||
| // @Test | |||
| // public void testDecrypt() { | |||
| // | |||
| // SymmetricCryptography symmetricCrypto = new SymmetricCryptographyImpl(); | |||
| // Random randomData = new Random(); | |||
| // Random randomKey = new Random(); | |||
| // | |||
| // | |||
| // //test AES | |||
| // CryptoAlgorithm algorithm = CryptoAlgorithm.AES; | |||
| // SymmetricEncryptionFunction sef = symmetricCrypto.getSymmetricEncryptionFunction(algorithm); | |||
| // | |||
| // byte[] data = new byte[16]; | |||
| // randomData.nextBytes(data); | |||
| // byte[] key = new byte[16]; | |||
| // randomKey.nextBytes(key); | |||
| // | |||
| // SymmetricKey symmetricKey = new SymmetricKey(algorithm, key); | |||
| // byte[] ciphertextBytes = sef.encrypt(symmetricKey,data).toBytes(); | |||
| // | |||
| // verifyDecrypt(symmetricCrypto, algorithm, key, data, ciphertextBytes, null); | |||
| // | |||
| // //密钥的算法标识与密文的算法标识不一致情况 | |||
| // verifyDecrypt(symmetricCrypto, CryptoAlgorithm.SM4, key, data, ciphertextBytes, IllegalArgumentException.class); | |||
| // | |||
| // //密文末尾两个字节丢失情况下,抛出异常 | |||
| // byte[] truncatedCiphertextBytes = new byte[ciphertextBytes.length-2]; | |||
| // System.arraycopy(ciphertextBytes,0,truncatedCiphertextBytes,0,truncatedCiphertextBytes.length); | |||
| // verifyDecrypt(symmetricCrypto, algorithm, key, data, truncatedCiphertextBytes, IllegalArgumentException.class); | |||
| // | |||
| // byte[] ciphertextBytesWithWrongAlgCode = ciphertextBytes; | |||
| // ciphertextBytesWithWrongAlgCode[0] = CryptoAlgorithm.SHA256.CODE; | |||
| // verifyDecrypt(symmetricCrypto,algorithm,key,data,ciphertextBytesWithWrongAlgCode,IllegalArgumentException.class); | |||
| // | |||
| // ciphertextBytes = null; | |||
| // verifyDecrypt(symmetricCrypto,algorithm,key,data,ciphertextBytes,NullPointerException.class); | |||
| // | |||
| // | |||
| // //test SM4 | |||
| // algorithm = CryptoAlgorithm.SM4; | |||
| // sef = symmetricCrypto.getSymmetricEncryptionFunction(algorithm); | |||
| // symmetricKey = new SymmetricKey(algorithm, key); | |||
| // ciphertextBytes = sef.encrypt(symmetricKey,data).toBytes(); | |||
| // | |||
| // verifyDecrypt(symmetricCrypto, algorithm, key, data, ciphertextBytes, null); | |||
| // | |||
| // //密钥的算法标识与密文的算法标识不一致情况 | |||
| // verifyDecrypt(symmetricCrypto, CryptoAlgorithm.AES, key, data, ciphertextBytes, IllegalArgumentException.class); | |||
| // | |||
| // //密文末尾两个字节丢失情况下,抛出异常 | |||
| // truncatedCiphertextBytes = new byte[ciphertextBytes.length-2]; | |||
| // System.arraycopy(ciphertextBytes,0,truncatedCiphertextBytes,0,truncatedCiphertextBytes.length); | |||
| // verifyDecrypt(symmetricCrypto, algorithm, key, data, truncatedCiphertextBytes, IllegalArgumentException.class); | |||
| // | |||
| // ciphertextBytesWithWrongAlgCode = ciphertextBytes; | |||
| // ciphertextBytesWithWrongAlgCode[0] = CryptoAlgorithm.SHA256.CODE; | |||
| // verifyDecrypt(symmetricCrypto,algorithm,key,data,ciphertextBytesWithWrongAlgCode,IllegalArgumentException.class); | |||
| // | |||
| // ciphertextBytes = null; | |||
| // verifyDecrypt(symmetricCrypto,algorithm,key,data,ciphertextBytes,NullPointerException.class); | |||
| // } | |||
| // | |||
| // private void verifyDecrypt(SymmetricCryptography symmetricCrypto, CryptoAlgorithm algorithm, | |||
| // byte[] key, byte[] data, byte[] ciphertextBytes, Class<?> expectedException) { | |||
| // | |||
| // Exception actualEx = null; | |||
| // | |||
| // try { | |||
| // SymmetricKey symmetricKey = new SymmetricKey(algorithm,key); | |||
| // | |||
| // byte[] plaintext = symmetricCrypto.decrypt(symmetricKey.toBytes(), ciphertextBytes); | |||
| // | |||
| // //解密后的明文与初始的明文一致 | |||
| // assertArrayEquals(data,plaintext); | |||
| // } | |||
| // catch (Exception e){ | |||
| // actualEx = e; | |||
| // } | |||
| // | |||
| // if (expectedException == null) { | |||
| // assertNull(actualEx); | |||
| // } | |||
| // else { | |||
| // assertNotNull(actualEx); | |||
| // assertTrue(expectedException.isAssignableFrom(actualEx.getClass())); | |||
| // } | |||
| // } | |||
| // | |||
| // @Test | |||
| // public void testResolveCiphertext() { | |||
| // | |||
| // SymmetricCryptography symmetricCrypto = new SymmetricCryptographyImpl(); | |||
| // Random randomData = new Random(); | |||
| // Random randomKey = new Random(); | |||
| // | |||
| // //test AES | |||
| // CryptoAlgorithm algorithm = CryptoAlgorithm.AES; | |||
| // SymmetricEncryptionFunction sef = symmetricCrypto.getSymmetricEncryptionFunction(algorithm); | |||
| // | |||
| // byte[] data = new byte[16]; | |||
| // randomData.nextBytes(data); | |||
| // byte[] key = new byte[16]; | |||
| // randomKey.nextBytes(key); | |||
| // | |||
| // SymmetricKey symmetricKey = new SymmetricKey(algorithm, key); | |||
| // byte[] ciphertextBytes = sef.encrypt(symmetricKey,data).toBytes(); | |||
| // verifyResolveCiphertext(symmetricCrypto, algorithm, ciphertextBytes, null); | |||
| // | |||
| // byte[] truncatedCiphertextBytes = new byte[ciphertextBytes.length-2]; | |||
| // System.arraycopy(ciphertextBytes,0,truncatedCiphertextBytes,0,truncatedCiphertextBytes.length); | |||
| // verifyResolveCiphertext(symmetricCrypto,algorithm,truncatedCiphertextBytes,IllegalArgumentException.class); | |||
| // | |||
| // byte[] ciphertextBytesWithWrongAlgCode = ciphertextBytes; | |||
| // ciphertextBytesWithWrongAlgCode[0] = CryptoAlgorithm.SHA256.CODE; | |||
| // verifyResolveCiphertext(symmetricCrypto,algorithm,ciphertextBytesWithWrongAlgCode,IllegalArgumentException.class); | |||
| // | |||
| // ciphertextBytes = null; | |||
| // verifyResolveCiphertext(symmetricCrypto,algorithm,ciphertextBytes,NullPointerException.class); | |||
| // | |||
| // | |||
| // //test SM4 | |||
| // algorithm = CryptoAlgorithm.SM4; | |||
| // sef = symmetricCrypto.getSymmetricEncryptionFunction(algorithm); | |||
| // | |||
| // symmetricKey = new SymmetricKey(algorithm, key); | |||
| // ciphertextBytes = sef.encrypt(symmetricKey,data).toBytes(); | |||
| // | |||
| // verifyResolveCiphertext(symmetricCrypto, algorithm, ciphertextBytes, null); | |||
| // | |||
| // truncatedCiphertextBytes = new byte[ciphertextBytes.length-2]; | |||
| // System.arraycopy(ciphertextBytes,0,truncatedCiphertextBytes,0,truncatedCiphertextBytes.length); | |||
| // verifyResolveCiphertext(symmetricCrypto,algorithm,truncatedCiphertextBytes,IllegalArgumentException.class); | |||
| // | |||
| // ciphertextBytesWithWrongAlgCode = ciphertextBytes; | |||
| // ciphertextBytesWithWrongAlgCode[0] = CryptoAlgorithm.SHA256.CODE; | |||
| // verifyResolveCiphertext(symmetricCrypto,algorithm,ciphertextBytesWithWrongAlgCode,IllegalArgumentException.class); | |||
| // | |||
| // ciphertextBytes = null; | |||
| // verifyResolveCiphertext(symmetricCrypto,algorithm,ciphertextBytes,NullPointerException.class); | |||
| // } | |||
| // | |||
| // private void verifyResolveCiphertext(SymmetricCryptography symmetricCrypto, CryptoAlgorithm algorithm, byte[] ciphertextBytes, | |||
| // Class<?> expectedException) { | |||
| // | |||
| // Exception actualEx = null; | |||
| // | |||
| // try { | |||
| // Ciphertext ciphertext = symmetricCrypto.resolveCiphertext(ciphertextBytes); | |||
| // | |||
| // assertNotNull(ciphertext); | |||
| // | |||
| // assertEquals(algorithm, ciphertext.getAlgorithm()); | |||
| // | |||
| // assertEquals(0, ciphertext.getRawCiphertext().length % 16); | |||
| // | |||
| // assertArrayEquals(ciphertextBytes, ciphertext.toBytes()); | |||
| // } | |||
| // catch (Exception e){ | |||
| // actualEx = e; | |||
| // } | |||
| // | |||
| // if (expectedException == null) { | |||
| // assertNull(actualEx); | |||
| // } | |||
| // else { | |||
| // assertNotNull(actualEx); | |||
| // assertTrue(expectedException.isAssignableFrom(actualEx.getClass())); | |||
| // } | |||
| // } | |||
| // | |||
| // @Test | |||
| // public void testTryResolveCiphertext() { | |||
| // } | |||
| // | |||
| // | |||
| // | |||
| // @Test | |||
| // public void testResolveSymmetricKey() { | |||
| // | |||
| // SymmetricCryptography symmetricCrypto = new SymmetricCryptographyImpl(); | |||
| // | |||
| // //test AES | |||
| // CryptoAlgorithm algorithm = CryptoAlgorithm.AES; | |||
| // | |||
| // Random randomKey = new Random(); | |||
| // byte[] key = new byte[16]; | |||
| // randomKey.nextBytes(key); | |||
| // | |||
| // byte[] symmetricKeyBytes = BytesUtils.concat(new byte[]{algorithm.CODE},new byte[]{SYMMETRIC_KEY.CODE},key); | |||
| // verifyResolveSymmetricKey(symmetricCrypto,algorithm,symmetricKeyBytes,null); | |||
| // | |||
| // byte[] truncatedSymmetricKeyBytes = new byte[symmetricKeyBytes.length-2]; | |||
| // System.arraycopy(symmetricKeyBytes,0,truncatedSymmetricKeyBytes,0,truncatedSymmetricKeyBytes.length); | |||
| // verifyResolveSymmetricKey(symmetricCrypto,algorithm,truncatedSymmetricKeyBytes,IllegalArgumentException.class); | |||
| // | |||
| // byte[] symmetricKeyBytesWithWrongAlgCode = symmetricKeyBytes; | |||
| // symmetricKeyBytesWithWrongAlgCode[0] = CryptoAlgorithm.SHA256.CODE; | |||
| // verifyResolveSymmetricKey(symmetricCrypto,algorithm,symmetricKeyBytesWithWrongAlgCode,IllegalArgumentException.class); | |||
| // | |||
| // byte[] symmetricKeyBytesWithWrongKeyType= symmetricKeyBytes; | |||
| // System.arraycopy(symmetricKeyBytes,0,symmetricKeyBytesWithWrongKeyType,0,symmetricKeyBytesWithWrongKeyType.length); | |||
| // symmetricKeyBytesWithWrongKeyType[1] = PRIV_KEY.CODE; | |||
| // verifyResolveSymmetricKey(symmetricCrypto,algorithm,symmetricKeyBytesWithWrongKeyType,IllegalArgumentException.class); | |||
| // | |||
| // symmetricKeyBytes = null; | |||
| // verifyResolveSymmetricKey(symmetricCrypto,algorithm,symmetricKeyBytes,NullPointerException.class); | |||
| // | |||
| // | |||
| // //test SM4 | |||
| // algorithm = CryptoAlgorithm.SM4; | |||
| // symmetricKeyBytes = BytesUtils.concat(new byte[]{algorithm.CODE},new byte[]{SYMMETRIC_KEY.CODE},key); | |||
| // | |||
| // verifyResolveSymmetricKey(symmetricCrypto,algorithm,symmetricKeyBytes,null); | |||
| // | |||
| // truncatedSymmetricKeyBytes = new byte[symmetricKeyBytes.length-2]; | |||
| // System.arraycopy(symmetricKeyBytes,0,truncatedSymmetricKeyBytes,0,truncatedSymmetricKeyBytes.length); | |||
| // verifyResolveSymmetricKey(symmetricCrypto,algorithm,truncatedSymmetricKeyBytes,IllegalArgumentException.class); | |||
| // | |||
| // symmetricKeyBytesWithWrongAlgCode = symmetricKeyBytes; | |||
| // symmetricKeyBytesWithWrongAlgCode[0] = CryptoAlgorithm.SHA256.CODE; | |||
| // verifyResolveSymmetricKey(symmetricCrypto,algorithm,symmetricKeyBytesWithWrongAlgCode,IllegalArgumentException.class); | |||
| // | |||
| // symmetricKeyBytesWithWrongKeyType= symmetricKeyBytes; | |||
| // System.arraycopy(symmetricKeyBytes,0,symmetricKeyBytesWithWrongKeyType,0,symmetricKeyBytesWithWrongKeyType.length); | |||
| // symmetricKeyBytesWithWrongKeyType[1] = PRIV_KEY.CODE; | |||
| // verifyResolveSymmetricKey(symmetricCrypto,algorithm,symmetricKeyBytesWithWrongKeyType,IllegalArgumentException.class); | |||
| // | |||
| // symmetricKeyBytes = null; | |||
| // verifyResolveSymmetricKey(symmetricCrypto,algorithm,symmetricKeyBytes,NullPointerException.class); | |||
| // } | |||
| // | |||
| // private void verifyResolveSymmetricKey(SymmetricCryptography symmetricCrypto, CryptoAlgorithm algorithm, byte[] symmetricKeyBytes, | |||
| // Class<?> expectedException) { | |||
| // | |||
| // Exception actualEx = null; | |||
| // | |||
| // try { | |||
| // SymmetricKey symmetricKey = symmetricCrypto.resolveSymmetricKey(symmetricKeyBytes); | |||
| // | |||
| // assertNotNull(symmetricKey); | |||
| // | |||
| // assertEquals(algorithm, symmetricKey.getAlgorithm()); | |||
| // | |||
| // assertEquals(16, symmetricKey.getRawKeyBytes().length); | |||
| // | |||
| // assertArrayEquals(symmetricKeyBytes, symmetricKey.toBytes()); | |||
| // } | |||
| // catch (Exception e){ | |||
| // actualEx = e; | |||
| // } | |||
| // | |||
| // if (expectedException == null) { | |||
| // assertNull(actualEx); | |||
| // } | |||
| // else { | |||
| // assertNotNull(actualEx); | |||
| // assertTrue(expectedException.isAssignableFrom(actualEx.getClass())); | |||
| // } | |||
| // } | |||
| // | |||
| // @Test | |||
| // public void testTryResolveSymmetricKey() { | |||
| // } | |||
| //} | |||
| @@ -5,7 +5,6 @@ import java.io.InputStream; | |||
| import java.io.OutputStream; | |||
| import java.util.Arrays; | |||
| import com.jd.blockchain.crypto.asymmetric.PubKey; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| import com.jd.blockchain.utils.io.BytesEncoding; | |||
| import com.jd.blockchain.utils.io.BytesUtils; | |||
| @@ -56,10 +55,10 @@ public class AddressEncoding { | |||
| public static Bytes generateAddress(PubKey pubKey) { | |||
| byte[] h1Bytes = ShaUtils.hash_256(pubKey.getRawKeyBytes()); | |||
| byte[] h2Bytes = RipeMD160Utils.hash(h1Bytes); | |||
| byte[] xBytes = BytesUtils.concat(new byte[]{AddressVersion.V1.CODE, pubKey.getAlgorithm().CODE}, h2Bytes); | |||
| byte[] xBytes = BytesUtils.concat(new byte[] { AddressVersion.V1.CODE}, CryptoAlgorithm.toBytes(pubKey.getAlgorithm()), h2Bytes); | |||
| byte[] checksum = Arrays.copyOf(ShaUtils.hash_256(ShaUtils.hash_256(xBytes)), 4); | |||
| byte[] addressBytes = BytesUtils.concat(xBytes, checksum); | |||
| return new Bytes(addressBytes); | |||
| } | |||
| @@ -1,9 +1,20 @@ | |||
| package com.jd.blockchain.crypto; | |||
| /** | |||
| * The version of Blockchain Address generation rule; <br> | |||
| * | |||
| * | |||
| * | |||
| * @author huanghaiquan | |||
| * | |||
| */ | |||
| public enum AddressVersion { | |||
| V1((byte) 0x91); | |||
| // Note: Implementor can only add new enum items, cann't remove or modify | |||
| // existing enum items; | |||
| public final byte CODE; | |||
| AddressVersion(byte code) { | |||
| @@ -1,9 +1,7 @@ | |||
| package com.jd.blockchain.crypto.base; | |||
| package com.jd.blockchain.crypto; | |||
| import java.util.Arrays; | |||
| import com.jd.blockchain.crypto.CryptoAlgorithm; | |||
| import com.jd.blockchain.crypto.CryptoBytes; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| import com.jd.blockchain.utils.io.BytesSlice; | |||
| import com.jd.blockchain.utils.io.BytesUtils; | |||
| @@ -25,17 +23,22 @@ public abstract class BaseCryptoBytes extends Bytes implements CryptoBytes { | |||
| super(cryptoBytes); | |||
| CryptoAlgorithm algorithm = decodeAlgorithm(cryptoBytes); | |||
| if (!support(algorithm)) { | |||
| throw new IllegalArgumentException("Not supported algorithm[" + algorithm.toString() + "]!"); | |||
| throw new CryptoException("Not supported algorithm[" + algorithm.toString() + "]!"); | |||
| } | |||
| this.algorithm = algorithm; | |||
| } | |||
| static byte[] encodeBytes(CryptoAlgorithm algorithm, byte[] rawCryptoBytes) { | |||
| return BytesUtils.concat(new byte[] { algorithm.CODE }, rawCryptoBytes); | |||
| return BytesUtils.concat(CryptoAlgorithm.toBytes(algorithm), rawCryptoBytes); | |||
| } | |||
| static CryptoAlgorithm decodeAlgorithm(byte[] cryptoBytes) { | |||
| return CryptoAlgorithm.valueOf(cryptoBytes[0]); | |||
| short algorithmCode = BytesUtils.toShort(cryptoBytes, 0); | |||
| CryptoAlgorithm algorithm = CryptoServiceProviders.getAlgorithm(algorithmCode); | |||
| if (algorithm == null) { | |||
| throw new CryptoException("The algorithm with code[" + algorithmCode + "] is not supported!"); | |||
| } | |||
| return algorithm; | |||
| } | |||
| protected abstract boolean support(CryptoAlgorithm algorithm); | |||
| @@ -44,6 +47,7 @@ public abstract class BaseCryptoBytes extends Bytes implements CryptoBytes { | |||
| return Arrays.copyOfRange(cryptoBytes, 1, cryptoBytes.length); | |||
| } | |||
| @Override | |||
| public CryptoAlgorithm getAlgorithm() { | |||
| // return resolveAlgorithm(encodedBytes); | |||
| return algorithm; | |||
| @@ -0,0 +1,46 @@ | |||
| package com.jd.blockchain.crypto; | |||
| import java.io.Serializable; | |||
| import com.jd.blockchain.utils.io.BytesSlice; | |||
| import com.jd.blockchain.utils.io.BytesUtils; | |||
| public abstract class BaseCryptoKey extends BaseCryptoBytes implements CryptoKey, Serializable { | |||
| public static final int KEY_TYPE_BYTES = 1; | |||
| private static final long serialVersionUID = 4543074827807908363L; | |||
| // public BaseCryptoKey() { | |||
| // super(); | |||
| // } | |||
| protected BaseCryptoKey(CryptoAlgorithm algorithm, byte[] rawKeyBytes, CryptoKeyType keyType) { | |||
| super(algorithm, encodeKeyBytes(rawKeyBytes, keyType)); | |||
| } | |||
| public BaseCryptoKey(byte[] cryptoBytes) { | |||
| super(cryptoBytes); | |||
| CryptoKeyType keyType = decodeKeyType(getRawCryptoBytes()); | |||
| if (getKeyType() != keyType) { | |||
| throw new CryptoException("CryptoKey doesn't support keyType[" + keyType + "]!"); | |||
| } | |||
| } | |||
| private static byte[] encodeKeyBytes(byte[] rawKeyBytes, CryptoKeyType keyType) { | |||
| return BytesUtils.concat(new byte[] { keyType.CODE }, rawKeyBytes); | |||
| } | |||
| private static CryptoKeyType decodeKeyType(BytesSlice cryptoBytes) { | |||
| return CryptoKeyType.valueOf(cryptoBytes.getByte()); | |||
| } | |||
| @Override | |||
| protected boolean support(CryptoAlgorithm algorithm) { | |||
| return CryptoAlgorithm.hasAsymmetricKey(algorithm) || CryptoAlgorithm.hasSymmetricKey(algorithm); | |||
| } | |||
| @Override | |||
| public byte[] getRawKeyBytes() { | |||
| return getRawCryptoBytes().getBytesCopy(1); | |||
| } | |||
| } | |||
| @@ -1,80 +1,110 @@ | |||
| package com.jd.blockchain.crypto; | |||
| import com.jd.blockchain.base.data.TypeCodes; | |||
| import com.jd.blockchain.binaryproto.EnumContract; | |||
| import com.jd.blockchain.binaryproto.EnumField; | |||
| import com.jd.blockchain.binaryproto.DataContract; | |||
| import com.jd.blockchain.binaryproto.DataField; | |||
| import com.jd.blockchain.consts.TypeCodes; | |||
| import com.jd.blockchain.utils.ValueType; | |||
| import com.jd.blockchain.utils.io.BytesUtils; | |||
| @DataContract(code = TypeCodes.CRYPTO_ALGORITHM) | |||
| public interface CryptoAlgorithm { | |||
| @EnumContract(code= TypeCodes.ENUM_TYPE_CRYPTO_ALGORITHM) | |||
| public enum CryptoAlgorithm { | |||
| SHA256(CryptoAlgorithmType.HASH, (byte) 0x01, false, false), | |||
| RIPEMD160(CryptoAlgorithmType.HASH, (byte) 0x02, false, false), | |||
| SM3(CryptoAlgorithmType.HASH, (byte) 0x03, false, false), | |||
| JNISHA256(CryptoAlgorithmType.HASH, (byte) 0x04, false, false), | |||
| JNIRIPEMD160(CryptoAlgorithmType.HASH, (byte) 0x05, false, false), | |||
| /** | |||
| * 随机数算法标识; | |||
| */ | |||
| static final int RANDOM_ALGORITHM = 0x1000; | |||
| // 非对称签名/加密算法; | |||
| /** | |||
| * 哈希数算法标识; | |||
| */ | |||
| static final int HASH_ALGORITHM = 0x2000; | |||
| /** | |||
| * RSA 签名算法;可签名,可加密; | |||
| * 签名算法标识; | |||
| */ | |||
| RSA(CryptoAlgorithmType.ASYMMETRIC, (byte) 0x01, true, true), | |||
| static final int SIGNATURE_ALGORITHM = 0x4000; | |||
| /** | |||
| * ED25519 签名算法;只用于签名,没有加密特性; | |||
| * 加密算法标识; | |||
| */ | |||
| ED25519(CryptoAlgorithmType.ASYMMETRIC, (byte) 0x02, true, false), | |||
| static final int ENCRYPTION_ALGORITHM = 0x8000; | |||
| /** | |||
| * ECDSA 签名算法;只用于签名,没有加密特性; | |||
| * 扩展密码算法标识; <br> | |||
| * 表示除了 | |||
| * {@link #RANDOM_ALGORITHM}、{@link #HASH_ALGORITHM}、{@link #SIGNATURE_ALGORITHM}、{@link #ENCRYPTION_ALGORITHM} | |||
| * 之外的其它非标准分类的密码算法,诸如加法同态算法、多方求和算法等; | |||
| */ | |||
| ECDSA(CryptoAlgorithmType.ASYMMETRIC, (byte) 0x03, true, false), | |||
| static final int EXT_ALGORITHM = 0x0000; | |||
| /** | |||
| * 国密 SM2 算法;可签名,可加密; | |||
| * 非对称密钥标识; | |||
| */ | |||
| SM2(CryptoAlgorithmType.ASYMMETRIC, (byte) 0x04, true, true), | |||
| static final int ASYMMETRIC_KEY = 0x0100; | |||
| /** | |||
| * JNIED25519 签名算法;只用于签名,没有加密特性; | |||
| * 对称密钥标识; | |||
| */ | |||
| JNIED25519(CryptoAlgorithmType.ASYMMETRIC, (byte) 0x05, true, false), | |||
| static final int SYMMETRIC_KEY = 0x0200; | |||
| // 对称加密; | |||
| /** | |||
| * AES 算法;可加密; | |||
| * 算法编码的字节长度;等同于 {@link #toBytes(CryptoAlgorithm)} 返回的字节数组的长度; | |||
| */ | |||
| AES(CryptoAlgorithmType.SYMMETRIC, (byte) 0x01, false, true), | |||
| static final int CODE_SIZE = 2; | |||
| SM4(CryptoAlgorithmType.SYMMETRIC, (byte) 0x02, false, true), | |||
| /** | |||
| * 密码算法的唯一编码; | |||
| * <p> | |||
| * 长度16位,高4位标识算法类型(包括: {@link #RANDOM_ALGORITHM}, {@link #HASH_ALGORITHM}, | |||
| * {@link #SIGNATURE_ALGORITHM}, {@link #ENCRYPTION_ALGORITHM}, | |||
| * {@link #EXT_ALGORITHM}) 5 种); 接下来4位标识密钥类型(包括:{@link #SYMMETRIC_KEY}, | |||
| * {@link #ASYMMETRIC_KEY}); 最后8位是算法唯一ID; | |||
| */ | |||
| @DataField(primitiveType = ValueType.INT16, order = 0) | |||
| short code(); | |||
| // 随机性; | |||
| /** | |||
| * 随机数算法,待定; | |||
| * 算法名称; | |||
| * <p> | |||
| * | |||
| * 实现者应该遵循“英文字符大写”的命名规范,并确保唯一性;<br> | |||
| * 例如,sha256 和 SHA256 将被视为相同的名称; | |||
| * | |||
| * @return | |||
| */ | |||
| JAVA_SECURE(CryptoAlgorithmType.RANDOM, (byte) 0x01, false, false); | |||
| String name(); | |||
| /** | |||
| * 密码算法的代号;<br> | |||
| * 注:只占16位; | |||
| * | |||
| * @return | |||
| */ | |||
| @EnumField(type= ValueType.INT8) | |||
| public final byte CODE; | |||
| static byte[] toBytes(CryptoAlgorithm algorithm) { | |||
| return BytesUtils.toBytes(algorithm.code()); | |||
| } | |||
| private final boolean signable; | |||
| static short resolveCode(byte[] algorithmBytes) { | |||
| return BytesUtils.toShort(algorithmBytes, 0); | |||
| } | |||
| private final boolean encryptable; | |||
| static short resolveCode(byte[] algorithmBytes, int offset) { | |||
| return BytesUtils.toShort(algorithmBytes, offset); | |||
| } | |||
| static boolean match(CryptoAlgorithm algorithm, byte[] algorithmBytes) { | |||
| return algorithm.code() == BytesUtils.toShort(algorithmBytes, 0); | |||
| } | |||
| private CryptoAlgorithm(byte algType, byte algId, boolean signable, boolean encryptable) { | |||
| this.CODE = (byte) (algType | algId); | |||
| this.signable = signable; | |||
| this.encryptable = encryptable; | |||
| static boolean match(CryptoAlgorithm algorithm, byte[] algorithmBytes, int offset) { | |||
| return algorithm.code() == BytesUtils.toShort(algorithmBytes, offset); | |||
| } | |||
| /** | |||
| * 是否属于随机数算法; | |||
| * | |||
| * @return | |||
| */ | |||
| static boolean isRandomAlgorithm(CryptoAlgorithm algorithm) { | |||
| return RANDOM_ALGORITHM == (algorithm.code() & RANDOM_ALGORITHM); | |||
| } | |||
| /** | |||
| @@ -82,69 +112,73 @@ public enum CryptoAlgorithm { | |||
| * | |||
| * @return | |||
| */ | |||
| public boolean isHash() { | |||
| return (CODE & CryptoAlgorithmType.HASH) == CryptoAlgorithmType.HASH; | |||
| static boolean isHashAlgorithm(CryptoAlgorithm algorithm) { | |||
| return HASH_ALGORITHM == (algorithm.code() & HASH_ALGORITHM); | |||
| } | |||
| /** | |||
| * 是否属于非对称密码算法; | |||
| * 是否属于签名算法; | |||
| * | |||
| * @return | |||
| */ | |||
| public boolean isAsymmetric() { | |||
| return (CODE & CryptoAlgorithmType.ASYMMETRIC) == CryptoAlgorithmType.ASYMMETRIC; | |||
| static boolean isSignatureAlgorithm(CryptoAlgorithm algorithm) { | |||
| return SIGNATURE_ALGORITHM == (algorithm.code() & SIGNATURE_ALGORITHM); | |||
| } | |||
| /** | |||
| * 是否属于对称密码算法; | |||
| * 是否属于加密算法; | |||
| * | |||
| * @return | |||
| */ | |||
| public boolean isSymmetric() { | |||
| return (CODE & CryptoAlgorithmType.SYMMETRIC) == CryptoAlgorithmType.SYMMETRIC; | |||
| static boolean isEncryptionAlgorithm(CryptoAlgorithm algorithm) { | |||
| return ENCRYPTION_ALGORITHM == (algorithm.code() & ENCRYPTION_ALGORITHM); | |||
| } | |||
| /** | |||
| * 是否属于随机数算法; | |||
| * 是否属于扩展密码算法; | |||
| * | |||
| * @return | |||
| */ | |||
| public boolean isRandom() { | |||
| return (CODE & CryptoAlgorithmType.RANDOM) == CryptoAlgorithmType.RANDOM; | |||
| static boolean isExtAlgorithm(CryptoAlgorithm algorithm) { | |||
| return EXT_ALGORITHM == (algorithm.code() & 0xF000); | |||
| } | |||
| /** | |||
| * 是否支持签名操作; | |||
| * 算法是否包含非对称密钥; | |||
| * | |||
| * @return | |||
| */ | |||
| public boolean isSignable() { | |||
| return signable; | |||
| static boolean hasAsymmetricKey(CryptoAlgorithm algorithm) { | |||
| return ASYMMETRIC_KEY == (algorithm.code() & ASYMMETRIC_KEY); | |||
| } | |||
| /** | |||
| * 是否支持加密操作; | |||
| * 算法是否包含对称密钥; | |||
| * | |||
| * @return | |||
| */ | |||
| public boolean isEncryptable() { | |||
| return encryptable; | |||
| static boolean hasSymmetricKey(CryptoAlgorithm algorithm) { | |||
| return SYMMETRIC_KEY == (algorithm.code() & SYMMETRIC_KEY); | |||
| } | |||
| /** | |||
| * 返回指定编码对应的枚举实例;<br> | |||
| * 是否属于对称加密算法; | |||
| * | |||
| * 如果不存在,则返回 null; | |||
| * @param algorithm | |||
| * @return | |||
| */ | |||
| static boolean isSymmetricEncryptionAlgorithm(CryptoAlgorithm algorithm) { | |||
| return isEncryptionAlgorithm(algorithm) && hasSymmetricKey(algorithm); | |||
| } | |||
| /** | |||
| * 是否属于非对称加密算法; | |||
| * | |||
| * @param code | |||
| * @param algorithm | |||
| * @return | |||
| */ | |||
| public static CryptoAlgorithm valueOf(byte code) { | |||
| for (CryptoAlgorithm alg : CryptoAlgorithm.values()) { | |||
| if (alg.CODE == code) { | |||
| return alg; | |||
| } | |||
| } | |||
| throw new IllegalArgumentException("CryptoAlgorithm doesn't support enum code[" + code + "]!"); | |||
| static boolean isAsymmetricEncryptionAlgorithm(CryptoAlgorithm algorithm) { | |||
| return isEncryptionAlgorithm(algorithm) && hasAsymmetricKey(algorithm); | |||
| } | |||
| } | |||
| @@ -0,0 +1,118 @@ | |||
| package com.jd.blockchain.crypto; | |||
| public final class CryptoAlgorithmDefinition implements CryptoAlgorithm { | |||
| private short code; | |||
| private String name; | |||
| CryptoAlgorithmDefinition(String name, short code) { | |||
| this.code = code; | |||
| this.name = name; | |||
| } | |||
| @Override | |||
| public short code() { | |||
| return this.code; | |||
| } | |||
| @Override | |||
| public String name() { | |||
| return name; | |||
| } | |||
| @Override | |||
| public String toString() { | |||
| return name + "[" + code + "]"; | |||
| } | |||
| /** | |||
| * 声明一项哈希算法; | |||
| * | |||
| * @param name | |||
| * 算法名称; | |||
| * @param uid | |||
| * 算法ID;需要在同类算法中保持唯一性; | |||
| * @return | |||
| */ | |||
| public static CryptoAlgorithm defineHash(String name, byte uid) { | |||
| short code = (short) (HASH_ALGORITHM | (uid & 0x00FF)); | |||
| return new CryptoAlgorithmDefinition(name, code); | |||
| } | |||
| /** | |||
| * 声明一项非对称密码算法; | |||
| * | |||
| * @param name | |||
| * 算法名称; | |||
| * @param uid | |||
| * 算法ID;需要在同类算法中保持唯一性; | |||
| * @return | |||
| */ | |||
| public static CryptoAlgorithm defineSignature(String name, boolean encryptable, byte uid) { | |||
| short code; | |||
| if (encryptable) { | |||
| code = (short) (SIGNATURE_ALGORITHM | ENCRYPTION_ALGORITHM | ASYMMETRIC_KEY | (uid & 0x00FF)); | |||
| } else { | |||
| code = (short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | (uid & 0x00FF)); | |||
| } | |||
| return new CryptoAlgorithmDefinition(name, code); | |||
| } | |||
| /** | |||
| * 声明一项非对称加密算法; | |||
| * | |||
| * @param name | |||
| * 算法名称; | |||
| * @param uid | |||
| * 算法ID;需要在同类算法中保持唯一性; | |||
| * @return | |||
| */ | |||
| public static CryptoAlgorithm defineAsymmetricEncryption(String name, byte uid) { | |||
| short code = (short) (ENCRYPTION_ALGORITHM | ASYMMETRIC_KEY | (uid & 0x00FF)); | |||
| return new CryptoAlgorithmDefinition(name, code); | |||
| } | |||
| /** | |||
| * 声明一项对称密码算法; | |||
| * | |||
| * @param name | |||
| * 算法名称; | |||
| * @param uid | |||
| * 算法ID;需要在同类算法中保持唯一性; | |||
| * @return | |||
| */ | |||
| public static CryptoAlgorithm defineSymmetricEncryption(String name, byte uid) { | |||
| short code = (short) (ENCRYPTION_ALGORITHM | SYMMETRIC_KEY | (uid & 0x00FF)); | |||
| return new CryptoAlgorithmDefinition(name, code); | |||
| } | |||
| /** | |||
| * 声明一项随机数算法; | |||
| * | |||
| * @param name | |||
| * 算法名称; | |||
| * @param uid | |||
| * 算法ID;需要在同类算法中保持唯一性; | |||
| * @return | |||
| */ | |||
| public static CryptoAlgorithm defineRandom(String name, byte uid) { | |||
| short code = (short) (RANDOM_ALGORITHM | (uid & 0x00FF)); | |||
| return new CryptoAlgorithmDefinition(name, code); | |||
| } | |||
| /** | |||
| * 声明一项扩展的密码算法; | |||
| * | |||
| * @param name | |||
| * 算法名称; | |||
| * @param uid | |||
| * 算法ID;需要在同类算法中保持唯一性; | |||
| * @return | |||
| */ | |||
| public static CryptoAlgorithm definExt(String name, byte uid) { | |||
| short code = (short) (EXT_ALGORITHM | (uid & 0x00FF)); | |||
| return new CryptoAlgorithmDefinition(name, code); | |||
| } | |||
| } | |||
| @@ -1,24 +1,24 @@ | |||
| package com.jd.blockchain.crypto; | |||
| public class CryptoAlgorithmType { | |||
| /** | |||
| * Hash 类算法的掩码; | |||
| */ | |||
| public static final byte HASH = 0x10; | |||
| /** | |||
| * 非对称加密类算法的掩码; | |||
| */ | |||
| public static final byte ASYMMETRIC = 0x20; | |||
| /** | |||
| * 对称加密类算法的掩码; | |||
| */ | |||
| public static final byte SYMMETRIC = 0x30; | |||
| /** | |||
| * 随机数类算法的掩码; | |||
| */ | |||
| public static final byte RANDOM = 0x40; | |||
| } | |||
| //package com.jd.blockchain.crypto; | |||
| // | |||
| //public class CryptoAlgorithmType { | |||
| // /** | |||
| // * Hash 类算法的掩码; | |||
| // */ | |||
| // public static final byte HASH = 0x10; | |||
| // | |||
| // /** | |||
| // * 非对称加密类算法的掩码; | |||
| // */ | |||
| // public static final byte ASYMMETRIC = 0x20; | |||
| // | |||
| // /** | |||
| // * 对称加密类算法的掩码; | |||
| // */ | |||
| // public static final byte SYMMETRIC = 0x30; | |||
| // | |||
| // /** | |||
| // * 随机数类算法的掩码; | |||
| // */ | |||
| // public static final byte RANDOM = 0x40; | |||
| // | |||
| //} | |||
| @@ -0,0 +1,150 @@ | |||
| //package com.jd.blockchain.crypto; | |||
| // | |||
| //import com.jd.blockchain.base.data.TypeCodes; | |||
| //import com.jd.blockchain.binaryproto.EnumContract; | |||
| //import com.jd.blockchain.binaryproto.EnumField; | |||
| //import com.jd.blockchain.utils.ValueType; | |||
| // | |||
| // | |||
| //@EnumContract(code= TypeCodes.CRYPTO_ALGORITHM) | |||
| //public enum CryptoAlgorithm_Enum { | |||
| // | |||
| // SHA256(CryptoAlgorithmType.HASH, (byte) 0x01, false, false), | |||
| // | |||
| // RIPEMD160(CryptoAlgorithmType.HASH, (byte) 0x02, false, false), | |||
| // | |||
| // SM3(CryptoAlgorithmType.HASH, (byte) 0x03, false, false), | |||
| // | |||
| // JNISHA256(CryptoAlgorithmType.HASH, (byte) 0x04, false, false), | |||
| // | |||
| // JNIRIPEMD160(CryptoAlgorithmType.HASH, (byte) 0x05, false, false), | |||
| // | |||
| // // 非对称签名/加密算法; | |||
| // | |||
| // /** | |||
| // * RSA 签名算法;可签名,可加密; | |||
| // */ | |||
| // RSA(CryptoAlgorithmType.ASYMMETRIC, (byte) 0x01, true, true), | |||
| // | |||
| // /** | |||
| // * ED25519 签名算法;只用于签名,没有加密特性; | |||
| // */ | |||
| // ED25519(CryptoAlgorithmType.ASYMMETRIC, (byte) 0x02, true, false), | |||
| // | |||
| // /** | |||
| // * ECDSA 签名算法;只用于签名,没有加密特性; | |||
| // */ | |||
| // ECDSA(CryptoAlgorithmType.ASYMMETRIC, (byte) 0x03, true, false), | |||
| // | |||
| // /** | |||
| // * 国密 SM2 算法;可签名,可加密; | |||
| // */ | |||
| // SM2(CryptoAlgorithmType.ASYMMETRIC, (byte) 0x04, true, true), | |||
| // | |||
| // /** | |||
| // * JNIED25519 签名算法;只用于签名,没有加密特性; | |||
| // */ | |||
| // JNIED25519(CryptoAlgorithmType.ASYMMETRIC, (byte) 0x05, true, false), | |||
| // | |||
| // // 对称加密; | |||
| // /** | |||
| // * AES 算法;可加密; | |||
| // */ | |||
| // AES(CryptoAlgorithmType.SYMMETRIC, (byte) 0x01, false, true), | |||
| // | |||
| // SM4(CryptoAlgorithmType.SYMMETRIC, (byte) 0x02, false, true), | |||
| // | |||
| // // 随机性; | |||
| // /** | |||
| // * 随机数算法,待定; | |||
| // */ | |||
| // JAVA_SECURE(CryptoAlgorithmType.RANDOM, (byte) 0x01, false, false); | |||
| // | |||
| // /** | |||
| // * 密码算法的代号;<br> | |||
| // * 注:只占16位; | |||
| // */ | |||
| // @EnumField(type= ValueType.INT8) | |||
| // public final byte CODE; | |||
| // | |||
| // private final boolean signable; | |||
| // | |||
| // private final boolean encryptable; | |||
| // | |||
| // private CryptoAlgorithm_Enum(byte algType, byte algId, boolean signable, boolean encryptable) { | |||
| // this.CODE = (byte) (algType | algId); | |||
| // this.signable = signable; | |||
| // this.encryptable = encryptable; | |||
| // } | |||
| // | |||
| // /** | |||
| // * 是否属于摘要算法; | |||
| // * | |||
| // * @return | |||
| // */ | |||
| // public boolean isHash() { | |||
| // return (CODE & CryptoAlgorithmType.HASH) == CryptoAlgorithmType.HASH; | |||
| // } | |||
| // | |||
| // /** | |||
| // * 是否属于非对称密码算法; | |||
| // * | |||
| // * @return | |||
| // */ | |||
| // public boolean isAsymmetric() { | |||
| // return (CODE & CryptoAlgorithmType.ASYMMETRIC) == CryptoAlgorithmType.ASYMMETRIC; | |||
| // } | |||
| // | |||
| // /** | |||
| // * 是否属于对称密码算法; | |||
| // * | |||
| // * @return | |||
| // */ | |||
| // public boolean isSymmetric() { | |||
| // return (CODE & CryptoAlgorithmType.SYMMETRIC) == CryptoAlgorithmType.SYMMETRIC; | |||
| // } | |||
| // | |||
| // /** | |||
| // * 是否属于随机数算法; | |||
| // * | |||
| // * @return | |||
| // */ | |||
| // public boolean isRandom() { | |||
| // return (CODE & CryptoAlgorithmType.RANDOM) == CryptoAlgorithmType.RANDOM; | |||
| // } | |||
| // | |||
| // /** | |||
| // * 是否支持签名操作; | |||
| // * | |||
| // * @return | |||
| // */ | |||
| // public boolean isSignable() { | |||
| // return signable; | |||
| // } | |||
| // | |||
| // /** | |||
| // * 是否支持加密操作; | |||
| // * | |||
| // * @return | |||
| // */ | |||
| // public boolean isEncryptable() { | |||
| // return encryptable; | |||
| // } | |||
| // | |||
| // /** | |||
| // * 返回指定编码对应的枚举实例;<br> | |||
| // * | |||
| // * 如果不存在,则返回 null; | |||
| // * | |||
| // * @param code | |||
| // * @return | |||
| // */ | |||
| // public static CryptoAlgorithm_Enum valueOf(byte code) { | |||
| // for (CryptoAlgorithm_Enum alg : CryptoAlgorithm_Enum.values()) { | |||
| // if (alg.CODE == code) { | |||
| // return alg; | |||
| // } | |||
| // } | |||
| // throw new IllegalArgumentException("CryptoAlgorithm doesn't support enum code[" + code + "]!"); | |||
| // } | |||
| //} | |||
| @@ -13,7 +13,7 @@ public interface CryptoBytes extends BytesSerializable { | |||
| /** | |||
| * 算法标识符的长度; | |||
| */ | |||
| int ALGORYTHM_BYTES = 1; | |||
| int ALGORYTHM_CODE_SIZE = CryptoAlgorithm.CODE_SIZE; | |||
| /** | |||
| * 算法; | |||
| @@ -25,10 +25,12 @@ public interface CryptoBytes extends BytesSerializable { | |||
| /** | |||
| * 返回编码后的摘要信息;<br> | |||
| * | |||
| * 这是算法标识 {@link #getAlgorithm()} 与原始的摘要数据 {@link #getRawDigest()} | |||
| * 这是算法标识 {@link #getAlgorithm()} 与原始的摘要数据 | |||
| * 按照特定的编码方式合并后的结果; | |||
| */ | |||
| @Override | |||
| byte[] toBytes(); | |||
| } | |||
| @@ -1,15 +1,15 @@ | |||
| package com.jd.blockchain.crypto; | |||
| import com.jd.blockchain.crypto.asymmetric.AsymmetricCryptography; | |||
| import com.jd.blockchain.crypto.hash.HashCryptography; | |||
| import com.jd.blockchain.crypto.symmetric.SymmetricCryptography; | |||
| public interface CryptoFactory { | |||
| HashCryptography hashCryptography(); | |||
| AsymmetricCryptography asymmetricCryptography(); | |||
| SymmetricCryptography symmetricCryptography(); | |||
| } | |||
| //package com.jd.blockchain.crypto; | |||
| // | |||
| //import com.jd.blockchain.crypto.asymmetric.AsymmetricCryptography; | |||
| //import com.jd.blockchain.crypto.hash.HashCryptography; | |||
| //import com.jd.blockchain.crypto.symmetric.SymmetricCryptography; | |||
| // | |||
| //public interface CryptoFactory { | |||
| // | |||
| // HashCryptography hashCryptography(); | |||
| // | |||
| // AsymmetricCryptography asymmetricCryptography(); | |||
| // | |||
| // SymmetricCryptography symmetricCryptography(); | |||
| // | |||
| //} | |||
| @@ -9,6 +9,4 @@ public interface CryptoKeyPairGenerator { | |||
| */ | |||
| CryptoKeyPair generateKeyPair(); | |||
| } | |||
| @@ -3,17 +3,17 @@ package com.jd.blockchain.crypto; | |||
| public enum CryptoKeyType { | |||
| /** | |||
| * 非对称密码算法的公钥 | |||
| * 非对称密钥的公钥 | |||
| */ | |||
| PUB_KEY((byte)0x01), | |||
| /** | |||
| * 非对称密码算法的私钥; | |||
| * 非对称密钥的私钥; | |||
| */ | |||
| PRIV_KEY((byte)0x02), | |||
| /** | |||
| * 对称密码算法的密钥; | |||
| * 对称密钥; | |||
| */ | |||
| SYMMETRIC_KEY((byte)0x03); | |||
| @@ -29,7 +29,7 @@ public enum CryptoKeyType { | |||
| return alg; | |||
| } | |||
| } | |||
| throw new IllegalArgumentException("CryptoKeyType doesn't support enum code[" + code + "]!"); | |||
| throw new CryptoException("CryptoKeyType doesn't support enum code[" + code + "]!"); | |||
| } | |||
| public byte getCODE() { | |||
| @@ -0,0 +1,9 @@ | |||
| package com.jd.blockchain.crypto; | |||
| import java.util.Collection; | |||
| public interface CryptoService { | |||
| Collection<CryptoFunction> getFunctions(); | |||
| } | |||
| @@ -0,0 +1,213 @@ | |||
| package com.jd.blockchain.crypto; | |||
| import java.util.Collection; | |||
| import java.util.Map; | |||
| import java.util.concurrent.ConcurrentHashMap; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import com.jd.blockchain.crypto.asymmetric.AsymmetricEncryptionFunction; | |||
| import com.jd.blockchain.crypto.asymmetric.SignatureFunction; | |||
| import com.jd.blockchain.crypto.hash.HashFunction; | |||
| import com.jd.blockchain.crypto.symmetric.SymmetricEncryptionFunction; | |||
| import com.jd.blockchain.provider.Provider; | |||
| import com.jd.blockchain.provider.ProviderManager; | |||
| /** | |||
| * 密码服务提供者的管理器; | |||
| * | |||
| * @author huanghaiquan | |||
| * | |||
| */ | |||
| public final class CryptoServiceProviders { | |||
| private static Logger LOGGER = LoggerFactory.getLogger(CryptoServiceProviders.class); | |||
| private static Map<Short, CryptoFunction> functions = new ConcurrentHashMap<>(); | |||
| private static Map<Short, CryptoAlgorithm> algorithms = new ConcurrentHashMap<>(); | |||
| private static Map<String, Short> names = new ConcurrentHashMap<>(); | |||
| private static ProviderManager pm = new ProviderManager(); | |||
| static { | |||
| loadDefaultProviders(); | |||
| } | |||
| private static void loadDefaultProviders() { | |||
| ClassLoader cl = CryptoServiceProviders.class.getClassLoader(); | |||
| pm.installAllProviders(CryptoService.class, cl); | |||
| Iterable<Provider<CryptoService>> providers = pm.getAllProviders(CryptoService.class); | |||
| for (Provider<CryptoService> provider : providers) { | |||
| register(provider); | |||
| } | |||
| } | |||
| private static void register(Provider<CryptoService> provider) { | |||
| for (CryptoFunction cryptoFunction : provider.getService().getFunctions()) { | |||
| String name = cryptoFunction.getAlgorithm().name().toUpperCase(); | |||
| short code = cryptoFunction.getAlgorithm().code(); | |||
| CryptoAlgorithm algorithm = new CryptoAlgorithmDefinition(name, code); | |||
| if (CryptoAlgorithm.isRandomAlgorithm(algorithm) && !(cryptoFunction instanceof RandomFunction)) { | |||
| LOGGER.error(String.format( | |||
| "The random algorithm \"%s\" declared by provider[%s] does not implement the interface \"%s\"!", | |||
| algorithm.toString(), provider.getFullName(), RandomFunction.class.getName())); | |||
| continue; | |||
| } | |||
| if (CryptoAlgorithm.isAsymmetricEncryptionAlgorithm(algorithm) | |||
| && !(cryptoFunction instanceof AsymmetricEncryptionFunction)) { | |||
| LOGGER.error(String.format( | |||
| "The asymmetric encryption algorithm \"%s\" declared by the provider[%s] does not implement the interface \"%s\"!", | |||
| algorithm.toString(), provider.getFullName(), AsymmetricEncryptionFunction.class.getName())); | |||
| continue; | |||
| } | |||
| if (CryptoAlgorithm.isSignatureAlgorithm(algorithm) && !(cryptoFunction instanceof SignatureFunction)) { | |||
| LOGGER.error(String.format( | |||
| "The signature algorithm \"%s\" declared by the provider[%s] does not implement the interface \"%s\"!", | |||
| algorithm.toString(), provider.getFullName(), SignatureFunction.class.getName())); | |||
| continue; | |||
| } | |||
| if (CryptoAlgorithm.isSymmetricEncryptionAlgorithm(algorithm) | |||
| && !(cryptoFunction instanceof SymmetricEncryptionFunction)) { | |||
| LOGGER.error(String.format( | |||
| "The symmetric encryption algorithm \"%s\" declared by the provider[%s] does not implement the interface \"%s\"!", | |||
| algorithm.toString(), provider.getFullName(), SymmetricEncryptionFunction.class.getName())); | |||
| continue; | |||
| } | |||
| if (CryptoAlgorithm.isHashAlgorithm(algorithm) && !(cryptoFunction instanceof HashFunction)) { | |||
| LOGGER.error(String.format( | |||
| "The hash encryption algorithm \"%s\" declared by the provider[%s] does not implement the interface \"%s\"!", | |||
| algorithm.toString(), provider.getFullName(), HashFunction.class.getName())); | |||
| continue; | |||
| } | |||
| if (CryptoAlgorithm.isExtAlgorithm(algorithm) && (cryptoFunction instanceof RandomFunction | |||
| || cryptoFunction instanceof AsymmetricEncryptionFunction | |||
| || cryptoFunction instanceof SignatureFunction | |||
| || cryptoFunction instanceof SymmetricEncryptionFunction | |||
| || cryptoFunction instanceof HashFunction)) { | |||
| LOGGER.error(String.format( | |||
| "The ext algorithm \"%s\" declared by the provider[%s] can not implement the standard algorithm interface!", | |||
| algorithm.toString(), provider.getFullName())); | |||
| continue; | |||
| } | |||
| if (functions.containsKey(algorithm.code()) || names.containsKey(algorithm.name())) { | |||
| LOGGER.error(String.format("The algorithm \"%s\" declared by the provider[%s] already exists!", | |||
| algorithm.toString(), provider.getFullName())); | |||
| continue; | |||
| } | |||
| functions.put(algorithm.code(), cryptoFunction); | |||
| algorithms.put(algorithm.code(), algorithm); | |||
| names.put(algorithm.name(), algorithm.code()); | |||
| } | |||
| } | |||
| private CryptoServiceProviders() { | |||
| } | |||
| public static Collection<CryptoAlgorithm> getAllAlgorithms() { | |||
| return algorithms.values(); | |||
| } | |||
| /** | |||
| * 返回指定编码的算法; <br> | |||
| * 如果不存在,则返回 null; | |||
| * | |||
| * @param code | |||
| * @return | |||
| */ | |||
| public static CryptoAlgorithm getAlgorithm(short code) { | |||
| return algorithms.get(code); | |||
| } | |||
| public static CryptoAlgorithm getAlgorithm(String name) { | |||
| Short code = names.get(name.toUpperCase()); | |||
| return code == null ? null : algorithms.get(code); | |||
| } | |||
| public static RandomFunction getRandomFunction(CryptoAlgorithm algorithm) { | |||
| if (!CryptoAlgorithm.isRandomAlgorithm(algorithm)) { | |||
| throw new CryptoException("The specified algorithm " + algorithm.name() + "[" + algorithm.code() | |||
| + "] is not a random function!"); | |||
| } | |||
| CryptoFunction func = functions.get(algorithm.code()); | |||
| if (func == null) { | |||
| throw new CryptoException( | |||
| "Algorithm " + algorithm.name() + "[" + algorithm.code() + "] has no service provider!"); | |||
| } | |||
| return (RandomFunction) func; | |||
| } | |||
| public static HashFunction getHashFunction(CryptoAlgorithm algorithm) { | |||
| if (!CryptoAlgorithm.isHashAlgorithm(algorithm)) { | |||
| throw new CryptoException("The specified algorithm " + algorithm.name() + "[" + algorithm.code() | |||
| + "] is not a hash function!"); | |||
| } | |||
| CryptoFunction func = functions.get(algorithm.code()); | |||
| if (func == null) { | |||
| throw new CryptoException( | |||
| "Algorithm " + algorithm.name() + "[" + algorithm.code() + "] has no service provider!"); | |||
| } | |||
| return (HashFunction) func; | |||
| } | |||
| public static AsymmetricEncryptionFunction getAsymmetricEncryptionFunction(CryptoAlgorithm algorithm) { | |||
| if (!CryptoAlgorithm.isAsymmetricEncryptionAlgorithm(algorithm)) { | |||
| throw new CryptoException("The specified algorithm " + algorithm.name() + "[" + algorithm.code() | |||
| + "] is not a asymmetric encryption function!"); | |||
| } | |||
| CryptoFunction func = functions.get(algorithm.code()); | |||
| if (func == null) { | |||
| throw new CryptoException( | |||
| "Algorithm " + algorithm.name() + "[" + algorithm.code() + "] has no service provider!"); | |||
| } | |||
| return (AsymmetricEncryptionFunction) func; | |||
| } | |||
| public static SignatureFunction getSignatureFunction(CryptoAlgorithm algorithm) { | |||
| if (!CryptoAlgorithm.isSignatureAlgorithm(algorithm)) { | |||
| throw new CryptoException("The specified algorithm " + algorithm.name() + "[" + algorithm.code() | |||
| + "] is not a signature function!"); | |||
| } | |||
| CryptoFunction func = functions.get(algorithm.code()); | |||
| if (func == null) { | |||
| throw new CryptoException( | |||
| "Algorithm " + algorithm.name() + "[" + algorithm.code() + "] has no service provider!"); | |||
| } | |||
| return (SignatureFunction) func; | |||
| } | |||
| public static SymmetricEncryptionFunction getSymmetricEncryptionFunction(CryptoAlgorithm algorithm) { | |||
| if (!CryptoAlgorithm.isSymmetricEncryptionAlgorithm(algorithm)) { | |||
| throw new CryptoException("The specified algorithm " + algorithm.name() + "[" + algorithm.code() | |||
| + "] is not a symmetric encryption function!"); | |||
| } | |||
| CryptoFunction func = functions.get(algorithm.code()); | |||
| if (func == null) { | |||
| throw new CryptoException( | |||
| "Algorithm " + algorithm.name() + "[" + algorithm.code() + "] has no service provider!"); | |||
| } | |||
| return (SymmetricEncryptionFunction) func; | |||
| } | |||
| public static CryptoFunction getCryptoFunction(CryptoAlgorithm algorithm) { | |||
| CryptoFunction func = functions.get(algorithm.code()); | |||
| if (func == null) { | |||
| throw new CryptoException( | |||
| "Algorithm " + algorithm.name() + "[" + algorithm.code() + "] has no service provider!"); | |||
| } | |||
| return func; | |||
| } | |||
| } | |||
| @@ -1,51 +1,73 @@ | |||
| package com.jd.blockchain.crypto; | |||
| import com.jd.blockchain.crypto.asymmetric.AsymmetricCryptography; | |||
| import com.jd.blockchain.crypto.asymmetric.AsymmetricEncryptionFunction; | |||
| import com.jd.blockchain.crypto.asymmetric.SignatureFunction; | |||
| import com.jd.blockchain.crypto.hash.HashCryptography; | |||
| import com.jd.blockchain.crypto.hash.HashFunction; | |||
| import com.jd.blockchain.crypto.impl.CryptoFactoryImpl; | |||
| import com.jd.blockchain.crypto.symmetric.SymmetricCryptography; | |||
| import com.jd.blockchain.crypto.symmetric.SymmetricEncryptionFunction; | |||
| public class CryptoUtils { | |||
| private static CryptoFactory CRYPTO_FACTORY = new CryptoFactoryImpl(); | |||
| public static CryptoFactory crypto() { | |||
| return CRYPTO_FACTORY; | |||
| } | |||
| public static HashCryptography hashCrypto() { | |||
| return crypto().hashCryptography(); | |||
| } | |||
| public static HashFunction hash(CryptoAlgorithm alg) { | |||
| return hashCrypto().getFunction(alg); | |||
| } | |||
| public static AsymmetricCryptography asymmCrypto() { | |||
| return crypto().asymmetricCryptography(); | |||
| } | |||
| public static SignatureFunction sign(CryptoAlgorithm alg) { | |||
| return asymmCrypto().getSignatureFunction(alg); | |||
| } | |||
| public static AsymmetricEncryptionFunction asymmEncrypt(CryptoAlgorithm alg) { | |||
| return asymmCrypto().getAsymmetricEncryptionFunction(alg); | |||
| } | |||
| public static SymmetricCryptography symmCrypto() { | |||
| return crypto().symmetricCryptography(); | |||
| } | |||
| public static SymmetricEncryptionFunction symmEncrypt(CryptoAlgorithm alg) { | |||
| return symmCrypto().getSymmetricEncryptionFunction(alg); | |||
| } | |||
| } | |||
| //package com.jd.blockchain.crypto; | |||
| // | |||
| //import org.slf4j.Logger; | |||
| //import org.slf4j.LoggerFactory; | |||
| // | |||
| //import com.jd.blockchain.crypto.asymmetric.AsymmetricCryptography; | |||
| //import com.jd.blockchain.crypto.asymmetric.AsymmetricEncryptionFunction; | |||
| //import com.jd.blockchain.crypto.asymmetric.SignatureFunction; | |||
| //import com.jd.blockchain.crypto.hash.HashCryptography; | |||
| //import com.jd.blockchain.crypto.hash.HashFunction; | |||
| //import com.jd.blockchain.crypto.symmetric.SymmetricCryptography; | |||
| //import com.jd.blockchain.crypto.symmetric.SymmetricEncryptionFunction; | |||
| // | |||
| //public class CryptoUtils { | |||
| // | |||
| // private static Logger LOGGER = LoggerFactory.getLogger(CryptoUtils.class); | |||
| // | |||
| // private static final Object MUTEX = new Object(); | |||
| // | |||
| // private static final String STD = "com.jd.blockchain.crypto.impl.CryptoFactoryImpl"; | |||
| // | |||
| // private static volatile CryptoFactory STD_FACTORY; | |||
| // | |||
| // public static CryptoFactory crypto() { | |||
| // if (STD_FACTORY == null) { | |||
| // synchronized (MUTEX) { | |||
| // if (STD_FACTORY == null) { | |||
| // try { | |||
| // Class<?> stdFactoryClass = Class.forName(STD); | |||
| // STD_FACTORY = (CryptoFactory) stdFactoryClass.newInstance(); | |||
| // } catch (ClassNotFoundException e) { | |||
| // LOGGER.error("STD crypto provider is not found!", e); | |||
| // throw new CryptoException("STD crypto provider is not found!", e); | |||
| // } catch (InstantiationException | IllegalAccessException e) { | |||
| // LOGGER.error("Fail to init STD crypto provider!", e); | |||
| // throw new CryptoException("Fail to init STD crypto provider!", e); | |||
| // } | |||
| // } | |||
| // return STD_FACTORY; | |||
| // } | |||
| // } | |||
| // return STD_FACTORY; | |||
| // } | |||
| // | |||
| // public static HashCryptography hashCrypto() { | |||
| // return crypto().hashCryptography(); | |||
| // } | |||
| // | |||
| // public static HashFunction hash(CryptoAlgorithm alg) { | |||
| // return hashCrypto().getFunction(alg); | |||
| // } | |||
| // | |||
| // public static AsymmetricCryptography asymmCrypto() { | |||
| // return crypto().asymmetricCryptography(); | |||
| // } | |||
| // | |||
| // public static SignatureFunction sign(CryptoAlgorithm alg) { | |||
| // return asymmCrypto().getSignatureFunction(alg); | |||
| // } | |||
| // | |||
| // public static AsymmetricEncryptionFunction asymmEncrypt(CryptoAlgorithm alg) { | |||
| // return asymmCrypto().getAsymmetricEncryptionFunction(alg); | |||
| // } | |||
| // | |||
| // public static SymmetricCryptography symmCrypto() { | |||
| // return crypto().symmetricCryptography(); | |||
| // } | |||
| // | |||
| // public static SymmetricEncryptionFunction symmEncrypt(CryptoAlgorithm alg) { | |||
| // return symmCrypto().getSymmetricEncryptionFunction(alg); | |||
| // } | |||
| // | |||
| //} | |||
| @@ -1,8 +1,4 @@ | |||
| package com.jd.blockchain.crypto.asymmetric; | |||
| import com.jd.blockchain.crypto.CryptoAlgorithm; | |||
| import com.jd.blockchain.crypto.CryptoKeyType; | |||
| import com.jd.blockchain.crypto.base.BaseCryptoKey; | |||
| package com.jd.blockchain.crypto; | |||
| /** | |||
| * 私钥; | |||
| @@ -20,9 +16,9 @@ public class PrivKey extends BaseCryptoKey { | |||
| public PrivKey(byte[] cryptoBytes) { | |||
| super(cryptoBytes); | |||
| } | |||
| @Override | |||
| protected boolean support(CryptoKeyType keyType) { | |||
| return CryptoKeyType.PRIV_KEY == keyType; | |||
| public CryptoKeyType getKeyType() { | |||
| return CryptoKeyType.PRIV_KEY; | |||
| } | |||
| } | |||
| @@ -1,8 +1,4 @@ | |||
| package com.jd.blockchain.crypto.asymmetric; | |||
| import com.jd.blockchain.crypto.CryptoAlgorithm; | |||
| import com.jd.blockchain.crypto.CryptoKeyType; | |||
| import com.jd.blockchain.crypto.base.BaseCryptoKey; | |||
| package com.jd.blockchain.crypto; | |||
| /** | |||
| * 公钥; | |||
| @@ -17,16 +13,13 @@ public class PubKey extends BaseCryptoKey { | |||
| public PubKey(CryptoAlgorithm algorithm, byte[] rawCryptoBytes) { | |||
| super(algorithm, rawCryptoBytes, CryptoKeyType.PUB_KEY); | |||
| } | |||
| public PubKey() { | |||
| super(); | |||
| } | |||
| public PubKey(byte[] cryptoBytes) { | |||
| super(cryptoBytes); | |||
| } | |||
| @Override | |||
| protected boolean support(CryptoKeyType keyType) { | |||
| return CryptoKeyType.PUB_KEY == keyType; | |||
| public CryptoKeyType getKeyType() { | |||
| return CryptoKeyType.PUB_KEY; | |||
| } | |||
| } | |||