Java PublicKey对象与base64格式数据转化

Java中要生成PublicKey需要KeyPair对象,先生成KeyPair,通过KeyPairGenerator,这需要结合算法并设置长度,常用的为RSA,长度可以是 1024,2048等。示例如下:

        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
assertNotNull(keyPair);

PrivateKey aPrivate = keyPair.getPrivate();
PublicKey aPublic = keyPair.getPublic();

//base64
String base64PrivateKey = new String(Base64.encodeBase64Chunked(aPrivate.getEncoded()));
// System.out.println(base64PrivateKey);
String base64PublicKey = new String(Base64.encodeBase64Chunked(aPublic.getEncoded()));
// System.out.println(base64PublicKey);

使用Base64可将生成的PublicKey,PrivateKey转化为方便传输的 base64格式数据,转化后的PublicKey数据如:

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq7h9NrI7OF4m2R53nemmih4N2ds13n/L
ARfFO1hDGKwE36iU+bCLlkw59gPrWgcsc4lKqVrQC3S3NlBIbkX7pcP2zGth3j5uCfM9DOnM+Jxg XyYVDf9YduuevII142BmG/5CGjrdJmDS4wdUZ+vXJPiSGXMdpRM4+p8jcPoZ71YUPJzxu9pOgD37 RL1UdD3wvM63sixPSmmwTua4GExcKnNZzeiM91UqvI90CG+gH/YG0hf2Pnd5ACquToFLPsUn95d6 cqIERTDi8NiBzB/AhlISM69IDnLhRdU8YjZuxoaFZhQT8eZ6Qhr75/aiUu0zN3aNeOHnrJHKV/Lq
xng6VQIDAQAB

当需要使用时可通过 KeyFactory 将base64数据转化为具体的PublicKey或PrivateKey对象。代码如下:

KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(base64PrivateKey));
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
assertNotNull(privateKey);
assertEquals(privateKey, aPrivate);


PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(Base64.decodeBase64(base64PublicKey)));
assertNotNull(publicKey);
assertEquals(publicKey, aPublic);

转化后的对象与原生的是一样的,可用于加密/解密, 签名验签等。

代码链接:https://gitee.com/mkk/MyOIDC/blob/b14bb9ef6da6ca6235b2f705cbd713fbe97f6436/myoidc-server/src/test/java/myoidc/server/service/business/RSAPublicKeyTest.java

专利:2016102613273 单点登录技术中的主令牌获取方法、单点登录方法及系统

技术专利:2016102613273 单点登录技术中的主令牌获取方法、单点登录方法及系统。

摘要 本发明提供的单点登录技术中的主令牌获取方法,涉及互联网领域,该方法通过手机端首先要通过识别码下发服务器的验证来换取识别码,之后在期望获取主令牌的时候,使用手机端将该识别码发送给令牌颁发服务器,之后令牌颁发服务器将该识别码提供给识别码下发服务器进行验证,只有该次验证通过后,令牌颁发服务器才会将对应的主令牌提供给手机端,这样,即使外部设备知悉了账户和密码,由于外部设备无法通过识别码下发服务器的验证,导致其依旧无法获取主令牌,保证了主令牌下发的安全性,也就保证了单点登录整体的安全性。

http://epub.cnipa.gov.cn/certifdesc.action?strWhere=CN105959267B

OAuth 2.1的状态与主要特征

经过多年的OAuth 2.0协议的发展,最新版本的 OAuth 2.1 协议已经在进行中,可访问 https://oauth.net/2.1/ 获取最新的相关信息。

2.1版本相比2.0版本的优化或不同点有:

OAuth 2.1

简单点说就是:

  • PKCE变成必须的了
  • Redrect URI的检查更严格
  • grant_type中的password, implicit都不再推荐使用(甚至不再支持)
  • 不再允许通过URL查询参数传递access_token(甚至不再支持)
  • 刷新token增加约束限制(如一次性刷新)

OAuth2.1将变得更加安全,从流程定义与各个端(endpoint)来讲;这也符合网络环境越来越复杂,安全问题越来越高的实际场景。相比传统的client端浏览器与APP来讲,未来的client端会更多样,如智能家居设备,穿戴设备,工业互联设备等。

从另一个方面来说,认证凭证(如常见的 密码)将趋于在授权服务(Authorization Server)中统一进行管理,认证的操作收归到授权服务器端来管控,不再放由client端可知晓(想想grant_type=password中可通过API传递用户凭证是多么的信任client端啊)。

读《聊聊‘架构’》— 尚不够架构

内容摘录:

  • 业务和架构,是压在软件从业人员身上的两座大山。页软件从业人员手上却只有一个武器:技术。可是这个武器还时灵时不灵,
  • 业务和架构都是处理人的问题。而技术人员最讨厌处理的就是人的问题,心里面厌恶,却又无法逃避。
  • 架构的目的并非产生一个业务之外新的东西出来,只是为了让业务长得更加高大强壮,服务于更多的人。
  • 做架构的人必须亲自体验业务,感受业务,才可能真正认识业务的个性,真正认识业务所面临的问题。
  • 识别问题这个能力基本上就决定了架构师的水平。
  • 识别了问题的主体,自然而然地就附带了这么多的隐含信息。挖掘出隐含信息,就自然而然能够问出来其他问题了,
  • 架构切分实际就是对利益相关人的利益进行切分或合并,使得每个利益相关人的权责是对等的,每个利益相关人可以为自己的利益负责。
  • 架构切分的最终结果都会体现在组织架构上,只有这样才能够让架构落地并推进。
  • 一个好的架构拆分,会形成一棵树,慢慢会长成一片森林。
  • 架构的目的就是为了增长。
  • 架构师有权力的同时也有其义务,也是权责对等的。架构师要时时把增长放在自己的第一考虑要素,把识别核心生命周期及其主体作为第一思考,这样才能确保权力的合理分配,保证增长的效率。这是真正的架构师和普通人思考的区别。
  • 要知道,工作是否完成由业务人员决定,而不是软件工程师自己。
  • 随着对业务的熟悉,对时间的恐惧才会慢慢地消失。对业务领域理解得越深入,就越知道如何去发现问题,慢慢就成为业务专家了。
  • 形象一点说,业务是硬币,架构和技术是硬币的两面。
  • 要知道开源的只是代码而已,而代码并非软件生命周期的核心。
  • 软件生命周期的核心是代码的运行生命周期和用户访问生命周期,而不是代码的建立生命周期。
  • 很多软件工程师学了大量的算法和计算机基础,然而在工作中发现派不上用场。这是非常正常的,因为这些内容是为了在科学领域做研究准备的。而在业务领域,大多是如何把现有的业务在软件中模拟出来的问题,并没有太多高深的数学问题。
  • 软件的拆分必须要和业务的拆分对应起来,
  • 很多人总是拆不好的原因,就是忽视了业务生命周期的分析。因为软件的核心是模拟业务,而业务代码又是按照业务的生命周期组织的,
  • 大数据其实说的是新的针对大量数据的处理技术,并非“大数据”这个概念表面文字那样是说“数据”本身。
  • 数据库事务只应该存在于和数据库打交道的存储代码中。

 

推荐你去品一品此书。

20210110221948

 

 

2021年阅读计划

阅读自有书,2021阅读计划

  1. 《暗网I:揭秘数字货币骗局》
  2. 《区块链:新经济蓝图及导读》1月
  3. 《习惯的力量》2月
  4. 《兴趣变现》
  5. 《起源 万物大历史》
  6. 《逼近的瘟疫》1月
  7. 《富爸爸,穷爸爸》1月
  8. 《30岁之后,用钱赚钱》2月
  9. 《巴菲特致股东的信》
  10. 《商业简史》刘润著
  11. 《像火箭科学家一样思考》
  12. 《规模 复杂世界的简单法则》
  13. 《大器晚成》
  14. 《价值:我对投资的思考》
  15. 《密码工程:原理与应用》

2020年阅读计划

2019年阅读计划

2018年阅读计划

2017年阅读计划

2016年及之前所看之书

OAuth2中token升级使用JWT的实现参考

OAuth2中默认使用 Bearer Tokens (一般用UUID值)作为token的数据格式,但也支持升级使用JSON Web Token(JWT)来作为token的数据格式。

20200918101526

下面以 spring-oauth-server 升级使用JWT来说明

重点在于提供一个 JwtTokenStore的配置类,详细可参见 MyOIDC 工程中的配置:https://gitee.com/mkk/MyOIDC/blob/master/myoidc-server/src/main/java/myoidc/server/config/OAuth2ServerConfiguration.java

需要注意的是底层使用的算法,可以是RSA也可以对称加密的HMAC等,具体可查看 JwtAccessTokenConverter.java 类。

对应的工程中需要增加 spring-security-jwt 库的依赖(如果是Maven工程)。

 

OIDC中JWK,JWKS的介绍与使用

JWKS全称为 JSON Web Key Set,是指多个JWK组合在一起的一种格式(详见 https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41#section-5 );

JWK全称是JSON Web Key,其标准协议链接:https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41

JWK在OIDC中的主要作用是为JWT(id_token)提供加密密钥,用于加密/解密或签名/验签,是JSON格式的数据。

综上所说,掌握了如何生成JWK,再按照JWKS协议的要求组合起来即可。根据使用不同的加密算法,各种算法的JWK展示内容会有些区别,一个使用RSA算法的JWK格式的数据如下,使用jose4j生成:

{
  "kty": "RSA",
  "kid": "myoidc-keyid",
  "use": "sig",
  "alg": "RS256",
  "n": "xMNL1jDatbHWGDH_H9GZbb2R4Ck2ga-lfE6wJnno_MfqJibSqkiLTZ7P06woJFxzB0WDu2PBe-ptRNoJhEnkzL8c1mgbGOdPVCsaaDm-POGZ3gnWGcyzyuJ9s9km41Rlan3TuuC3HIniY4bmyQAZ-SLwrFk7Bfa91ui4F9S5RvM",
  "e": "AQAB",
  "d": "q73XDM65p8vgll_VUn2NUPcdQ65VUB7y76xzHjJchX8tRj2utUj6pjaPKi_jHdG_6UHouIBa2oEE_QrfMaOZ2wA6LgYPXT_a296LKoOtKKRUlgob_leHxn0FJxLOXtEHgMqDgtMQ1-eFipsFgriip94dmcLEWW3YVK_y5JwJrnE",
  "p": "7OqN19bEbMb9cr9zA98QQq9LOgvQfq5-nOvzwMsubqMosHxViRnivFz2-3LpusK7u2XEG5EljqUxZrf4lgeVmw",
  "q": "1Jy9ksoLuQ5tuc4docgLaXQWqf3iaTm3iC07AA4v9jHzvnkewWFS_PUPPcra4475Dew-y7oIENaRBMijrrWViQ",
  "dp": "HBEdhLh4xLo-RF3R7l96uauyqcnEhX1-mnCJjAmGEq1ZoK7aI0fhyJbq25cdgXaYbvb7aJilbmS7mYOp-3wiiQ",
  "dq": "NRMLn-EgHAomCgQSEZjGgISiQ71FD8-AqVXhLJpeDq9ZkWra6ptJBCyIqXxCOBwwv_EBnAnMiaeGfBM6CRr7QQ",
  "qi": "VCdAeu4h25X_kM69Netc3SKPo5P-1VjeSHz0Ko0QuSMF0INc6H2yi7hZgZuYANVaTF1Ipf6lWfHBLpuRGh3lXw"
}

JWK数据的格式具体可参见 https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41#section-4

主要属性:kty(Key类型),use(两个可选值:sig or enc),alg(具体的算法),kid(Key的唯一标识id)

 

有了JWK数据,只需要按照JWKS的格式组装成对应的JSON数据即可,以上面的JWK组装的JWKS数据如下:

{
  "keys": [
    {
      "p": "7OqN19bEbMb9cr9zA98QQq9LOgvQfq5-nOvzwMsubqMosHxViRnivFz2-3LpusK7u2XEG5EljqUxZrf4lgeVmw",
      "kty": "RSA",
      "q": "1Jy9ksoLuQ5tuc4docgLaXQWqf3iaTm3iC07AA4v9jHzvnkewWFS_PUPPcra4475Dew-y7oIENaRBMijrrWViQ",
      "d": "q73XDM65p8vgll_VUn2NUPcdQ65VUB7y76xzHjJchX8tRj2utUj6pjaPKi_jHdG_6UHouIBa2oEE_QrfMaOZ2wA6LgYPXT_a296LKoOtKKRUlgob_leHxn0FJxLOXtEHgMqDgtMQ1-eFipsFgriip94dmcLEWW3YVK_y5JwJrnE",
      "e": "AQAB",
      "use": "sig",
      "kid": "myoidc-keyid",
      "qi": "VCdAeu4h25X_kM69Netc3SKPo5P-1VjeSHz0Ko0QuSMF0INc6H2yi7hZgZuYANVaTF1Ipf6lWfHBLpuRGh3lXw",
      "dp": "HBEdhLh4xLo-RF3R7l96uauyqcnEhX1-mnCJjAmGEq1ZoK7aI0fhyJbq25cdgXaYbvb7aJilbmS7mYOp-3wiiQ",
      "alg": "RS256",
      "dq": "NRMLn-EgHAomCgQSEZjGgISiQ71FD8-AqVXhLJpeDq9ZkWra6ptJBCyIqXxCOBwwv_EBnAnMiaeGfBM6CRr7QQ",
      "n": "xMNL1jDatbHWGDH_H9GZbb2R4Ck2ga-lfE6wJnno_MfqJibSqkiLTZ7P06woJFxzB0WDu2PBe-ptRNoJhEnkzL8c1mgbGOdPVCsaaDm-POGZ3gnWGcyzyuJ9s9km41Rlan3TuuC3HIniY4bmyQAZ-SLwrFk7Bfa91ui4F9S5RvM"
    }
  ]
}

以上的JWK,JWKS的示例的完整代码(JAVA实现)可在此查看 https://gitee.com/mkk/MyOIDC/blob/master/myoidc-server/src/test/java/myoidc/server/infrastructure/JWKSTest.java。代码中还包括除RSA外,ECC,OCT的示例实现。

 

JWK本身未定义一种新的加密算法或变种,只是定义一种JSON格式的数据展示(更符合互联网传输),其底层实现依旧依赖PKI体系的技术,如x509,公钥/私钥体系。在其协议介绍中能更好地体现出来。

20200920160628

 

如果是使用非JAVA语言,也可以使用对应的PKI技术生成JWK,如openssl;

一个使用JDK自带的 keytool 工具生成的示例如下:

keytool -genkeypair -alias oidc-demo -validity 180 -keyalg RSA -keypass oidc-demo -keystore oidc-demo.jks -storepass oidc-demo

命令输入后依次填写DN的各类信息,即可生成 oidc-demo.jks文件,密码为 oidc-demo,文件中有私钥公钥等信息。

若需要导出为 x509格式数据,使用keytool命令:

keytool -exportcert -keystore oidc-demo.jks -rfc -file oidc-demo.cer -alias oidc-demo

输入密码后生成的 oidc-demo.cer文件为x509格式。