Hyperledger-TWGC / java-gm

Java语言国密基础库
Apache License 2.0
47 stars 19 forks source link

[提议] 支持通过直接读取公私钥字符串来加载其对象 #81

Closed photowey closed 11 months ago

photowey commented 11 months ago

提议描述: 通常有些场景是将公私钥配置在配置文件或者配置中心里面,这个时候我们的工具类似乎就有点力不从心,当然可以自己实现。

例子: 加载公钥:

twgc.gm.sm2.SM2Util#loadPublicFromFile

public static PublicKey loadPublicFromFile(String filename) throws IOException, NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException {
try (PemReader pemReader = new PemReader(new FileReader(filename))) {
PemObject spki = pemReader.readPemObject();
Security.getProvider(BouncyCastleProvider.PROVIDER_NAME);
return KeyFactory.getInstance(Const.EC_VALUE, BouncyCastleProvider.PROVIDER_NAME).generatePublic(new X509EncodedKeySpec(spki.getContent()));
}
}

期望:

// 提供类似的方法可以通过读取字符串来加载
PemReader pemReader = new PemReader(new StringReader(publicKey))
SamYuan1990 commented 11 months ago

https://github.com/Hyperledger-TWGC/java-gm/blob/master/src/main/java/twgc/gm/sm2/SM2Util.java#L207 ?

photowey commented 11 months ago

1.twgc.gm.sm2.SM2Util#loadPublicFromFile 该方法的入参是一个文件名称(filename),然后构造一个FileReader 对象. 1.1.示例:

new FileReader(filename)

2.期望 2.1.入参是密钥的字符串形式. 2.2.我们可以构造一个 String 类型 的 Reader 2.3.示例

new StringReader(publicKey)

3.在 2 的基础上,我们可以直接从配置文件或者配置中心获取密钥对配置的字符串形式 3.1.通过直接读取字符串来构造其对象形式,比如: PublicKey

SamYuan1990 commented 11 months ago

1.twgc.gm.sm2.SM2Util#loadPublicFromFile 该方法的入参是一个文件名称(filename),然后构造一个FileReader 对象. 1.1.示例:

new FileReader(filename)

2.期望 2.1.入参是密钥的字符串形式. 2.2.我们可以构造一个 String 类型 的 Reader 2.3.示例

new StringReader(publicKey)

3.在 2 的基础上,我们可以直接从配置文件或者配置中心获取密钥对配置的字符串形式 3.1.通过直接读取字符串来构造其对象形式,比如: PublicKey

开个PR带着用例看看,主要我理解最后是要配置文件的。为什么不直接读文件?有那个库能解决文件到string的转化么?

photowey commented 11 months ago

发起了一个 PR#82

photowey commented 11 months ago

回答: 为什么不直接读文件? 1.通常在软件开发中会有不同的环境; 2.不同的环境配置文件不一样(也就是说: 密钥对不一样); 3.不同环境的密钥对特别是正式环境(生产环境)的证书不可能放在项目中,更不可能放在服务器的某个目录; 4.所以通过字符串形式的配置就应运而生, 4.1.运维小伙伴可以在打包前修改不同环境的配置文件也就是密钥对; 4.2.程序也可以直接从 配置中心 中获取; 5.正因为上述的一些原因,就萌生了从字符串加载对象的想法.

PS: 1.以上为个人想法; 2.在实际的开发过程中,开发者自己实现一下也不是难事儿. 3.java-gm 作为一个库,当然期望它全一点.

SamYuan1990 commented 11 months ago

回答: 为什么不直接读文件? 1.通常在软件开发中会有不同的环境; 2.不同的环境配置文件不一样(也就是说: 密钥对不一样); 3.不同环境的密钥对特别是正式环境(生产环境)的证书不可能放在项目中,更不可能放在服务器的某个目录; 4.所以通过字符串形式的配置就应运而生, 4.1.运维小伙伴可以在打包前修改不同环境的配置文件也就是密钥对; 4.2.程序也可以直接从 配置中心 中获取; 5.正因为上述的一些原因,就萌生了从字符串加载对象的想法.

PS: 1.以上为个人想法; 2.在实际的开发过程中,开发者自己实现一下也不是难事儿. 3.java-gm 作为一个库,当然期望它全一点.

  1. 请使用环境管理方式。
  2. 文件名可以一样,来避免雪花环境。
  3. 鉴于2不成立,故3作为2的延伸看起来似乎不必要?
  4. 证书是签名后的公钥,不能放在服务器目录的理由看起来并不成立。

如果是私钥,私钥通过网络传输的方式看起来并不安全。故,从配置中心获取私钥也就是4.2的安全性并不由java-gm处理。 从文件获取私钥,可以假设私钥物理存储于某个文件上。(总会存在文件上吧?考虑重启,备份,灾备)

SamYuan1990 commented 11 months ago

@davidkhala, @xiaohui249 对于私钥的网络传输怎么看?

photowey commented 11 months ago

1.上述第2点就已经申明了软件开发中会有不同的环境,通常都会有环境管理;

2.在分布式情况下,配置信息是很复杂的,让运维去每一台服务器处理公私钥文件似乎并不合理,通常中心化的配置中心更常见; 2.1.这一点也仅仅是一个场景,和该 提议 并没有直接的关系,只是陈述有这样的场景;

3.通常配置中心是在内网运行且账号密码以及访问权限都有严格的管理,所以回答中提及的网络传输不安全的问题并不存在.且和一个库是否提供某个函数并没有直接的关系,网络等问题带来的安全隐患是库不能保证的. 3.1.个人认为这不是讨论的重点;

4.上述的任何讨论和这次的 提议 的初衷并不符合 4.1.开源库提供了某些功能的函数实现; 4.2.对于该函数的正确使用和适用场景,这个是由开发者自己评估和确定的; 4.3.非库本身带来的安全性问题,我认为是由开发者保证,而并非库;

5.更多是讨论 5.1.有没有适用场景? 5.2.有没有必须开发的理由? 5.2.1.比如: 使用场景少,或者理由不充分. 5.3.会不会引入其他的问题? 5.4.会不会影响现有的代码?

davidkhala commented 11 months ago

@SamYuan1990 @photowey 我理解这个issue的初衷只是希望将io readstream作为输入的一个函数抽象并暴露出来,然后将原来file io的函数重写成新函数的一个特例封装。如果我理解和issue作者初衷吻合的话,我个人支持这个想法

关于私钥/公钥的网络传输话题,我认为已经离题了。

另外我也不同意说这个库的只能受限于读配置文件,业界有很多流式或者运行时式的软件范式全程都没有文件,甚至不允许程序读盘。我评估中若要满足以上需求,代码的改动也不大,是值得去兼顾的

SamYuan1990 commented 11 months ago

我们暂时先以 #82 的代码为主吧。 支持string io不算很难,但是我还是希望能找到一个配置中心直接下发私钥的例子。比如某开源项目的案例?

davidkhala commented 11 months ago

@SamYuan1990 github action 的secret就能作为环境变量直接注入代码。类似的secret管理方式应该在业界不少

SamYuan1990 commented 11 months ago

fixed via #82