Reference-Request
如何為 PGP 公鑰生成指紋
我想知道如何為 openPGP 公鑰生成指紋。
需要明確的是,我對如何生成指紋感興趣。我知道我可以使用命令行工具獲取指紋。
我在這裡查閱了 PGP 文件,但無法重現我感興趣的密鑰的已知指紋。
我試圖指紋的關鍵是:
-----BEGIN PGP PUBLIC KEY BLOCK----- Version: Keybase OpenPGP v2.0.49 Comment: https://keybase.io/crypto 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 6RZ7aOZsD4ZW =/HI0 -----END PGP PUBLIC KEY BLOCK-----
在keybase.io上,指紋給出為
07DBC7442CABB41ADCB031E03103E62B81D9EB52
再說一遍:我對如何生成指紋感興趣(而不是如何使用 PGP 軟體)。
您的指紋與 OpenPGP V4 兼容,因為它使用 SHA-1。指紋是 20 個字節,而不是舊包格式中使用的 MD5 的 16 個字節。
對於 V4,需要先提取公鑰包。這可能是最棘手的部分,因為 PGP 使用它自己的數據包格式。您必須解析 base 64 編碼 blob 中的二進制數據才能找到數據包。
這來自RFC 4880:OpenPGP 標準,第 12.2 節:
V4 指紋是八位字節的 160 位 SHA-1 雜湊
0x99
,後跟兩個八位字節的數據包長度,然後是從版本欄位開始的整個公鑰數據包。Key ID 是指紋的低 64 位。Java 源的 Bouncy Castle 僅在以下內容中聲明
JcaKeyFingerprintCalculator
:byte[] kBytes = publicPk.getEncodedContents(); MessageDigest digest = MessageDigest.getInstance("SHA1"); digest.update((byte)0x99); digest.update((byte)(kBytes.length >> 8)); digest.update((byte)kBytes.length); digest.update(kBytes); return digest.digest();
在哪裡
publicPk
並且kBytes
已經包含已解析的數據包。所以你必須使用pre-V4 編碼長度,即16 位大端整數編碼。
在上述情況下,公鑰數據包位於位置 [3, 528)。
查找數據包位置的有趣蠻力方法:
String base64Key = "xsFNBFaVsC8BEADPvQH7xlfx2HJf7wQjPkFpkRCGSWR+lSo+cS3Ci81HcguLqt/l" .... + "6RZ7aOZsD4ZW"; // note: don't include the checksum at the end, after and including the `=` sign. byte[] decodedKey = Base64.decode(base64Key); System.out.println(decodedKey.length); ByteBuffer encodedLength = ByteBuffer.allocate(2); MessageDigest digest = MessageDigest.getInstance("SHA1"); int startOff = 0; for (startOff = 0; startOff < decodedKey.length; startOff++) { for (int endOff = decodedKey.length; endOff > startOff; endOff--) { encodedLength.putShort(0, (short) (endOff - startOff)); digest.update((byte) 0x99); digest.update(encodedLength.array()); digest.update(decodedKey, startOff, endOff - startOff); byte[] fingerPrint = digest.digest(); String hexFingerPrint = Hex.toHexString(fingerPrint); if (hexFingerPrint .equalsIgnoreCase("07DBC7442CABB41ADCB031E03103E62B81D9EB52")) { System.out.printf("%d - %d%n", startOff, endOff); return; } } }