智能合约中的加密合约,一个简单的加密算法

  • 在智能合约中其实所有数据都是透明的
  • 我这加密合约的作用其实是弥补以前旧合约中有敏感字段调用的时候需要加密不被发现破解
  • 合约数据都是透明的(private也一样),但是还是可以阻挡90%的人,不懂技术和技术不深者
  • 加密合约需要使用升级合约的目的是升级算法

这是流程图

在这里插入图片描述

合约代码

mint合约

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;

import "./interface/IAxie.sol";
import "./interface/ICipherGenes.sol";
import "@openzeppelin442/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import "@openzeppelin442/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin442/contracts-upgradeable/utils/AddressUpgradeable.sol";
import "./utils/VerifySignatUreupgradeable.sol";

contract Xxx is
    Initializable,
    AccessControlUpgradeable,
    VerifySignatUreupgradeable
{
    using AddressUpgradeable for address payable;
    IAxie public _axieAddress;
    ICipherGenes public _cipherGenesAddress;
    // 价格
    uint256 public _price;
    mapping(bytes => uint256) public _signs;

    event WakeupEvent(
        bytes signature,
        uint256 axieId,
        uint256 new_horse_id,
        uint256 price,
        address owner
    );
    event ChangePrice(uint256 price);

    bytes32 public constant CFO_ROLE = keccak256("CFO_ROLE");
    bytes32 public constant OPER_ROLE = keccak256("OPER_ROLE");

    function initialize() public initializer {
        __AccessControl_init();
        __VerifySignature_init();

        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(OPER_ROLE, msg.sender);
        _changeSignaturer(msg.sender);
    }

    /**
     * @dev 设置 axie合约
     */
    function setCoreAddress(IAxie axieAddress)
        public
        onlyRole(DEFAULT_ADMIN_ROLE)
    {
        _axieAddress = axieAddress;
    }

    /**
     * @dev 设置加密合约
     */
    function setCipherGenesAddress(ICipherGenes cipherGenesAddress)
        public
        onlyRole(DEFAULT_ADMIN_ROLE)
    {
        _cipherGenesAddress = cipherGenesAddress;
    }

    /**
     * @dev 设置当前价格
     */
    function setPrice(uint256 value) public onlyRole(OPER_ROLE) {
        _price = value;
        emit ChangePrice(_price);
    }

    /**
     * wiehdraw all amount
     */
    function withdraw(address payable to) public onlyRole(CFO_ROLE) {
        uint256 amount = address(this).balance;
        to.sendValue(amount);
    }

    // 进行mint
    function conduct(
        uint256 rawAxieId,
        uint256 genes,
        uint256 expirationTime,
        uint256 nonce,
        bytes memory signature,
        uint256 v,
        uint256 len
    ) public payable returns (uint256) {
        // 一系列判断代码我删了

        // 先解密
        uint256 decode_genes;
        if (v == 1) {
            decode_genes = _cipherGenesAddress.decryption(genes);
        } else if (v == 2) {
            decode_genes = _cipherGenesAddress.decryptionV2(genes, len);
        } else if (v == 3) {
            decode_genes = _cipherGenesAddress.decryptionV3(genes);
        } else {
            revert("version is not");
        }
        // 后验签
        require(
            verify(rawAxieId, decode_genes, expirationTime, nonce, signature),
            "signature is not correct"
        );
        // 这里你去处理其他事情,调用主体合约mint也好,其他也好
        return horse_id;
    }

    fallback() external payable {}

    receive() external payable {}
}

非升级合约写法 CipherGenes.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;

import "@openzeppelin442/contracts/access/AccessControl.sol";
import "../utils/CipherGenesVerifySignature.sol";

/**
 * !call的from可以伪造
 */

contract CipherGenes is AccessControl, CipherGenesVerifySignature {
    event updateKeyEvent();
    event updateType(uint256 t);

    uint256 private _key;
    uint256 public _type;
    bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");

    constructor() {
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(ADMIN_ROLE, msg.sender);
        _setKey();
        setType(100001);
        _changeSignaturer(msg.sender);
    }

    // 设置类型,防止_signature丢失可以重新生成一个新的
    function setType(uint256 t) public onlyRole(ADMIN_ROLE) {
        _type = t;
        emit updateType(_type);
    }

    // 加严
    function _stricter() private view returns (uint256) {
        return _key % 1e6;
    }

    // 随机生成一个密码
    function _setKey() private {
        _key =
            (uint256(
                keccak256(abi.encodePacked(block.difficulty, block.timestamp))
            ) +
            (uint256(keccak256(abi.encodePacked(block.timestamp))) % 1e10) +
            _type +
            (uint256(
                keccak256(abi.encodePacked(block.difficulty, block.timestamp))
            ) % 1e8)) / 10000;
        emit updateKeyEvent();
    }

    // 加密
    function encryption(uint256 original) public view returns (uint256) {
        //进行取反操作
        uint256 stricter = _stricter();
        uint256 sign = original ^ _key ^ stricter;
        return (revertse(sign * 10 + 1) ^ stricter) + stricter;
    }

    uint256 private _num;

    // 解密消耗gas,防止from伪造
    function decryption(uint256 sign)
        public
        onlyRole(ADMIN_ROLE)
        returns (uint256)
    {
        _num += 1;
        //进行取反操作
        uint256 stricter = _stricter();
        uint256 sign2 = (revertse((sign - stricter) ^ stricter) - 1) / 10;
        return sign2 ^ _key ^ stricter;
    }

    function revertse(uint256 x) internal pure returns(uint256)
    {
        uint256 result = 0;
        while(x != 0){
            result = result * 10 + x % 10;
            x = x / 10;
        }
        return result;
    }

    // 验证签名获取秘钥,因为from地址可以伪造,但是签名有秘钥所以不可能伪造,签名、怕调用盲盒或者其他合约有签名数据然后套取key
    function (uint256 _nonce, bytes memory _signature)
        public
        view
        onlyRole(ADMIN_ROLE)
        returns (uint256)
    {
        require(verify(_type, _nonce, _signature), "signature is not correct");
        return _key;
    }

    // 更新密钥,不能加参数只能线上更新
    function updateKey() public onlyRole(ADMIN_ROLE) {
        _setKey();
    }
}

升级合约写法 CipherGenesUpgradeable.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;

import "@openzeppelin442/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import "@openzeppelin442/contracts-upgradeable/proxy/utils/Initializable.sol";
import "../utils/upgradeable/CipherGenesVerifySignatureUpgradeable.sol";
import "../utils/Uint256s.sol";

/**
 * !call的from可以伪造
 */

contract CipherGenesUpgradeable is
    Initializable,
    AccessControlUpgradeable,
    CipherGenesVerifySignatureUpgradeable
{
    event updateKeyEvent();
    event updateType(uint256 indexed t);

    using Uint256s for uint256;

    uint256 private _key;
    uint256 public _type;
    bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");

    function initialize() public initializer {
        __AccessControl_init();
        __VerifySignature_init();

        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(ADMIN_ROLE, msg.sender);
        _setKey();
        setType(100001);
        _changeSignaturer(msg.sender);
    }

    // 设置类型,防止_signature丢失可以重新生成一个新的
    function setType(uint256 t) public onlyRole(ADMIN_ROLE) {
        _type = t;
        emit updateType(_type);
    }

    // 加严
    function _stricter() private view returns (uint256) {
        return _key % 1e6;
    }

    // 随机生成一个密码
    function _setKey() private {
        _key =
            (uint256(
                keccak256(abi.encodePacked(block.difficulty, block.timestamp))
            ) +
            (uint256(keccak256(abi.encodePacked(block.timestamp))) % 1e10) +
            _type +
            (uint256(
                keccak256(abi.encodePacked(block.difficulty, block.timestamp))
            ) % 1e8)) / 10;
        emit updateKeyEvent();
    }

    // 加密
    function encryption(uint256 original) public view returns (uint256) {
        //进行取反操作
        uint256 stricter = _stricter();
        uint256 sign = original ^ _key ^ stricter;
        return sign + stricter;
    }

    bool private a;

    // 解密消耗gas,防止from伪造
    function decryption(uint256 sign)
        public
        onlyRole(ADMIN_ROLE)
        returns (uint256)
    {
        //进行取反操作
        a = true;
        uint256 stricter = _stricter();
        uint256 sign2 = sign - stricter;
        return sign2 ^ _key ^ stricter;
    }

    // 加密 v1版本秘钥太长,v2版本需要*10,uint256会溢出,所以秘钥 / 1000
    // 基因太长,只反转6位~节省gas,计算整形长度消耗gas所以直接传值
    function encryptionV2(uint256 original,uint256 len) public view returns (uint256) {
        //进行取反操作
        uint256 stricter = _stricter();
        uint256 sign = original ^ (_key / 1000) ^ stricter;
        return ((sign * 10 + 1).revertse1(len) ^ stricter) + stricter;
    }

    // 解密消耗gas,防止from伪造
    // 基因太长,只反转6位~节省gas,计算整形长度消耗gas所以直接传值
    function decryptionV2(uint256 sign, uint256 len)
        public
        onlyRole(ADMIN_ROLE)
        returns (uint256)
    {
        a = true;
        //进行取反操作
        uint256 stricter = _stricter();
        uint256 sign2 = (((sign - stricter) ^ stricter).revertse2(len) - 1) / 10;
        return sign2 ^ (_key / 1000) ^ stricter;
    }

    // 加密v3
    function encryptionV3(uint256 original) public view returns (uint256) {
        //进行取反操作
        uint256 stricter = _stricter();
        uint256 sign = original ^ (_key / 100) ^ stricter;
        uint256 iszero = 1;
        if((sign % 10) == 0){
            iszero = 10;
        }
        sign = sign.revertse() * iszero;
        return (sign ^ getNewKey(sign,_key)) + stricter;
    }

    // 解密v3
    function decryptionV3(uint256 sign)
        public
        onlyRole(ADMIN_ROLE)
        returns (uint256)
    {
        a = true;
        //进行取反操作
        uint256 stricter = _stricter();
        sign = sign - stricter;
        uint256 iszero = 1;
        sign = sign ^ getNewKey(sign,_key);
        if((sign % 10) == 0){
            iszero = 10;
        }
        sign = (sign).revertse();
        sign = sign * iszero;
        return sign ^ (_key / 100) ^ stricter;
    }

    function getNewKey(uint256 original,uint256 key) internal pure returns(uint256)
    {
        uint256 len = key.getLength() - original.getLength();
        if(len > 0){
            key /= 10 ** len;
        }
        return key;
    }

    // 验证签名获取秘钥,因为from地址可以伪造,但是签名有秘钥所以不可能伪造,签名、怕调用盲盒或者其他合约有签名数据然后套取key
    function getKey(uint256 _nonce, bytes memory _signature)
        public
        view
        onlyRole(ADMIN_ROLE)
        returns (uint256)
    {
        require(verify(_type, _nonce, _signature), "signature is not correct");
        return _key;
    }

    // 更新密钥,不能加参数只能线上更新
    function updateKey() public onlyRole(ADMIN_ROLE) {
        _setKey();
    }
}

utils/CipherGenesVerifySignature.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;
import "@openzeppelin442/contracts/access/AccessControl.sol";

abstract contract CipherGenesVerifySignature is AccessControl {
    address public signaturer;

    function changeSignaturer(address value)
        public
        onlyRole(DEFAULT_ADMIN_ROLE)
    {
        _changeSignaturer(value);
    }

    function _changeSignaturer(address value) internal {
        signaturer = value;
    }


    function getMessageHash(
        address owner,
        address contract_addr,
        uint256 t,
        uint256 _nonce
    ) public pure returns (bytes32) {
        return keccak256(abi.encodePacked(owner, contract_addr, t, _nonce));
    }

    function getEthSignedMessageHash(bytes32 _messageHash)
        public
        pure
        returns (bytes32)
    {
        return
            keccak256(
                abi.encodePacked(
                    "\x19Ethereum Signed Message:\n32",
                    _messageHash
                )
            );
    }

    function verify(
        uint256 t,
        uint256 _nonce,
        bytes memory signature
    ) public view returns (bool) {
        bytes32 messageHash = getMessageHash(
            signaturer,
            address(this),
            t,
            _nonce
        );
        bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash);
        return recoverSigner(ethSignedMessageHash, signature) == signaturer;
    }

    function recoverSigner(
        bytes32 _ethSignedMessageHash,
        bytes memory _signature
    ) public pure returns (address) {
        (bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature);
        return ecrecover(_ethSignedMessageHash, v, r, s);
    }

    function splitSignature(bytes memory sig)
        public
        pure
        returns (
            bytes32 r,
            bytes32 s,
            uint8 v
        )
    {
        require(sig.length == 65, "invalid signature length");
        assembly {
            r := mload(add(sig, 32))
            s := mload(add(sig, 64))
            v := byte(0, mload(add(sig, 96)))
        }
    }
}

utils/Uint256s.sol

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Uint256s {

    /**
     * @dev leng
     */
    function getLength(uint256 x) internal pure returns (uint256) {
        uint256 len = 0;
        while(x != 0){
            len++;
            x = x / 10;
        }
        return len;
    }

    /**
     * @dev leng
     */
    function revertse(uint256 x) internal pure returns (uint256) {
        uint256 result = 0;
        while(x != 0){
            result = result * 10 + x % 10;
            x = x / 10;
        }
        return result;
    }

    // 84269 26813 53746 27964
    function revertse1(uint256 x,uint256 len) internal pure returns(uint256)
    {
        uint256 remainder = 6;
        uint256 digit = 10;
        uint256 result = 0;
        for(uint256 i = 0; i < remainder; i++){
            result = result * digit + x % digit;
            x = x / digit;
        }
        result = result * (10 ** (len - remainder)) + x;
        return result;
    }

    function revertse2(uint256 x,uint256 len) internal pure returns(uint256)
    {
        uint256 remainder = 6;
        uint256 digit = 10;
        uint256 result = 0;
        uint256 divisor = 10 ** (len - remainder);
        uint256 x2 = x / divisor;
        for(uint256 i = 0; i < 6; i++){
            result = result * digit + x2 % digit;
            x2 = x2 / digit;
        }
        x = x % divisor;
        result = x * (10 ** remainder) + result;
        return result;
    }
}

服务端代码

签名api

    #[Security("is_granted('ROLE_USER')")]
    #[Route(path: "/api/signature", name: "signature", methods: ["GET"])]
    public function signature(Request $request, ShuShuService $shushu): JsonResponse
    {
        $uid      = $this->getUser()->getId();
        $address  = $this->getUser()->getAddress();
        $token_id = $request->get('token_id');
        if (!$token_id) {
            return $this->json(['code' => 400, 'message' => 'Missing parameter token_id'], 400);
        }

        /** @var \Doctrine\ORM\EntityManager $game_em */
        $game_em = $this->getDoctrine()->getManager('DerbyUserData');
        $xxService = new XxContractService($game_em);

        // 一系列判断,开源的话 这段代码被我删了
        

        // 加锁5s
        $lock = Lock::acquireLock("xx_start_" . $this->getUser()->getId(), 5);
        if (!$lock) {
            return $this->json(['code' => 400, 'message' => 'Operation too frequent!'], 400);
        }

        // 生成genes
        try {
            $genes = "这是要加密的字段"
            // 签名
            $genes = new BN($genes, 16);
            /** @var \App\Service\Tron\WakeupService $erc721 */
            $erc721         = Web3Service::getInstance()->getContract('xx');
            $expirationTime = time() + WakeupService::WAKEUP_EXPIR_TIME;
            $sign           = $erc721->soliditySignature($horse_id, $genes, $expirationTime);
			// 加密
            $genes_encrypt  = CipherGenes::getInstance()->encryptionV2($genes->toString());
            
            return $this->json([
                'code'           => 200,
                'v'              => 2, // 加密版本
                'expirationTime' => $expirationTime,
                'genes_encrypt'  => $genes_encrypt, // 返回加密的字段
                'signature'      => $sign['signature'],
                'nonce'          => $sign['nonce'],
                'len'            => strlen($genes_encrypt),
            ]);
        } catch (\Exception $e) {
            return $this->json(['code' => $e->getCode(), 'message' => $e->getMessage()], 400);
        }
    }

加密类 CipherGenes.php

<?php

namespace App\Support;

use App\Service\Web3Service;
use App\Support\BigInteger as SupportBigInteger;
use phpseclib\Math\BigInteger;

class CipherGenes
{
    public static $cg_cache_key_key = "cipher_genes_key";
    public static $cg_cache_type_key = 'cipher_genes_type';
    /** @var \Predis\Client|null */
    private $redis = null;

    public static function getInstance(): static
    {
        return new static();
    }

    public function __construct()
    {
        $this->redis = new \Predis\Client(
            [
                'scheme' => 'tcp',
                'host' => $_ENV['REDIS_HOST'],
                'port' => $_ENV['REDIS_PORT'],
            ],
            [
                'prefix' => 'market:' . $_ENV['BLOCKCHAIN'] . ':',
                'parameters' => [
                    'password' => $_ENV['REDIS_PASS'],
                    'database' => 10,
                ]
            ]
        );
    }

    /**
     * 获取type
     */
    public function getGenesType(): int
    {
        $type = $this->redis->get(self::$cg_cache_type_key);
        return $type ?: $this->updateGenesType();
    }

    /**
     * 更新type
     */
    public function updateGenesType($type = false): int
    {
        /** @var \App\Service\Binance\CipherGenesService $cipherGenes */
        /** @var \App\Service\Ethereum\CipherGenesService $cipherGenes */
        /** @var \App\Service\Tron\CipherGenesService $cipherGenes */
        $cipherGenes = Web3Service::getInstance()->getContract("CipherGenes");
        $type = $type ?: Web3Service::decodeParameter('uint256', $cipherGenes->callMethod('_type'))->toString();
        $this->redis->set(self::$cg_cache_type_key, $type);
        return $type;
    }

    /**
     * 获取密钥
     */
    public function getGenesKey(): string
    {
        // (new FilesystemAdapter())->delete($_ENV['BLOCKCHAIN'] . '_cipher_genes_key');
        $key = $this->redis->get(self::$cg_cache_key_key);
        return $key ?: $this->updateGenesKey();
    }

    /**
     * 更新密钥
     */
    public function updateGenesKey(): string
    {
        $type = $this->getGenesType();
        // echo $type . PHP_EOL;
        /** @var \App\Service\Binance\CipherGenesService $web3Service */
        /** @var \App\Service\Ethereum\CipherGenesService $web3Service */
        /** @var \App\Service\Tron\CipherGenesService $web3Service */
        $web3Service = Web3Service::getInstance()->getContract("CipherGenes");
        // 签名、怕调用盲盒或者其他合约有签名数据然后套取key
        list(
            'nonce'     => $nonce,
            'signature' => $signature
        ) = $web3Service->typeSign($type);
        $key = $web3Service->getKey($nonce, $signature);
        $this->redis->set(self::$cg_cache_key_key, $key);
        // $this->redis->expire(self::$cg_cache_key_key, 60 * 24 * 30);
        return $key;
    }

    /**
     * 加密
     * @param string $genes
     * 
     * @return string
     */
    public function encryption(string $genes): string
    {
        $genes  = new BigInteger($genes);
        $key    = $this->getGenesKey();
        $strict = $this->_stricter($key);
        return $genes
            ->bitwise_xor(new BigInteger($key))
            ->bitwise_xor($strict)
            ->add($strict)
            ->toString();
    }

    /**
     * v1加密之后血统的前置位会一致!会被科学家发现数字规律
     * @param string $genes
     * 
     * @return string
     */
    public function encryptionV2(string $genes): string
    {
        $genes  = new BigInteger($genes);
        $key    = $this->getGenesKey();
        $strict = $this->_stricter($key);
        $key    = substr($key, 0, strlen($key) - 3);
        $genes  = $genes
            ->bitwise_xor(new BigInteger($key))
            ->bitwise_xor($strict)
            ->multiply(new BigInteger(10))
            ->add(new BigInteger(1))
            ->toString();
        // 字符串反转后6位补位前置位
        $str = strrev(substr($genes, -6));
        // dump("========");
        // dump($str);
        // dump($genes);
        $genes = new BigInteger($str . substr($genes,0,-6));
        // $genes = new BigInteger(strrev($genes));
        // 在进行异或
        return $genes
            ->bitwise_xor($strict)
            ->add($strict)
            ->toString();
    }

    /**
     * 解密
     * @param string $sign
     * 
     * @return string
     */
    public function decryptionV2(string $sign): string
    {
        $genes  = new BigInteger($sign);
        $key    = $this->getGenesKey();
        $strict = $this->_stricter($key);
        $key    = substr($key, 0, strlen($key) - 3);
        $genes  = $genes
            ->subtract($strict)
            ->bitwise_xor($strict)
            ->toString();
        // 前6位反转补位最后
        $str = strrev(substr($genes,0, 6));
        // dump("========");
        // dump($str);
        // dump($genes);
        // dump(substr($genes,6) . $str );
        $genes = new BigInteger(substr($genes,6) . $str );
        // $genes = new BigInteger(strrev($genes));

        $arr   = $genes->subtract(new BigInteger(1))->divide(new BigInteger(10));
        return $arr[0]
            ->bitwise_xor(new BigInteger($key))
            ->bitwise_xor($strict)
            ->toString();
    }

    /**
     * V3
     * @param string $genes
     * 
     * @return string
     */
    public function encryptionV3(string $genes): string
    {
        $key    = $this->getGenesKey();
        $genes  = new BigInteger($genes);
        $strict = $this->_stricter($key);
        $genes  = $genes
            ->bitwise_xor(new BigInteger(substr($key, 0, -2)))
            ->bitwise_xor($strict)
            ->toString();
        // 判断尾数是否是0
        $iszero = 1;
        if (substr($genes, -1) == 0) {
            $iszero = 10;
            $genes = rtrim($genes, '0');
        }
        // 字符串反转,有0补0
        $genes  = (new BigInteger(strrev($genes)))->multiply(new BigInteger($iszero));
        // 秘钥长度与明文一致
        $len = strlen($key) - strlen($genes->toString());
        $newKey = $len ? substr($key, 0, strlen($genes->toString())) : $key;
        // 在进行异或
        return $genes
            ->bitwise_xor(new BigInteger($newKey))
            ->add($strict)
            ->toString();
    }

    /**
     * v3解密
     * @param string $sign
     * 
     * @return string
     */
    public function decryptionV3(string $sign): string
    {
        $key    = $this->getGenesKey();
        $strict = $this->_stricter($key);
        $genes  = new BigInteger($sign);
        $genes  = $genes->subtract($strict);
        $len    = strlen($key) - strlen($genes->toString());
        $newKey = $len ? substr($key, 0, strlen($genes->toString())) : $key;
        $genes  = $genes->bitwise_xor(new BigInteger($newKey));
        // 判断尾数是否是0
        $iszero = 1;
        if (substr($genes->toString(), -1) == 0) {
            $iszero = 10;
        }
        $genes  = new BigInteger(strrev($genes));
        return $genes
            ->multiply(new BigInteger($iszero))
            ->bitwise_xor(new BigInteger(substr($key, 0, -2)))
            ->bitwise_xor($strict)
            ->toString();
    }

    /**
     * 解密
     * @param string $sign
     * 
     * @return string
     */
    public function decryption(string $sign): string
    {
        $key    = $this->getGenesKey();
        $strict = $this->_stricter($key);
        return (new BigInteger($sign))
            ->subtract($strict)
            ->bitwise_xor(new BigInteger($key))
            ->bitwise_xor($strict)
            ->toString();
    }

    /**
     * 加严
     */
    private function _stricter($key): BigInteger
    {
        $bi  = new SupportBigInteger($key);
        $str = $bi->mod(1e6)->toString();
        return new BigInteger($str);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
FISCO-BCOS智能合约支持使用C++编写智能合约,因此可以在智能合约使用SM4算法的C++源码实现。以下是一个简单的示例: ```cpp #include <openssl/evp.h> #include <string.h> extern "C" { #include "sm4.h" } // 使用OpenSSL库实现SM4算法加密 std::string sm4_encrypt_openssl(const std::string& key, const std::string& iv, const std::string& data) { EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX_init(ctx); // 设置加密算法和模式 EVP_EncryptInit_ex(ctx, EVP_sms4_cbc(), NULL, (const unsigned char*)key.c_str(), (const unsigned char*)iv.c_str()); // 执行加密操作并获取加密后的数据 int len = data.length(); int ciphertext_len = len + EVP_MAX_BLOCK_LENGTH; unsigned char* ciphertext = new unsigned char[ciphertext_len]; int outlen; EVP_EncryptUpdate(ctx, ciphertext, &outlen, (const unsigned char*)data.c_str(), len); ciphertext_len = outlen; EVP_EncryptFinal_ex(ctx, ciphertext + outlen, &outlen); ciphertext_len += outlen; // 转换为十六进制字符串返回 std::string result; for (int i=0; i<ciphertext_len; i++) { char buf[3]; snprintf(buf, sizeof(buf), "%02x", ciphertext[i]); result.append(buf); } delete[] ciphertext; return result; } // 使用国密SM4算法加密 std::string sm4_encrypt_sm(const std::string& key, const std::string& iv, const std::string& data) { unsigned char* plaintext = new unsigned char[data.length() + 1]; strcpy((char*)plaintext, data.c_str()); // 加密 unsigned char* ciphertext = new unsigned char[data.length() + 1]; memset(ciphertext, 0, data.length() + 1); unsigned char* tmp_key = new unsigned char[key.length() + 1]; strcpy((char*)tmp_key, key.c_str()); unsigned char* tmp_iv = new unsigned char[iv.length() + 1]; strcpy((char*)tmp_iv, iv.c_str()); sm4_context ctx; sm4_setkey_enc(&ctx, tmp_key); sm4_crypt_cbc(&ctx, SM4_ENCRYPT, data.length(), tmp_iv, plaintext, ciphertext); // 转换为十六进制字符串返回 std::string result; for (int i=0; i<data.length(); i++) { char buf[3]; snprintf(buf, sizeof(buf), "%02x", ciphertext[i]); result.append(buf); } delete[] plaintext; delete[] ciphertext; delete[] tmp_key; delete[] tmp_iv; return result; } ``` 其,`sm4_encrypt_openssl`使用OpenSSL库实现SM4算法加密,`sm4_encrypt_sm`使用国密SM4算法加密。在使用国密SM4算法加密时,需要包含国密SM4算法的头文件,并调用其API实现加密操作。 请注意,由于国密SM4算法的限制,其密钥长度必须为16个字节,IV长度必须为16个字节。在实际使用时,需要根据实际情况生成合适的密钥和IV。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值