Skip to content

Commit ec3dbd0

Browse files
committed
Merge branch 'pgpainless-fingerprintUtil'
2 parents 21501b2 + b7a8c9c commit ec3dbd0

File tree

2 files changed

+138
-0
lines changed

2 files changed

+138
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package org.bouncycastle.bcpg;
2+
3+
public class FingerprintUtil
4+
{
5+
6+
/**
7+
* Derive a 64 bit key-id from a version 6 OpenPGP fingerprint.
8+
* For v6 keys, the key-id corresponds to the left-most 8 octets of the fingerprint.
9+
* @param v6Fingerprint 32 byte fingerprint
10+
* @return key-id
11+
*/
12+
public static long keyIdFromV6Fingerprint(byte[] v6Fingerprint)
13+
{
14+
return longFromLeftMostBytes(v6Fingerprint);
15+
}
16+
17+
/**
18+
* Derive a 64 bit key-id from a version 5 LibrePGP fingerprint.
19+
* For such keys, the key-id corresponds to the left-most 8 octets of the fingerprint.
20+
* @param v5Fingerprint 32 byte fingerprint
21+
* @return key-id
22+
*/
23+
public static long keyIdFromLibrePgpFingerprint(byte[] v5Fingerprint)
24+
{
25+
return longFromLeftMostBytes(v5Fingerprint);
26+
}
27+
28+
/**
29+
* Derive a 64 bit key-id from a version 4 OpenPGP fingerprint.
30+
* For v4 keys, the key-id corresponds to the right-most 8 octets of the fingerprint.
31+
* @param v4Fingerprint 20 byte fingerprint
32+
* @return key-id
33+
*/
34+
public static long keyIdFromV4Fingerprint(byte[] v4Fingerprint)
35+
{
36+
return longFromRightMostBytes(v4Fingerprint);
37+
}
38+
39+
/**
40+
* Convert the left-most 8 bytes from the given array to a long.
41+
* @param bytes bytes
42+
* @return long
43+
*/
44+
public static long longFromLeftMostBytes(byte[] bytes)
45+
{
46+
if (bytes.length < 8)
47+
{
48+
throw new IllegalArgumentException("Byte array MUST contain at least 8 bytes");
49+
}
50+
return ((bytes[0] & 0xffL) << 56) |
51+
((bytes[1] & 0xffL) << 48) |
52+
((bytes[2] & 0xffL) << 40) |
53+
((bytes[3] & 0xffL) << 32) |
54+
((bytes[4] & 0xffL) << 24) |
55+
((bytes[5] & 0xffL) << 16) |
56+
((bytes[6] & 0xffL) << 8) |
57+
((bytes[7] & 0xffL));
58+
}
59+
60+
/**
61+
* Convert the right-most 8 bytes from the given array to a long.
62+
* @param bytes bytes
63+
* @return long
64+
*/
65+
public static long longFromRightMostBytes(byte[] bytes)
66+
{
67+
if (bytes.length < 8)
68+
{
69+
throw new IllegalArgumentException("Byte array MUST contain at least 8 bytes");
70+
}
71+
int i = bytes.length;
72+
return ((bytes[i - 8] & 0xffL) << 56) |
73+
((bytes[i - 7] & 0xffL) << 48) |
74+
((bytes[i - 6] & 0xffL) << 40) |
75+
((bytes[i - 5] & 0xffL) << 32) |
76+
((bytes[i - 4] & 0xffL) << 24) |
77+
((bytes[i - 3] & 0xffL) << 16) |
78+
((bytes[i - 2] & 0xffL) << 8) |
79+
((bytes[i - 1] & 0xffL));
80+
}
81+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package org.bouncycastle.bcpg.test;
2+
3+
import org.bouncycastle.bcpg.FingerprintUtil;
4+
import org.bouncycastle.util.encoders.Hex;
5+
import org.bouncycastle.util.test.SimpleTest;
6+
7+
public class FingerprintUtilTest extends SimpleTest {
8+
9+
private void testKeyIdFromTooShortFails() {
10+
byte[] decoded = new byte[1];
11+
try {
12+
FingerprintUtil.keyIdFromV4Fingerprint(decoded);
13+
fail("Expected exception");
14+
} catch (IllegalArgumentException e) {
15+
// expected
16+
}
17+
}
18+
19+
private void testV4KeyIdFromFingerprint() {
20+
String fingerprint = "1D018C772DF8C5EF86A1DCC9B4B509CB5936E03E";
21+
byte[] decoded = Hex.decode(fingerprint);
22+
isEquals("v4 key-id from fingerprint mismatch",
23+
-5425419407118114754L, FingerprintUtil.keyIdFromV4Fingerprint(decoded));
24+
}
25+
26+
private void testV6KeyIdFromFingerprint() {
27+
String fingerprint = "cb186c4f0609a697e4d52dfa6c722b0c1f1e27c18a56708f6525ec27bad9acc9";
28+
byte[] decoded = Hex.decode(fingerprint);
29+
isEquals("v6 key-id from fingerprint mismatch",
30+
-3812177997909612905L, FingerprintUtil.keyIdFromV6Fingerprint(decoded));
31+
}
32+
33+
private void testLibrePgpKeyIdFromFingerprint() {
34+
// v6 key-ids are derived from fingerprints the same way as LibrePGP does
35+
String fingerprint = "cb186c4f0609a697e4d52dfa6c722b0c1f1e27c18a56708f6525ec27bad9acc9";
36+
byte[] decoded = Hex.decode(fingerprint);
37+
isEquals("LibrePGP key-id from fingerprint mismatch",
38+
-3812177997909612905L, FingerprintUtil.keyIdFromLibrePgpFingerprint(decoded));
39+
}
40+
41+
@Override
42+
public String getName() {
43+
return "FingerprintUtilTest";
44+
}
45+
46+
@Override
47+
public void performTest() throws Exception {
48+
testV4KeyIdFromFingerprint();
49+
testV6KeyIdFromFingerprint();
50+
testKeyIdFromTooShortFails();
51+
testLibrePgpKeyIdFromFingerprint();
52+
}
53+
54+
public static void main(String[] args) {
55+
runTest(new FingerprintUtilTest());
56+
}
57+
}

0 commit comments

Comments
 (0)