Skip to content

Commit d1a0f2c

Browse files
author
gefeili
committed
#1736 FingerprintUtil: Add prettifyFingerprint method
2 parents 902266f + e081c2d commit d1a0f2c

File tree

2 files changed

+109
-0
lines changed

2 files changed

+109
-0
lines changed

pg/src/main/java/org/bouncycastle/bcpg/FingerprintUtil.java

+76
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,35 @@
11
package org.bouncycastle.bcpg;
22

33
import org.bouncycastle.util.Pack;
4+
import org.bouncycastle.util.encoders.Hex;
45

56
public class FingerprintUtil
67
{
78

9+
/**
10+
* Derive a key-id from the given key fingerprint.
11+
* This method can derive key-ids from v4, v5 (LibrePGP) and v6 keys.
12+
* For keys with other versions (2,3) it will return 0.
13+
*
14+
* @param keyVersion version of the key
15+
* @param fingerprint fingerprint of the key
16+
* @return derived key-id
17+
*/
18+
public static long keyIdFromFingerprint(int keyVersion, byte[] fingerprint)
19+
{
20+
switch (keyVersion)
21+
{
22+
case PublicKeyPacket.VERSION_4:
23+
return keyIdFromV4Fingerprint(fingerprint);
24+
case PublicKeyPacket.LIBREPGP_5:
25+
return keyIdFromLibrePgpFingerprint(fingerprint);
26+
case PublicKeyPacket.VERSION_6:
27+
return keyIdFromV6Fingerprint(fingerprint);
28+
default:
29+
return 0;
30+
}
31+
}
32+
833
/**
934
* Derive a 64 bit key-id from a version 6 OpenPGP fingerprint.
1035
* For v6 keys, the key-id corresponds to the left-most 8 octets of the fingerprint.
@@ -112,4 +137,55 @@ public static void writeKeyID(long keyID, byte[] bytes)
112137
{
113138
writeKeyID(keyID, bytes, 0);
114139
}
140+
141+
public static String prettifyFingerprint(byte[] fingerprint)
142+
{
143+
// -DM Hex.toHexString
144+
String hex = Hex.toHexString(fingerprint).toUpperCase();
145+
StringBuilder sb = new StringBuilder();
146+
switch (hex.length())
147+
{
148+
case 32:
149+
// v3 keys
150+
for (int i = 0; i < 4; i++)
151+
{
152+
sb.append(hex, i * 4, (i + 1) * 4).append(' ');
153+
}
154+
sb.append(' ');
155+
for (int i = 4; i < 7; i++)
156+
{
157+
sb.append(hex, i * 4, (i + 1) * 4).append(' ');
158+
}
159+
sb.append(hex, 28, 32);
160+
return sb.toString();
161+
case 40:
162+
// v4 keys
163+
for (int i = 0; i <= 4; i++)
164+
{
165+
sb.append(hex, i * 4, (i + 1) * 4).append(' ');
166+
}
167+
sb.append(' ');
168+
for (int i = 5; i <= 8; i++)
169+
{
170+
sb.append(hex, i * 4, (i + 1) * 4).append(' ');
171+
}
172+
sb.append(hex, 36, 40);
173+
return sb.toString();
174+
case 64:
175+
// v5, v6 keys
176+
for (int i = 0; i < 4; i++)
177+
{
178+
sb.append(hex, i * 8, (i + 1) * 8).append(' ');
179+
}
180+
sb.append(' ');
181+
for (int i = 4; i < 7; i++)
182+
{
183+
sb.append(hex, i * 8, (i + 1) * 8).append(' ');
184+
}
185+
sb.append(hex, 56, 64);
186+
return sb.toString();
187+
default:
188+
return hex;
189+
}
190+
}
115191
}

pg/src/test/java/org/bouncycastle/bcpg/test/FingerprintUtilTest.java

+33
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,19 @@ private void testLibrePgpKeyIdFromFingerprint()
4747
-3812177997909612905L, FingerprintUtil.keyIdFromLibrePgpFingerprint(decoded));
4848
}
4949

50+
private void testKeyIdFromFingerprint()
51+
{
52+
isEquals("v4 key-id from fingerprint mismatch",
53+
-5425419407118114754L, FingerprintUtil.keyIdFromFingerprint(
54+
4, Hex.decode("1D018C772DF8C5EF86A1DCC9B4B509CB5936E03E")));
55+
isEquals("v5 key-id from fingerprint mismatch",
56+
-3812177997909612905L, FingerprintUtil.keyIdFromFingerprint(
57+
5, Hex.decode("cb186c4f0609a697e4d52dfa6c722b0c1f1e27c18a56708f6525ec27bad9acc9")));
58+
isEquals("v6 key-id from fingerprint mismatch",
59+
-3812177997909612905L, FingerprintUtil.keyIdFromFingerprint(
60+
6, Hex.decode("cb186c4f0609a697e4d52dfa6c722b0c1f1e27c18a56708f6525ec27bad9acc9")));
61+
}
62+
5063
private void testLeftMostEqualsRightMostFor8Bytes()
5164
{
5265
byte[] bytes = new byte[] {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
@@ -79,6 +92,23 @@ private void testWriteKeyIdToBytes()
7992
}
8093
}
8194

95+
private void testPrettifyFingerprint()
96+
{
97+
isEquals("Prettified v4 fingerprint mismatch",
98+
"1D01 8C77 2DF8 C5EF 86A1 DCC9 B4B5 09CB 5936 E03E",
99+
FingerprintUtil.prettifyFingerprint(Hex.decode("1D018C772DF8C5EF86A1DCC9B4B509CB5936E03E")));
100+
isEquals("Prettified v5/v6 fingerprint mismatch",
101+
"CB186C4F 0609A697 E4D52DFA 6C722B0C 1F1E27C1 8A56708F 6525EC27 BAD9ACC9",
102+
FingerprintUtil.prettifyFingerprint(Hex.decode("cb186c4f0609a697e4d52dfa6c722b0c1f1e27c18a56708f6525ec27bad9acc9")));
103+
}
104+
105+
private void testPrettifyFingerprintReturnsHexForUnknownFormat()
106+
{
107+
String fp = "C0FFEE1DECAFF0";
108+
isEquals("Prettifying fingerprint with unknown format MUST return uppercase hex fingerprint",
109+
fp, FingerprintUtil.prettifyFingerprint(Hex.decode(fp)));
110+
}
111+
82112
@Override
83113
public String getName()
84114
{
@@ -95,6 +125,9 @@ public void performTest()
95125
testLibrePgpKeyIdFromFingerprint();
96126
testLeftMostEqualsRightMostFor8Bytes();
97127
testWriteKeyIdToBytes();
128+
testKeyIdFromFingerprint();
129+
testPrettifyFingerprint();
130+
testPrettifyFingerprintReturnsHexForUnknownFormat();
98131
}
99132

100133
public static void main(String[] args)

0 commit comments

Comments
 (0)