Line data Source code
1 : // Copyright (C) 2015 The Android Open Source Project
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : package com.google.gerrit.gpg;
16 :
17 : import static com.google.common.base.Preconditions.checkArgument;
18 :
19 : import java.util.Arrays;
20 : import java.util.Collections;
21 : import java.util.HashMap;
22 : import java.util.Map;
23 : import org.eclipse.jgit.util.NB;
24 :
25 : public class Fingerprint {
26 : private final byte[] fp;
27 :
28 : public static String toString(byte[] fp) {
29 3 : checkLength(fp);
30 3 : return String.format(
31 : "%04X %04X %04X %04X %04X %04X %04X %04X %04X %04X",
32 3 : NB.decodeUInt16(fp, 0),
33 3 : NB.decodeUInt16(fp, 2),
34 3 : NB.decodeUInt16(fp, 4),
35 3 : NB.decodeUInt16(fp, 6),
36 3 : NB.decodeUInt16(fp, 8),
37 3 : NB.decodeUInt16(fp, 10),
38 3 : NB.decodeUInt16(fp, 12),
39 3 : NB.decodeUInt16(fp, 14),
40 3 : NB.decodeUInt16(fp, 16),
41 3 : NB.decodeUInt16(fp, 18));
42 : }
43 :
44 : public static long getId(byte[] fp) {
45 3 : return NB.decodeInt64(fp, 12);
46 : }
47 :
48 : public static Map<Long, Fingerprint> byId(Iterable<Fingerprint> fps) {
49 0 : Map<Long, Fingerprint> result = new HashMap<>();
50 0 : for (Fingerprint fp : fps) {
51 0 : result.put(fp.getId(), fp);
52 0 : }
53 0 : return Collections.unmodifiableMap(result);
54 : }
55 :
56 : private static byte[] checkLength(byte[] fp) {
57 3 : checkArgument(fp.length == 20, "fingerprint must be 20 bytes, got %s", fp.length);
58 3 : return fp;
59 : }
60 :
61 : /**
62 : * Wrap a fingerprint byte array.
63 : *
64 : * <p>The newly created Fingerprint object takes ownership of the byte array, which must not be
65 : * subsequently modified. (Most callers, such as hex decoders and {@code
66 : * org.bouncycastle.openpgp.PGPPublicKey#getFingerprint()}, already produce fresh byte arrays).
67 : *
68 : * @param fp 20-byte fingerprint byte array to wrap.
69 : */
70 3 : public Fingerprint(byte[] fp) {
71 3 : this.fp = checkLength(fp);
72 3 : }
73 :
74 : /**
75 : * Wrap a portion of a fingerprint byte array.
76 : *
77 : * <p>Unlike {@link #Fingerprint(byte[])}, creates a new copy of the byte array.
78 : *
79 : * @param buf byte array to wrap; must have at least {@code off + 20} bytes.
80 : * @param off offset in buf.
81 : */
82 0 : public Fingerprint(byte[] buf, int off) {
83 0 : int expected = 20 + off;
84 0 : checkArgument(
85 : buf.length >= expected,
86 : "fingerprint buffer must have at least %s bytes, got %s",
87 : expected,
88 : buf.length);
89 0 : this.fp = new byte[20];
90 0 : System.arraycopy(buf, off, fp, 0, 20);
91 0 : }
92 :
93 : public byte[] get() {
94 3 : return fp;
95 : }
96 :
97 : public boolean equalsBytes(byte[] bytes) {
98 3 : return Arrays.equals(fp, bytes);
99 : }
100 :
101 : @Override
102 : public int hashCode() {
103 : // Same hash code as ObjectId: second int word.
104 3 : return NB.decodeInt32(fp, 4);
105 : }
106 :
107 : @Override
108 : public boolean equals(Object o) {
109 2 : return (o instanceof Fingerprint) && equalsBytes(((Fingerprint) o).fp);
110 : }
111 :
112 : @Override
113 : public String toString() {
114 1 : return toString(fp);
115 : }
116 :
117 : public long getId() {
118 3 : return getId(fp);
119 : }
120 : }
|