不足和可替代方案

这篇Java教程基于JDK1.8。教程中的示例和实践不会使用未来发行版中的优化建议。
不足和可替代方案

本课中的GenSig和VerSig程序演示了如何使用JDK Security API为数据生成数字签名,并验证签名的真实性。然而,程序中描述的实际场景是,发送者使用JDK Security API生成一个新的公钥/私钥对,发送方公钥编码字节存储在一个文件,接收者读取到的密钥字节不一定是真实的,这里有一个潜在的主要缺陷。

在大部分情况下,不需要生成密钥;编码密钥要么存在于文件中,要么存在于密钥存储库的条目中。

潜在的主要缺陷是,没有任何东西能够保证接收方接收到的公钥的真实性,只有在提供的公钥本身是真实的情况下,VerSig程序才能正确地验证签名的真实性!

使用已编码的密钥字节

有时,已编码的密钥字节存在于文件中,以便用于签名和验证密钥对。如果是这种情况,GenSig程序可以导入已编码的私钥字节,并将其转换为签名所需的PrivateKey,如下文所述,假设privkeyfile字符串代表包含私钥字节文件的名称,并且这些字节表示使用PKCS #8标准编码的DSA密钥。

FileInputStream keyfis = new FileInputStream(privkeyfile);
byte[] encKey = new byte[keyfis.available()];
keyfis.read(encKey);
keyfis.close();

PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(encKey);

KeyFactory keyFactory = KeyFactory.getInstance(“DSA”);
PrivateKey privKey = keyFactory.generatePrivate(privKeySpec);

GenSig不再将公钥字节保存在文件中,因为它们已经在一个文件中了。

这种情况下发送者向接收者发送

  • 已存在的包含公钥字节的文件
  • 通过GenSig导出的数据和签名文件

VerSig程序保持不变,因为它已在文件中获取到期望的已编码公钥字节。

但是,如果恶意用户拦截了这些文件,并以无法检测到的篡改行为方式替换这些文件,那么潜在的问题是什么呢? 在某些情况下,这不是问题,因为人们已经面对面或通过可信的第三方面对面的交换了公钥。在此之后,可以远程执行多个后续文件和签名交换(即在不同位置的两个人之间),并且可以使用公钥验证其真实性。如果恶意用户试图更改数据或签名,VerSig将检测到这一点。

如果无法进行面对面的密钥交换,可以尝试其他方法来增加正确接收的可能性。例如,可以在随后交换数据和签名文件之前,通过最安全的方法发送公钥,可能使用的是不太安全的传输介质。通常,将数据和签名与公钥分开发送会大大降低攻击的可能性。除非所有三个文件都被更改,并且以下文中讨论的某种方式更改,否则VerSig将检测到任何篡改。

如果所有三个文件(数据文档、公钥和签名)被恶意用户拦截,拦截者可以用别的东西代替文档,用私钥签名,并转发给你替换后的文档、新的签名和用于生成新签名对应的公钥。然后VerSig将报告一个成功的验证,您会误认为文档来自原始发送者。因此,应该采取步骤确保至少正确地接收到公钥(VerSig检测对其他文件的任何篡改),或者可以使用证书来促进公钥的身份验证,如下文所述。

使用证书

在密码学中,更常见的是交换包含公钥的证书而不是交换密钥本身。

一个显而易见的好处是,证书是由一个实体(发行方)签名,用来验证所包含的公钥其实是另一个实体(主体或所有者)的公钥。通常,可信的第三方认证机构(CA)验证主体的身份,然后通过签署证书来证明其是公钥的所有者。

使用证书的另一个好处是,可以使用颁发者(签名者)的公钥验证其数字签名,从而确保收到的证书的有效性,这个公钥本身可以存储在证书中,其签名可以使用该证书颁发者的公钥进行验证。

如果无法建立信任链(可能因为所需的证书颁发者对您不可用),还可以计算证书指纹。每个指纹都是一个相对较短的数字,它惟一且可靠地标识证书。(从技术上讲,它是证书信息的哈希值,使用消息摘要,也称为单向哈希函数。)您可以调用证书所有者来比较收到的证书和发送的证书的指纹。如果它们是一样的,那么证书也是一样的。

对于GenSig来说,创建包含公钥的证书相比对于VerSig来说导入证书并提取公钥更安全。但是,JDK没有提供从公钥创建证书的API,所以GenSig程序不能从它生成的公钥创建证书。(不过,它提供了从证书中提取公钥的API。)

如果需要,可以使用各种安全工具(而不是API)来签署重要的文档,并使用密钥存储库中的证书,就像在交换文件课中所做的那样。

或者,可以使用API修改程序,以使用密钥存储库中已经存在的私钥和相应的公钥(在证书中)。首先,修改GenSig程序,从密钥存储库中提取私钥,而不是生成新的密钥。我们假设:

  • 密钥名称存储在ksName字符串变量中
  • 密钥存储类型是“JKS”,这是来自Oracle的专有类型
  • 密钥存储在char数组spass变量中
  • 包含私钥和公钥证书的密钥存储库条目的别名存储在字符串变量alias中
  • 私钥密码存储在char数组kpass中

接着可以参考下文所述方式从密钥库中提取私钥。

KeyStore ks = KeyStore.getInstance(“JKS”);
FileInputStream ksfis = new FileInputStream(ksName);
BufferedInputStream ksbufin = new BufferedInputStream(ksfis);

ks.load(ksbufin, spass);
PrivateKey priv = (PrivateKey) ks.getKey(alias, kpass);

可以从密钥存储库中提取公钥证书,并通过以下步骤将其编码字节保存到名为suecert的文件中。

java.security.cert.Certificate cert = ks.getCertificate(alias);
byte[] encodedCert = cert.getEncoded();

// Save the certificate in a file named “suecert”

FileOutputStream certfos = new FileOutputStream(“suecert”);
certfos.write(encodedCert);
certfos.close();

然后将数据文件、签名和证书发送给接收方。接收方首先通过keytool -printcert命令获取证书的指纹,从而验证证书的真实性。

keytool -printcert -file suecert
Owner: CN=Susan Jones, OU=Purchasing, O=ABC, L=Cupertino, ST=CA, C=US
Issuer: CN=Susan Jones, OU=Purchasing, O=ABC, L=Cupertino, ST=CA, C=US
Serial number: 35aaed17
Valid from: Mon Jul 13 22:31:03 PDT 1998 until:
Sun Oct 11 22:31:03 PDT 1998
Certificate fingerprints:
MD5: 1E:B8:04:59:86:7A:78:6B:40:AC:64:89:2C:0F:DD:13
SHA1: 1C:79:BD:26:A1:34:C0:0A:30:63:11:6A:F2:B9:67:DF:E5:8D:7B:5E

然后接收方验证指纹,通过调用发送方并将其与发送方证书的指纹进行比较,或者在公共存储库中查找指纹。假设证书文件名(例如suecert)存储在字符串certName中,接收方的验证程序(修改后的VerSig)可以导入证书并通过以下方式从证书中提取公钥。

FileInputStream certfis = new FileInputStream(certName);
java.security.cert.CertificateFactory cf =
java.security.cert.CertificateFactory.getInstance(“X.509”);
java.security.cert.Certificate cert = cf.generateCertificate(certfis);
PublicKey pub = cert.getPublicKey();

确保数据保密

确保对数据内容保密,以便人们在传输过程中(或在您自己的机器或磁盘上)无意或恶意地试图查看数据。为了保证数据的机密性,应该加密它,并只存储和发送加密结果(称为密文)。接收方可以解密密文以获得原始数据的副本。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值