[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [metrics-tasks/master] Add Java code to verify server descriptors (#2768).
commit bda584d6f61140c14a326ade1f5234e13246cbb7
Author: Karsten Loesing <karsten.loesing@xxxxxxx>
Date: Fri Mar 30 13:16:01 2012 +0200
Add Java code to verify server descriptors (#2768).
---
task-2768/.gitignore | 4 +
task-2768/VerifyServerDescriptors.java | 140 ++++++++++++++++++++++++++++++++
task-2768/run.sh | 3 +
3 files changed, 147 insertions(+), 0 deletions(-)
diff --git a/task-2768/.gitignore b/task-2768/.gitignore
new file mode 100644
index 0000000..e813ffc
--- /dev/null
+++ b/task-2768/.gitignore
@@ -0,0 +1,4 @@
+*.jar
+*.class
+in/
+
diff --git a/task-2768/VerifyServerDescriptors.java b/task-2768/VerifyServerDescriptors.java
new file mode 100644
index 0000000..978d4a3
--- /dev/null
+++ b/task-2768/VerifyServerDescriptors.java
@@ -0,0 +1,140 @@
+/* Copyright 2012 The Tor Project
+ * See LICENSE for licensing information */
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.StringReader;
+import java.security.Security;
+import java.security.interfaces.RSAPublicKey;
+import java.util.Iterator;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.codec.binary.Hex;
+import org.bouncycastle.asn1.ASN1OutputStream;
+import org.bouncycastle.crypto.digests.SHA1Digest;
+import org.bouncycastle.crypto.encodings.PKCS1Encoding;
+import org.bouncycastle.crypto.engines.RSAEngine;
+import org.bouncycastle.crypto.params.RSAKeyParameters;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.openssl.PEMReader;
+import org.torproject.descriptor.Descriptor;
+import org.torproject.descriptor.DescriptorFile;
+import org.torproject.descriptor.DescriptorReader;
+import org.torproject.descriptor.DescriptorSourceFactory;
+import org.torproject.descriptor.ServerDescriptor;
+
+/*
+ * Verify server descriptors using the contained signing key. Verify that
+ * 1) the contained fingerprint is actually a hash of the signing key and
+ * 2) the router signature was created using the signing key.
+ *
+ * Usage:
+ * - Extract server descriptors to in/.
+ * - Clone metrics-lib, run `ant jar`, and copy descriptor.jar to this
+ * directory.
+ * - Download Apache Commons Codec jar file commons-codec-1.4.jar and put
+ * it in this directory.
+ * - Download BouncyCastle 1.47 jar files bcprov-jdk15on-147.jar and
+ * bcpkix-jdk15on-147.jar and put them in this directory.
+ * - Compile and run this class:
+ * $ javac -cp descriptor.jar:commons-codec-1.4.jar:bcprov-jdk15on-147.jar:bcpkix-jdk15on-147.jar VerifyServerDescriptors.java
+ * $ java -cp descriptor.jar:commons-codec-1.4.jar:bcprov-jdk15on-147.jar:bcpkix-jdk15on-147.jar:. VerifyServerDescriptors
+ */
+public class VerifyServerDescriptors {
+ public static void main(String[] args) throws Exception {
+ System.out.println("Verifying descriptors...");
+ if (Security.getProvider("BC") == null) {
+ Security.addProvider(new BouncyCastleProvider());
+ }
+ File inputDirectory = new File("in/");
+ DescriptorReader reader = DescriptorSourceFactory
+ .createDescriptorReader();
+ reader.addDirectory(inputDirectory);
+ Iterator<DescriptorFile> descriptorFiles = reader.readDescriptors();
+ int processedDescriptors = 0, verifiedDescriptors = 0;
+ while (descriptorFiles.hasNext()) {
+ DescriptorFile descriptorFile = descriptorFiles.next();
+ if (descriptorFile.getDescriptors() == null) {
+ continue;
+ }
+ for (Descriptor descriptor : descriptorFile.getDescriptors()) {
+ if (!(descriptor instanceof ServerDescriptor)) {
+ continue;
+ }
+ ServerDescriptor serverDescriptor = (ServerDescriptor) descriptor;
+ boolean isVerified = true;
+
+ /* Verify that the contained fingerprint is a hash of the signing
+ * key. */
+ String signingKeyString = serverDescriptor.getSigningKey();
+ String fingerprintString =
+ serverDescriptor.getFingerprint().toLowerCase();
+ PEMReader pemReader = new PEMReader(new StringReader(
+ signingKeyString));
+ RSAPublicKey signingKey = (RSAPublicKey) pemReader.readObject();
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ new ASN1OutputStream(baos).writeObject(
+ new org.bouncycastle.asn1.pkcs.RSAPublicKey(
+ signingKey.getModulus(),
+ signingKey.getPublicExponent()).toASN1Primitive());
+ byte[] pkcs = baos.toByteArray();
+ byte[] signingKeyHashBytes = new byte[20];
+ SHA1Digest sha1 = new SHA1Digest();
+ sha1.update(pkcs, 0, pkcs.length);
+ sha1.doFinal(signingKeyHashBytes, 0);
+ String signingKeyHashString = Hex.encodeHexString(
+ signingKeyHashBytes);
+ if (!signingKeyHashString.equals(fingerprintString)) {
+ System.out.println("In " + descriptorFile.getFile()
+ + ", server descriptor "
+ + serverDescriptor.getServerDescriptorDigest()
+ + ", the calculated signing key hash "
+ + signingKeyHashString
+ + " does not match the contained fingerprint "
+ + fingerprintString + "!");
+ isVerified = false;
+ }
+
+ /* Verify that the router signature was created using the signing
+ * key. */
+ String serverDescriptorDigestString = serverDescriptor
+ .getServerDescriptorDigest().toLowerCase();
+ String routerSignatureString = serverDescriptor
+ .getRouterSignature();
+ byte[] routerSignature = Base64
+ .decodeBase64(routerSignatureString.substring(
+ 0 + "-----BEGIN SIGNATURE-----\n".length(),
+ routerSignatureString.length()
+ - "-----END SIGNATURE-----\n".length()).replaceAll(
+ "\n", ""));
+ RSAKeyParameters rsakp = new RSAKeyParameters(false,
+ signingKey.getModulus(), signingKey.getPublicExponent());
+ PKCS1Encoding pe = new PKCS1Encoding(new RSAEngine());
+ pe.init(false, rsakp);
+ byte[] decryptedSignature = pe.processBlock(routerSignature, 0,
+ routerSignature.length);
+ String decryptedSignatureString =
+ Hex.encodeHexString(decryptedSignature);
+ if (!decryptedSignatureString.equals(
+ serverDescriptorDigestString)) {
+ System.out.println("In " + descriptorFile.getFile()
+ + ", server descriptor "
+ + serverDescriptor.getServerDescriptorDigest()
+ + ", the decrypted signature "
+ + decryptedSignatureString
+ + " does not match the descriptor digest "
+ + serverDescriptorDigestString + "!");
+ isVerified = false;
+ }
+
+ processedDescriptors++;
+ if (isVerified) {
+ verifiedDescriptors++;
+ }
+ }
+ }
+ System.out.println("Verified " + verifiedDescriptors + "/"
+ + processedDescriptors + " server descriptors.");
+ }
+}
+
diff --git a/task-2768/run.sh b/task-2768/run.sh
new file mode 100755
index 0000000..a819ac5
--- /dev/null
+++ b/task-2768/run.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+javac -cp descriptor.jar:commons-codec-1.4.jar:bcprov-jdk15on-147.jar:bcpkix-jdk15on-147.jar VerifyServerDescriptors.java && java -cp descriptor.jar:commons-codec-1.4.jar:bcprov-jdk15on-147.jar:bcpkix-jdk15on-147.jar:. VerifyServerDescriptors
+
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits