tron ECC使用及项目中的应用

2023-10-23 14:40:24 浏览数 (1)

简述

ECC(Elliptic Curves Cryptography,椭圆曲线密码编码学)是一种公开密钥算法。基于椭圆曲线数学的公开密钥加密算法,其本质是利用离散对数问题实现加密。 ECC的主要优势,是在使用更小的密钥的同时,提供更快的性能和更高等级的安全。 网上的理论大都讲的非常透彻,我也是看了很多,但是实际能力有限,对数论层面的只停留在浅薄的理解上,不敢乱讲。但是可以简单的说明其原理。

还有一点,加密算法包括RSAECC并不是不可以被破解,只是以当下现代计算机的计算性能算起来比较费劲,理论上破解ECC需要最少250万年,其破解的代价很高,以此来达到不可破解目的。 用量子计算?不说现在有量子技术可不可么,假设量子计算可是可行的,那为什么不升级到量子加密?

ECC: 基于椭圆曲线和离散对数

其原理是数论理论中的单向运算函数,这种函数有一个特点:正方向计算容易,反方向计算却十分困难。 啥意思?就是计算:

1234 * 4567 = ?

计算这个简单,结果是:5635678。 那么,返过来计算:

5635678 = x * y

这样就不好计算了,而且结果有很多种有可能是:

5635678 = 1 * 5635678 5635678 = 2 * 2817839 5635678 = 3 * 1408919.5

都有可能。

应用

在编程领域最难的是0到1的过程,而复用前人的技术和经验上就比较轻松。 在对ECC的使用上,已经将这一算法简化到接口层面,通过调用接口来获提需要的安全性。

BouncyCastle 加密工具包

BouncyCastle(轻量级密码术包)是一种用于 Java 平台的开放源码的轻量级密码术包;Bouncycstle 包含了大量的密码算法,其支持椭圆曲线密码算法,并提供JCE 1.2.1的实现。它提供了Java标准库没有的一些算法,例如,RipeMD160哈希算法。

TRON 中也是使用的这个算法工具包。 官网:https://www.bouncycastle.org/

ECKey 类

ECC 类是对加密工具的一个抽象,从类的Copyright上可以看到,这个类实际上是从ethereumJ拿过来的。好的设计都是相通的。

ECC在TRON中,创建账号的时候的用法:

1.获取一个ECKey 对象 2.获得私钥 3.获得公钥

通过 TRON 中生成账户这个接口来,非常典型

代码语言:javascript复制
@Component
@Slf4j(topic = "API")
public class GenerateAddressServlet extends RateLimiterServlet {

  protected void doGet(HttpServletRequest request, HttpServletResponse response) {
    try {
      // 获得一个Sign 接口用来获得私钥
      SignInterface sign = SignUtils.getGeneratedRandomSign(Utils.getRandom(),
          Args.getInstance().isECKeyCryptoEngine());
      // 获得私钥
      byte[] priKey = sign.getPrivateKey();
      // base58check 地址,我在之前的文章的专门讲过这个格式
      byte[] address = sign.getAddress();
      // 转成 十六进制字符串,这个也就是通常意义是的私钥,不能丢
      String priKeyStr = Hex.encodeHexString(priKey);
      // 推出 base58check 地址
      String base58check = StringUtil.encode58Check(address);
      String hexString = ByteArray.toHexString(address);
      JSONObject jsonAddress = new JSONObject();
      jsonAddress.put("address", base58check);
      jsonAddress.put("hexAddress", hexString);
      jsonAddress.put("privateKey", priKeyStr);
      // 回写给前端,可以是页面、postman
      response.getWriter().println(jsonAddress.toJSONString());
    } catch (Exception e) {
      Util.processError(e, response);
    }
  }

  protected void doPost(HttpServletRequest request, HttpServletResponse response) {
    doGet(request, response);
  }
}

调一下试试,反复多调几次可以生成不同的私钥

curl -X GET http://127.0.0.1:8090/wallet/generateaddress

结果关键是拿到私钥,然后通过私钥获得公钥、base58check:

address: TNV7s8K96ZgEiFDuecSXvzKKJgkXwtjkWi hexAddress: 418949b347588b1901fdf3b6e6dc80dffcd385c4de privateKey: f7252a484bc631e57910cf65481b12c32b2906fa05742c72f27669b9ddc5d871

使用就是这么简单,可以本地起一个FullNode自行调用接口,产生新的私钥,并没有中心化节点的之间的通信,也可以调用官方节点的接口,都是一样的。可以反复生成私钥,用来测试。

看下SignUtils.getGeneratedRandomSign是怎么处理

代码语言:javascript复制
public static SignInterface getGeneratedRandomSign(
    SecureRandom secureRandom, boolean isECKeyCryptoEngine) {
  //安全的随机数,在java中Random是伪随机数,并不安全,SecureRandom 是安全的随机数
  // isECKeyCryptoEngine = true
  if (isECKeyCryptoEngine) {
    return new ECKey(secureRandom);
  }
  return new SM2(secureRandom);
}

完整示例

使用一个完整的例子来看看怎么用。

代码语言:javascript复制
public static void test() {
  // 生成一个 ECKey 对象
  ECKey ecKey = new ECKey(Utils.getRandom());
  String privateKey = ByteArray.toHexString(ecKey.getPrivKeyBytes());
  String publicKey = Hex.toHexString(ecKey.getPubKey());
  byte[] hexAddress = ecKey.getAddress();
  String base58check1 = PublicMethed.getAddressString(privateKey);
  String base58check2 = StringUtil.encode58Check(hexAddress);
  String bash58check3 = Base58.encode58Check(hexAddress);

  System.out.println("private key: "   privateKey);
  System.out.println("public key"    publicKey);
  System.out.println("hex address1: "   ByteArray.toHexString(hexAddress));
  System.out.println("base58check1: "   base58check1);
  System.out.println("base58check2: "   base58check2);
  System.out.prntln("bash58check3: "   bash58check3);
  ByteString bytes = ByteString.copyFrom(Commons.decodeFromBase58Check(base58check1));
  System.out.println("hex address2: "   ByteArray.toHexString(bytes.toByteArray()));
}

base58check 地址

base58check是一种特殊的格式,我在之前的文章中讲过个格式。看看它是怎么实现的。 TRON 中有两处需要使用到base58check格式:

  1. 私钥address
  2. 账户address

基本上账户的address用的多,在转账交易中base58check地址用的是最多的。 base58check就是给人看的,实际数据存到数据库中就是byte[]。

看下 base58check 的工作原理:将输入数据进行两次hash后,截取部分数据进行base58编码。

代码语言:javascript复制
public static String encode58Check(byte[] input) {
  byte[] hash0 = Sha256Hash.hash(CommonParameter.getInstance().isECKeyCryptoEngine(), input);
  byte[] hash1 = Sha256Hash.hash(CommonParameter.getInstance().isECKeyCryptoEngine(), hash0);
  byte[] inputCheck = new byte[input.length   4];
  System.arraycopy(input, 0, inputCheck, 0, input.length);
  System.arraycopy(hash1, 0, inputCheck, input.length, 4);
  return Base58.encode(inputCheck);
}

总结

分享了一下ECC的用法,使用场景上不同链的用法也都是大同小异,明白几个概念,在关键处不至于被卡住。 学习方法我不断强调先熟练使用,再谈理解。 总是会有朋友跟我谈如何学习、理解这个问题,总觉得自己不聪明、理解不了。排除每个各人的理解能力,只谈投入时间,如果没有达到称的上努力的程度,请先不要谈悟性,如果你做不到看一眼一分钟内就理解,那么每天最少一小时的时间成本投入都没有,那先不要谈悟性。 时间也是成本,不要吝啬在重要的事情上投入时间

0 人点赞