forked from Path-Check/paper-cred-demo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
verify.java
133 lines (102 loc) · 4.8 KB
/
verify.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Base64;
import java.util.Hashtable;
import javax.naming.directory.Attribute;
import javax.naming.directory.InitialDirContext;
import org.apache.commons.codec.binary.Base32;
public class verify {
public static String pad(String base32Str) {
switch (base32Str.length() % 8) {
case 2: return base32Str + "======";
case 4: return base32Str + "====";
case 5: return base32Str + "===";
case 7: return base32Str + "=";
}
return base32Str;
}
public static String rmPad(String base32Str) {
return base32Str.replaceAll("=", "");
}
public static String buildPEMFromDNS(String encodedKey) {
String key = encodedKey.replaceAll("\"","").replaceAll("\\\\n", "n").replaceAll("\\\\n", "\n");
if (!key.contains("-----BEGIN PUBLIC KEY-----")) {
key = "-----BEGIN PUBLIC KEY-----" + "\n" + key + "\n" + "-----END PUBLIC KEY-----\n";
}
return key;
}
public static String downloadPubKeyFromTXTRecord(String pubKeyLink) throws Exception {
Hashtable<String, String> env = new Hashtable<String, String>();
env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
Attribute txt = new InitialDirContext(env).getAttributes(pubKeyLink, new String[] { "TXT" }).get("TXT");
return buildPEMFromDNS(txt.get(0).toString());
}
public static PrivateKey getPrivateKey() throws Exception {
String privKeyPEM = new String(Files.readAllBytes(Paths.get("keys/ecdsa_private_key8.pem")));
privKeyPEM = privKeyPEM.replaceAll("\\n", "")
.replace("-----BEGIN PRIVATE KEY-----", "")
.replace("-----END PRIVATE KEY-----", "");
PKCS8EncodedKeySpec keySpecPKCS8 = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privKeyPEM));
return KeyFactory.getInstance("EC").generatePrivate(keySpecPKCS8);
}
public static PublicKey getPublicKey(String pubKeyLink) throws Exception {
String pubKeyPEM = downloadPubKeyFromTXTRecord(pubKeyLink);
pubKeyPEM = pubKeyPEM.replaceAll("\\n", "")
.replace("-----BEGIN PUBLIC KEY-----", "")
.replace("-----END PUBLIC KEY-----", "");
X509EncodedKeySpec x509 = new X509EncodedKeySpec(Base64.getDecoder().decode(pubKeyPEM));
return KeyFactory.getInstance("EC").generatePublic(x509);
}
public static String[] parseQR(String qr) {
return qr.split(":");
}
public static boolean parseAndVerifyQR(String qr) throws Exception {
String[] qrArray = parseQR(qr);
System.out.println("Parsed QR\t" + Arrays.toString(qrArray));
String base32Signature = qrArray[3];
String pubKeyLink = qrArray[4];
String payload = qrArray[5];
byte[] payloadBytes = payload.getBytes();
byte[] signatureDER = new Base32().decode(pad(base32Signature).getBytes());
Signature s = Signature.getInstance("SHA256withECDSA");
s.initVerify(getPublicKey(pubKeyLink));
s.update(payloadBytes);
System.out.println("Payload Bytes\t" + Arrays.toString(payloadBytes));
System.out.println("Signature DER\t" + Arrays.toString(signatureDER));
boolean verified = s.verify(signatureDER);
System.out.println("");
System.out.println("Verify Payload\t" + verified);
return verified;
}
public static String signAndFormatQR(String schema, String qrtype, String version, String pubKeyLink, String payload) throws Exception {
byte[] payloadBytes = payload.getBytes();
Signature s = Signature.getInstance("SHA256withECDSA");
s.initSign(getPrivateKey());
s.update(payloadBytes);
byte[] signatureDER = s.sign();
String formattedSig = rmPad(new String(new Base32().encode(signatureDER)));
return schema + ":" + qrtype + ":" + version + ":" + formattedSig + ":" + pubKeyLink + ":" + payload;
}
public static void main( String args[]) throws Exception {
String qr = "CRED:STATUS:2:GBCAEIAHV2J6PWDSYVLI67RN55WVHIMUTKLFF5GZ4NPHPZ7ZSIJE4MP5M4BCAU6QVDHUP4RQCPXW6XJDAM54VMZ7XURUN34WFT2RWL5ETTZDNHUF:KEYS.PATHCHECK.ORG:1/BUQHHANUB4Z5KHBZTYCWMNI4RQ6CP5WFVVQCUXYHCQVY5WLDDFPA/";
System.out.println("");
System.out.println("Loading hardcoded QR");
System.out.println("");
parseAndVerifyQR(qr);
System.out.println("");
System.out.println("Resigning same payload");
System.out.println("");
String[] qrArray = parseQR(qr);
String newQR = signAndFormatQR(qrArray[0], qrArray[1], qrArray[2], qrArray[4], qrArray[5]);
System.out.println("New QR Signed\t" + newQR);
System.out.println("");
parseAndVerifyQR(newQR);
}
}