SM2的非对称加解密Java工具类(bcprov-jdk15on/bcprov-jdk16)

bcprov-jdk15on实现例子

Maven依赖:

Java实现如下:

bcprov-jdk16实现例子

注意

  • 根据国密推荐的SM2椭圆曲线公钥密码算法,首先产生随机数计算出曲线点C1,2个32byte的BIGNUM大数,即为SM2加密结果的第1部分(C1)。第2部分则是真正的密文,是对明文的加密结果,长度和明文一样(C2)。第3部分是杂凑值,用来效验数据(C3)。按国密推荐的256位椭圆曲线,明文加密结果比原长度会大97byte(C1使用EC_POINT_point2oct转换)。

我们可以利用 密文,长度和明文一样(C2)这个原理,来跟踪现实中的调试问题,我们在没办法解密用户输入数据的内容的情况下,可以知道用户输入内容的长度,也能辅助我们解决很多调试问题。

参考链接


synchronized全局锁和实例锁的区别

实例锁 -- 锁在某一个实例对象上。如果该类是单例,那么该锁也具有全局锁的概念。
               实例锁对应的就是synchronized关键字。
全局锁 -- 该锁针对的是类,无论实例多少个对象,那么线程都共享该锁。
               全局锁对应的就是static synchronized(或者是锁在该类的class或者classloader对象上)。

关于“实例锁”和“全局锁”有一个很形象的例子:

假设,Something有两个实例xy。分析下面4组表达式获取的锁的情况。
(01) x.isSyncA()与x.isSyncB() 
(02) x.isSyncA()与y.isSyncA()
(03) x.cSyncA()与y.cSyncB()
(04) x.isSyncA()与Something.cSyncA()

(01) 不能被同时访问。因为isSyncA()isSyncB()都是访问同一个对象(对象x)的同步锁!

(02) 可以同时被访问。因为访问的不是同一个对象的同步锁,x.isSyncA()访问的是x的同步锁,而y.isSyncA()访问的是y的同步锁。

(03) 不能被同时访问。因为cSyncA()cSyncB()都是static类型,x.cSyncA()相当于Something.isSyncA()y.cSyncB()相当于Something.isSyncB(),因此它们共用一个同步锁,不能被同时反问。

(04) 可以被同时访问。因为isSyncA()是实例方法,x.isSyncA()使用的是对象x的锁;而cSyncA()是静态方法,Something.cSyncA()可以理解对使用的是“类的锁”。因此,它们是可以被同时访问的。

参考链接


mybaties连接sqlite,并读取blob类型数据时,报错 java.sql.SQLFeatureNotSupportedException

错误,或者如下错误:

场景:
具体需求,要求像springboot连接mysql或者pgsql数据库一样,在application配置文件中配置sqlite数据库信息,并实现对blob类型数据(我们的库中有该类型的数据)的读写,按照平常一样写好controller、service、dao、mapper.xml后,执行查询操作后报错

原因分析:
sqlite的driver中,JDBC4ResultSet没有实现以下接口:

而是直接抛出了异常。
解决方法:
mapper.xml中该字段的设置:

即blob字段加个typeHandler属性。
然后自定义一个BlobTypeHandler处理类:

注意:实体类中blob字段类型是byte[]。

参考链接


mybaties连接sqlite,并读取blob类型数据时,报 java.sql.SQLException: not implemented by SQLite JDBC driver错误

JsonParser解析json字符串双引号问题

** 今天在项目 中使用到了JsonParser解析json字符串为JsonArray或者JsonObject,解析之后使用 如下代码获取到的字符串多了一层 “”(双引号) **

JSON字符串格式如下

** 如果将这样的字符串直接设值在 yaml 文件中,那么设置完成后的 yaml文件如下: **

** 调试查看之后发现 Jarray.get(k) 获取得到的是 JsonPrimitive对象(会在字符串外面再加一对引号) **

** 弄清楚原因之后我们只要在 Jarray.get(k) 之后再对对象取值就可以了 **

参考链接


JsonParser解析json字符串双引号问题

Jakarta EE - Java EE的终结者

什么是 Jakarta EE

Jakarta EE并不是新技术,他的前身就是大家熟悉的Java EE,老一辈的程序员可能还记得J2EE,是的,他们都是同一个东西,至于为什么会改来改去,这里面就有很多故事了。

1998年12月,SUN公司发布了JDK1.2,开始使用Java 2 这一名称,第二年Sun公司联合IBM、Oracle、BEA等大型企业应用系统开发商共同制订了一个基于Java组件技术的企业应用系统开发规范,名字很自然就取为Java 2 Platform Enterprise Edition简称J2EE,后面的事情大家也知道,JDK版本升的很快,J2EE名称如果跟着Java版本走必然会给开发人员造成困惑不利于该技术的推广,终于在2006年,SUN公司在发布Java 5后正式将J2EE改名为Java EE(Java Platform, Enterprise Edition),很多早期j2ee开发者虽然现在用的是最新的java ee标准但他们还是认为自己在用j2ee,当然,只是名称的改变并没有给开发者带来什么麻烦,相比之下下面这个就是要命。

2009年,Oracle宣布收购SUN,Java相关技术自然归Oracle所有,在2017年,Oracle 宣布开源 Java EE 并将项目移交给 Eclipse 基金会,但Oracle移交的很不痛快,提了很多要求,其中就包括不能再使用Java EE这个名称,虽然有点无理但Eclipse基金会还是接受了这个要求并且改名为Jakarta EE,经历了从j2ee到java ee的改名再经历一次似乎也无所谓,但要命的是Oracle要求Jakarta EE不能修改javax命名空间,这个就意味着java ee移交后代码就此封版,如果想修改代码,不好意思,请另起炉灶,所以,Oracle你移交的意义在哪?

那么从Java EE到Jakarta EE会给企业带来什么影响?下面我们一起分析。

名称的转变

这个对企业影响不大,对开发者影响也不大,你可以愉快用着Jakarta EE最新标准的同时跟同事说java ee发布新版本了。

命名空间的转变

如果你是用Maven进行开发,那么Java EE的依赖是这么定义的

我们可以看到groupId是javax,并且源码的结构如下:

所有的源码都定义在javax.*这个路径下,根据Oracle的要求Jakarta EE不能修改javax命名空间,那么Jakarta EE只能将代码中javax修改为jakarta,因此最新版本Jakarta Maven描述是长这样的:

源码目录:

可以看到除了顶层包名称不一样下面的定义都一样,那么包路径更改会有什么影响?影响非常大。

  • 所有java ee应用服务器比如Weblogic,GlassFish等如果要支持最新版本的jakarta ee就必须修改源码重新编译,并且如果支持了jakarta ee就无法支持java ee,也就是无法向前兼容,Tomcat虽然只是Servlet容器但是Servlet本身就是Java EE的一部分,因此也逃不过修改的命运。据说Tomcat可以对应用进行自动代码转换以支持jakarta,因此在不远的将来我们可以看到各种奇技淫巧去兼容jakarta,是不是想起了被IE支配的恐惧。
  • 企业如果需要用到jakarta ee最新特性必须修改现有代码,修改并不复杂,就是把代码中import javax.*替换为import jakarta.*,修改完重新编译打包部署,似乎很简单,事实上没那么简单。
  • 对企业来说,保持应用服务器处于最新版本是必须的,因为新版本可能修复了老版本的漏洞,并且性能上也可能有一定的提升,但如果升级应用服务器的同时也要修改源码代码就很大,修改的成本,带来的风险并不是所有企业都能接受的。
  • 假设修改了一个应用,那么就需要部署到新版本应用服务器上,由于新服务器不兼容老应用因此需要运维两套应用服务器,运维成本提高,两套应用服务器也可能涉及license问题,不知道各厂商要怎么解决这个问题。

总之企业面临两难的境地,要么升级改系统源码,要么保持不变不升级,要么部分升级运维两套应用服务器,刀刀都要命。

未来

在如今各种诸如spring boot框架的包装下,在应用层面已经找不到Java EE的影子了,这些框架完全有能力抛弃jakarta自己实现,对于这些框架来说,跟随jakarta的意义似乎不大。对于企业来说,拥抱spring boot已经大势所趋,Java EE又搞出这么一件事,只会更加坚定企业转型的决心。对于开发者来说,Java EE已经是古董级的技术,Spring Boot不香吗,有什么理由去用jakarta EE。Oracle似乎也是看到了Java EE行将就木就索性移交出去,还能换取Eclipse基金会的董事会席位,但我还是看不懂Oracle对Java EE致命的这一刀目的何在,weblogic和中间件也是Oracle重要的两块业务,这两块业务都依赖Java EE,这么做只会两败俱伤。

参考


PBKDF2加密的实现

PBKDF2(Password-Based Key Derivation Function)

通过哈希算法进行加密。由于哈希算法是单向的,能够将不论什么大小的数据转化为定长的“指纹”,并且无法被反向计算。

另外,即使数据源仅仅修改了一丁点。哈希的结果也会全然不同。

这种特性使得它很适合用于保存password。由于我们须要加密后的password无法被解密,同一时候也能保证正确校验每一个用户的password。可是哈希加密能够通过字典攻击和暴力攻击破解。

password加盐。盐是一个加入到用户的password哈希过程中的一段随机序列。

这个机制可以防止通过预先计算结果的彩虹表破解。每一个用户都有自己的盐,这种结果就是即使用户的password同样。通过加盐后哈希值也将不同。

为了校验password是否正确,我们须要储存盐值。通常和password哈希值一起存放在账户数据库中。或者直接存为哈希字符串的一部分。

首先要生成一个盐值salt,再把原始passwordsalt加密得到密文。验证的时候,把用户输入的password和同样的盐值salt使用同样的加密算法得到一个密文,将这个密文和原密文相比較,同样则验证通过,反之则不通过。


測试结果为:

参考链接


Robolectric 3.x编写屏幕分辨率/多语言/资源文件相关测试用例

在编写 Android 测试用例的时候,有时候我们需要涉及到屏幕分辨率相关测试用例。

比如不同分辨率得到不同的像素数值,可以参考如下:

比如不同语言得到不同的字符串,可以参考如下: