1 概述

本文主要讲述了如何利用Openssl生成ECDSA密钥对,并利用Auth0库进行Token生成及验证的过程。

2 ECDSA

2.1 简介

ECCElliptic Curve Cryptography,椭圆曲线加密)是一种基于椭圆曲线数学的公钥加密算法,而ECDSA是使用ECC对数字签名算法(DSA)的模拟,总的来说ECC相比起常见的RSA更加安全并且生成密钥对的过程会更快。本文不会涉及过多原理性的东西,只是作简单的介绍,想要详情了解这些算法的可以戳这里。

2.2 密钥对生成

Openssl中生成ECDSA密钥对的流程如下:

openssl ecparam -genkey -name secp521r1 -out private.pem #生成私钥
openssl ec -in private.pem -pubout -out public.pem #生成公钥

参数说明如下:

  • ecparamEC参数设置以及生成命令
  • -genkey:使用特定参数生成EC私钥
  • -nameec参数,可以使用openssl ecparam -list_curves查看,这里用的是secp521r1
  • -out:输出文件名
  • ecEC密钥处理命令
  • -in:输入文件
  • -pubout:默认情况下会输出私钥,加上该选项会变成输出公钥(如果输入是公钥的情况下该参数会自动设置)

执行完命令后就成功生成密钥对了,可以查看一下:

密钥对生成之后就可以准备一下生成Token了。

3 Auth0中的Token应用

3.1 Auth0

Auth0提供了验证以及授权服务,这里利用官方提供的Java实现去生成Token(这里插一句题外话,Java常用的Token实现还有一个叫JJWT的库),首先引入包:

<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.12.0</version>
</dependency>

Gradle

compile group: 'com.auth0', name: 'java-jwt', version: '3.12.0'

引入后来看一下支持的加密算法,如下图:

最简单的使用HMAC算法生成的Token如下:

System.out.println(JWT.create().withIssuer("issuer").withAudience("content").sign(Algorithm.HMAC512("password")));

当然这不是本文的重点,本文的重点是介绍如何利用ECDSA去生成Token

首先Auth0提供的签名api如下:

JWT.create().sign(Algorithm)

其中Algorithm可以取值如下:

想要使用ECDSA算法需要提供一个ECDSAKeyProvider或一个ECPublicKey和一个ECPrivateKey,这里选择后一种方式实现。

3.2 密钥对处理

官方并没有提供如何生成ECPublicKey/ECPrivateKey的方法,甚至连从文件读取密钥对的方法都没有提供,笔者从官方提供的测试代码中发现了如下方法:

其中核心就是读取密钥对的两个方法:

  • readPublicKeyFromFile
  • readPrivateKeyFromFile

import结果可以看到这是一个工具类:

但问题是官方该工具类是测试使用的,换句话说不对外暴露的,在IDEA中直接引入会报错:

因此直接找到该工具类的源码(链接可以戳这里,需要引入bouncycastle包,Maven仓库链接可以戳这里)

package com.auth0.jwt;import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;public class PemUtils {private static byte[] parsePEMFile(File pemFile) throws IOException {if (!pemFile.isFile() || !pemFile.exists()) {throw new FileNotFoundException(String.format("The file '%s' doesn't exist.", pemFile.getAbsolutePath()));}PemReader reader = new PemReader(new FileReader(pemFile));PemObject pemObject = reader.readPemObject();byte[] content = pemObject.getContent();reader.close();return content;}private static PublicKey getPublicKey(byte[] keyBytes, String algorithm) {PublicKey publicKey = null;try {KeyFactory kf = KeyFactory.getInstance(algorithm);EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);publicKey = kf.generatePublic(keySpec);} catch (NoSuchAlgorithmException e) {System.out.println("Could not reconstruct the public key, the given algorithm could not be found.");} catch (InvalidKeySpecException e) {System.out.println("Could not reconstruct the public key");}return publicKey;}private static PrivateKey getPrivateKey(byte[] keyBytes, String algorithm) {PrivateKey privateKey = null;try {KeyFactory kf = KeyFactory.getInstance(algorithm);EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);privateKey = kf.generatePrivate(keySpec);} catch (NoSuchAlgorithmException e) {System.out.println("Could not reconstruct the private key, the given algorithm could not be found.");} catch (InvalidKeySpecException e) {System.out.println("Could not reconstruct the private key");}return privateKey;}public static PublicKey readPublicKeyFromFile(String filepath, String algorithm) throws IOException {byte[] bytes = PemUtils.parsePEMFile(new File(filepath));return PemUtils.getPublicKey(bytes, algorithm);}public static PrivateKey readPrivateKeyFromFile(String filepath, String algorithm) throws IOException {byte[] bytes = PemUtils.parsePEMFile(new File(filepath));return PemUtils.getPrivateKey(bytes, algorithm);}
}

直接复制该工具类后,将前一步生成的private.pem以及public.pem放置合适位置,通过工具类读取并生成Token

public class Main {public static void main(String[] args) {try {ECPublicKey publicKey = (ECPublicKey) PemUtils.readPublicKeyFromFile("src/main/resources/public.pem","EC");ECPrivateKey privateKey = (ECPrivateKey) PemUtils.readPrivateKeyFromFile("src/main/resources/private.pem","EC");Algorithm algorithm = Algorithm.ECDSA512(publicKey,privateKey);String token = JWT.create().withIssuer("issuer").sign(algorithm);JWTVerifier verifier = JWT.require(algorithm).build();verifier.verify(JWT.decode(token));} catch (Exception e) {e.printStackTrace();}}
}

但是会报错说私钥是null

从官方issue中查到了类似的问题:

回答说是密钥格式的问题,其中提到的pkcs8是私钥格式转换命令:

将私钥的格式进行转换:

openssl pkcs8 -topk8 -inform pem -in private.pem -outform pem -nocrypt -out newprivate.pem

参数说明:

  • pkcs8:私钥格式转换命令
  • -topk8:读取私钥并转换为PKCS#8格式
  • -inform:指定输入格式,默认pem,使用该参数并配合-topk8后会生成加密后的PKCS#8格式的私钥
  • -in:输入文件
  • -outform:与-inform类似
  • -nocrypt:在这里主要配合-inform+-topk8使用,生成不加密的PrivateKeyInfo而不是加密的PKCS#8 EncryptedPrivateKeyInfo,因为一些软件(比如某些版本的Java代码)使用的是不加密格式的私钥
  • -out:输出文件

转换后就可以生成Token了。

3.3 生成Token

最后readPrivateKeyFromFile中的参数修改为新的私钥即可:

ECPrivateKey privateKey = (ECPrivateKey) PemUtils.readPrivateKeyFromFile("src/main/resources/newprivate.pem","EC");

4 参考源码

包含了示例密钥对以及如何使用(Gradle版的):

Github​github.com码云​gitee.com项目 · 氷泠 / ECDSA Auth0 Token Demo​codechina.csdn.net

5 参考网站

1、知乎-ECC椭圆曲线加密算法:介绍

2、什么是椭圆曲线数字签名算法(ECDSA)?

3、Elliptic Curve Cryptography: breaking security and a comparison with RSA

4、OpenSSL doc

5、StackExange-https://superuser.com/questions/1103401/generate-an-ecdsa-key-and-csr-with-openssl

6、auth0/java-jwt Issue - ECDSA key version mismatch from openssl pem files #270

7、auth0/java-jwt Github

8、codota-How to useECDSA512methodincom.auth0.jwt.algorithms.Algorithm

公钥生成命令_ECDSA密钥对生成以及在Token中的应用相关推荐

  1. RSA密钥对生成工具代码

    RSA密钥对生成工具 RSA密钥对生成工具 RSA密钥生成 RSA密钥写入文件 RSA密钥生成测试 Github代码仓 RSA密钥对生成工具 最近研究License方案,用到了Java生成RSA公私钥 ...

  2. VS中的预先生成事件和后期生成事件

    VS中的预先生成事件和后期生成事件 原文:VS中的预先生成事件和后期生成事件 在C#开发中,有时候需要在程序编译之前或之后做一些操作. 要达到这个目的,可以使用Visual Studio中的预先生成事 ...

  3. 支付宝打造公共账号业务网关, RSA密钥对生成

    作者: 玉龙      版权全部,同意转载. 请注明出处(创建金融_玉龙  http://www.weibo.com/u/1872245125) 原文地址: http://blog.csdn.net/ ...

  4. 支付宝公众账号商户网关的搭建, RSA密钥对生成

    作者: 玉龙      版权所有,允许转载, 请注明出处(创建金融_玉龙  http://www.weibo.com/u/1872245125) 原文地址: http://blog.csdn.net/ ...

  5. 前后端RSA互相加解密、加签验签、密钥对生成(Java)

    目录 一.序言 二.关于PKCS#1和PKCS#8格式密钥 1.简介 2.区别 二.关于JSEncrypt 三.关于jsrsasign 四.前端RSA加解密.加验签示例 1.相关依赖 2.crypto ...

  6. window10使用命令ssh工具生成github开源中国需要的ssh密钥以及转换为ppk让tortriseGit工具支持它

    不知道大家用过putty没有,那个也可以生成,我以前生成很快的,现在不知道为什么,等待n久还是不行,如果把加密数缩短,还在github还用不了,还是用命令生成秒杀 比较好 .. ssh-keygen ...

  7. oracle取32位唯一码,Oracle导出导入dmp文件命令,以及excel生成32位uuid

    Oracle导出dmp文件命令,以及excel生成64位uuid 导出命令cmd中 expdp mms/xfkjerp@orcl schemas=mms dumpfile=expdp.dmp DIRE ...

  8. 使用 CommandBuilder 生成命令 (ADO.NET)

    DataSet对象有4种典型功能,包括数据 的提取.删除.更新和插入.实际上我们是对DataSet对象的4个属性分别定义相应的SQL语句来完成的.比如,对SelectCommand对象定义 Selec ...

  9. JAVA编译成文件的说法_下列关于使用Javac命令编译后生成文件的说法中,正确的是?...

    下列关于使用Javac命令编译后生成文件的说法中,正确的是? 答:编译后生成的文件可以在Java虚拟机中运行\n\n编译后生成的文件为二进制文件\n\n编译后生成文件的后缀名为.class 线性表的链 ...

最新文章

  1. PTA团体程序设计天梯赛-L2-024 部落
  2. java中native的用法[转]
  3. FPGA内部电源管理详解
  4. python 日期 间隔_Python datetime time 等时间 日期 之间的计算和相互转化
  5. http协议的各类状态码
  6. js检查元素是否包括在数组中
  7. windows c++ 原子操作_高分辨质谱数据处理操作篇
  8. HDU6268 Master of Subgraph
  9. 修电脑入门名词及等级划分
  10. mysql一张表有几个主键_一张表可以有多少个主键
  11. 智慧农业实验室第一次成果
  12. MSSQL 负载均衡(Moebius)
  13. gogo/protobuf proto.GoGoProtoPackageIsVersion2、proto3 版本 不一致
  14. beautiful report 的简单使用
  15. 小酷智慧地图3D导览v1.0.82 打卡定位 地图打卡
  16. SQL server 2008R2 入门
  17. C语言实现打印某年某月的日历
  18. 冲鸭!羊毛薅起来!当当618专享不到4折,Python书籍囤起来!
  19. node.js+vue.js+mysql实现登录注册的功能(前后端分离)
  20. 关于IC封装的目的及其发展历程

热门文章

  1. E都市(福州)地图分析
  2. springboot 秒杀系统(一)
  3. python3 array为什么不能放不同类型的数据_想快速学会数据可视化?这里有一门 4 小时的 Kaggle 微课程...
  4. 成功者所应具有的九大素质
  5. android listview item宽度,为什么listview的item大小不一样
  6. python处理颜色rgb_使用python获得N个区分度较高的RGB颜色值
  7. 【c++】龟兔赛跑问题
  8. 获取用户当前周期(1=》月经期,2=》排卵期,3=》安全期)
  9. easyuefi删除ubuntu_ubuntu双系统卸载教程
  10. Nodejs安装配置