1 回答
TA贡献2036条经验 获得超8个赞
首先,签名者正在寻找任何可签名的密钥,而验证者正在寻找任何可加密的密钥。根据您生成密钥的方式和时间,这些可能不相同:使用子密钥进行加密(仅)被认为是一种好的做法,并且至少二十年来都是默认设置——有时也一个不同的用于数据签名的子密钥(仅保留用于密钥签名的主密钥,也称为“仅认证”)。但是从技术上讲,拥有一个具有数据签名和加密功能的 RSA 主密钥是可能的(并且还可以选择进行认证,尽管它未被使用);在 GPG 中,这可以通过在“专家”模式下生成来完成,或者在最新版本中通过生成后编辑来完成。由于您没有向我们展示您的秘密/私钥的详细信息 - 除非这些是仅测试密钥,否则您不应该向我们展示您可以妥协 - 不可能告诉您的情况。如果您实际上使用不同的密钥来尝试签名和验证,那么它当然永远无法正常工作。
一般来说,接收方应使用消息中keyid 指定的密钥:发送方使用任何具有加密能力的公钥进行加密,在消息中识别该密钥,接收方使用发送方选择的密钥的一半私钥进行解密;发送方使用任何可签名的私钥进行签名,在消息中识别该密钥,接收方使用发送方选择的密钥的一半公钥进行验证。这将需要重新组织您的代码以仅在读取签名包后选择验证密钥。现在我只是在其中添加了一张verifyFile
支票sig.getKeyID() == publicKey.getKeyID()
。
这在您的数据处理中留下了更严重的错误signFile
byte[] buf = new byte[2048];
int ch;
while ((ch = fIn.read(buf)) >= 0) {
lOut.write(ch);
sGen.update(buf, 0, ch);
}
您计算输入文件中所有数据的签名,但您只为每个缓冲数据在消息中放入一个字节;请参阅 javadoc OutputStream.write(int)。由于验证者使用消息中的数据,该数据现在与已签名的数据完全不同,签名不应该也不会验证。以及消息对接收者无用。相反做
lOut.write(buf,0,ch);
或者像你一样切换到一次一个字节的处理verifyFile
int ch; // no byte[] buf
while( (ch = fIn.read()) >= 0 ){
lOut.write((byte)ch); // cast not needed but clarifies intent
sig.update((byte)ch);
}
添加回答
举报