diff --git a/.gitignore b/.gitignore index 9793e15..6339218 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,10 @@ .gradle .idea build +bin +.settings +.classpath +.project out *.iml *.ipr diff --git a/meerkat-common/build.gradle b/meerkat-common/build.gradle index 9768dd8..b744fcd 100644 --- a/meerkat-common/build.gradle +++ b/meerkat-common/build.gradle @@ -45,6 +45,10 @@ dependencies { // Google protobufs compile 'com.google.protobuf:protobuf-java:3.+' + // Crypto + compile 'org.bouncycastle:bcprov-jdk15on:1.53' + compile 'org.bouncycastle:bcpkix-jdk15on:1.53' + testCompile 'junit:junit:4.+' runtime 'org.codehaus.groovy:groovy:2.4.+' diff --git a/meerkat-common/src/main/java/meerkat/crypto/DigitalSignature.java b/meerkat-common/src/main/java/meerkat/crypto/DigitalSignature.java index 691b492..eda41a2 100644 --- a/meerkat-common/src/main/java/meerkat/crypto/DigitalSignature.java +++ b/meerkat-common/src/main/java/meerkat/crypto/DigitalSignature.java @@ -2,16 +2,92 @@ package meerkat.crypto; import com.google.protobuf.Message; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.PasswordCallback; +import java.io.IOException; +import java.io.InputStream; +import java.security.InvalidKeyException; +import java.security.KeyStore; +import java.security.SignatureException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; import java.util.List; import static meerkat.protobuf.Crypto.*; /** * Created by talm on 25/10/15. * - * Sign arrays of messages + * Sign and verifyarrays of messages */ -public interface DigitalSignature { // Extends SCAPI DigitalSignature - public Signature sign(List msg); +public interface DigitalSignature { + final public static String CERTIFICATE_ENCODING_X509 = "X.509"; + + /** + * Load a set of certificates from an input stream. + * This will consume the entire stream. + * Certificates can be either DER-encoded (binary) or PEM (base64) encoded. + * This may be called multiple times to load several different certificates. + * It must be called before calling {@link #verify()}. + * @param certStream source from which certificates are loaded + * @throws CertificateException on parsing errors + */ + public void loadVerificationCertificates(InputStream certStream) + throws CertificateException; + + /** + * Clear the loaded verification certificates. + */ + public void clearVerificationCertificates(); + + + /** + * Add msg to the content stream to be verified / signed. Each message is always (automatically) + * prepended with its length as a 32-bit unsigned integer in network byte order. + * + * @param msg + * @throws SignatureException + */ + public void updateContent(Message msg) throws SignatureException; + + + /** + * Sign the content that was added. + * @return + * @throws SignatureException + */ + Signature sign() throws SignatureException; + + /** + * Initialize the verifier with the certificate whose Id is in sig. + * @param sig + * @throws CertificateException + * @throws InvalidKeyException + */ + void initVerify(Signature sig) + throws CertificateException, InvalidKeyException; + + /** + * Verify the updated content using the initialized signature. + * @return + */ + public boolean verify(); + + /** + * Loads a private signing key. The keystore must include both the public and private + * key parts. + * This method must be called before calling {@link #sign(List)} + * Calling this method again will replace the key. + * + * @param keyStoreBuilder A keystore builder that can be used to load a keystore. + */ + public void loadSigningCertificate(KeyStore.Builder keyStoreBuilder) + throws IOException, CertificateException, UnrecoverableKeyException; + + + + /** + * Clear the signing key (will require authentication to use again). + */ + public void clearSigningKey(); - public boolean verify(Signature sig, List msgs); } diff --git a/meerkat-common/src/main/java/meerkat/crypto/concrete/ECDSASignature.java b/meerkat-common/src/main/java/meerkat/crypto/concrete/ECDSASignature.java new file mode 100644 index 0000000..4fb8de5 --- /dev/null +++ b/meerkat-common/src/main/java/meerkat/crypto/concrete/ECDSASignature.java @@ -0,0 +1,272 @@ +package meerkat.crypto.concrete; + +import java.io.IOException; +import java.io.InputStream; +import java.security.*; +import java.security.cert.*; +import java.security.cert.Certificate; +import java.util.*; + +import com.google.protobuf.ByteString; +import meerkat.crypto.Digest; +import meerkat.protobuf.Crypto; +import meerkat.util.Hex; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.protobuf.Message; + +import meerkat.crypto.DigitalSignature; +import meerkat.protobuf.Crypto.Signature; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.callback.UnsupportedCallbackException; + + +/** + * Sign and verify digital signatures. + *

+ * This class is not thread-safe (each thread should have its own instance). + */ +public class ECDSASignature extends GlobalCryptoSetup implements DigitalSignature { + final Logger logger = LoggerFactory.getLogger(getClass()); + + final public static String KEYSTORE_TYPE = "PKCS12"; + final public static String DEFAULT_SIGNATURE_ALGORITHM = "SHA256withECDSA"; + + SHA256Digest digest = new SHA256Digest(); + + Map loadedCertificates = new HashMap<>(); + + /** + * Signature currently loaded (will be used in calls to {@link #verify()}). + */ + ByteString loadedSignature = null; + + ByteString loadedSigningKeyId = null; + + /** + * The actual signing implementation. (used for both signing and verifying) + */ + java.security.Signature signer; + + + /** + * Compute a fingerprint of a cert as a SHA256 hash. + * + * @param cert + * @return + */ + public ByteString computeCertificateFingerprint(Certificate cert) { + try { + digest.reset(); + byte[] data = cert.getEncoded(); + digest.update(data); + return ByteString.copyFrom(digest.digest()); + } catch (CertificateEncodingException e) { + // Shouldn't happen + logger.error("Certificate encoding error", e); + return ByteString.EMPTY; + } + + } + + public ECDSASignature(java.security.Signature signer) { + this.signer = signer; + } + + public ECDSASignature() { + try { + this.signer = java.security.Signature.getInstance(DEFAULT_SIGNATURE_ALGORITHM); + } catch (NoSuchAlgorithmException e) { + // Should never happen + logger.error("Couldn't find implementation for " + DEFAULT_SIGNATURE_ALGORITHM + " signatures", e); + } + } + + @Override + public void loadVerificationCertificates(InputStream certStream) + throws CertificateException { + CertificateFactory certificateFactory = CertificateFactory.getInstance(CERTIFICATE_ENCODING_X509); + Collection certs = certificateFactory.generateCertificates(certStream); + for (Certificate cert : certs) { + // Just checking + if (!(cert instanceof X509Certificate)) { + logger.error("Certificate must be in X509 format; got {} instead!", cert.getClass().getCanonicalName()); + continue; + } + PublicKey pubKey = cert.getPublicKey(); + ByteString keyId = computeCertificateFingerprint(cert); + loadedCertificates.put(keyId, cert); + } + } + + @Override + public void clearVerificationCertificates() { + loadedCertificates.clear(); + } + + + /** + * Add the list of messages to the stream that is being verified/signed. + * Messages are separated with {@link Digest#CONCAT_MARKER} + * + * @param msg + * @throws SignatureException + */ + @Override + public void updateContent(Message msg) throws SignatureException { + assert msg != null; + int len = msg.getSerializedSize(); + + byte[] lenBytes = { (byte) ((len >>> 24) & 0xff), (byte) ((len >>> 16) & 0xff), (byte) ((len >>> 8) & 0xff), (byte) (len & 0xff) }; + signer.update(lenBytes); + signer.update(msg.toByteString().asReadOnlyByteBuffer()); + } + + public void updateSigner(InputStream in) throws IOException, SignatureException { + ByteString inStr = ByteString.readFrom(in); + signer.update(inStr.asReadOnlyByteBuffer()); + } + + @Override + public Signature sign() throws SignatureException { + Signature.Builder sig = Signature.newBuilder(); + sig.setType(Crypto.SignatureType.ECDSA); + sig.setData(ByteString.copyFrom(signer.sign())); + sig.setSignerId(loadedSigningKeyId); + return sig.build(); + } + + @Override + public void initVerify(Signature sig) + throws CertificateException, InvalidKeyException { + Certificate cert = loadedCertificates.get(sig.getSignerId()); + if (cert == null) { + logger.warn("No certificate loaded for ID {}!", sig.getSignerId()); + throw new CertificateException("No certificate loaded for " + sig.getSignerId()); + } + signer.initVerify(cert.getPublicKey()); + loadedSignature = sig.getData(); + loadedSigningKeyId = null; + } + + @Override + public boolean verify() { + try { + return signer.verify(loadedSignature.toByteArray()); + } catch (SignatureException e) { + // Happens only if signature is invalid! + logger.error("Signature exception", e); + return false; + } + } + + /** + * Utility method to more easily deal with simple password-protected files. + * + * @param password + * @return + */ + public CallbackHandler getFixedPasswordHandler(final char[] password) { + return new CallbackHandler() { + @Override + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + for (Callback callback : callbacks) { + if (callback instanceof PasswordCallback) { + PasswordCallback passwordCallback = (PasswordCallback) callback; + logger.debug("Requested password ({})", passwordCallback.getPrompt()); + passwordCallback.setPassword(password); + } + } + + } + }; + } + + /** + * Load a keystore from an input stream in PKCS12 format. + * + * @param keyStream + * @param password + * @return + * @throws IOException + * @throws CertificateException + * @throws KeyStoreException + * @throws NoSuchAlgorithmException + */ + public KeyStore.Builder getPKCS12KeyStoreBuilder(InputStream keyStream, char[] password) + throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException { + KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE); + keyStore.load(keyStream, password); + return KeyStore.Builder.newInstance(keyStore, new KeyStore.CallbackHandlerProtection(getFixedPasswordHandler(password))); + } + + + /** + * For now we only support PKCS12. + * TODO: Support for PKCS11 as well. + * + * @param keyStoreBuilder + * @throws IOException + * @throws CertificateException + * @throws UnrecoverableKeyException + */ + @Override + public void loadSigningCertificate(KeyStore.Builder keyStoreBuilder) + throws IOException, CertificateException, UnrecoverableKeyException { + try { + + KeyStore keyStore = keyStoreBuilder.getKeyStore(); + + // Iterate through all aliases until we find the first privatekey + Enumeration aliases = keyStore.aliases(); + while (aliases.hasMoreElements()) { + String alias = aliases.nextElement(); + logger.trace("Testing keystore entry {}", alias); + + try { + Certificate cert = keyStore.getCertificate(alias); + logger.trace("keystore entry {}, has cert type {}", alias, cert.getClass()); + Key key = keyStore.getKey(alias, null); + logger.trace("keystore entry {}, has key type {}", alias, key.getClass()); + if (key instanceof PrivateKey) { + loadedSigningKeyId = computeCertificateFingerprint(cert); + signer.initSign((PrivateKey) key); + logger.debug("Loaded signing key with ID {}", Hex.encode(loadedSigningKeyId)); + return; + } else { + logger.info("Certificate {} in keystore does not have a private key", cert.toString()); + } + } catch(InvalidKeyException e) { + logger.info("Read invalid key", e); + } catch(UnrecoverableEntryException e) { + logger.info("Read unrecoverable entry", e); + } + } + + } catch (KeyStoreException e) { + logger.error("Keystore exception", e); + } catch (NoSuchAlgorithmException e) { + logger.error("NoSuchAlgorithmException exception", e); + throw new CertificateException(e); + } + logger.error("Didn't find valid private key entry in keystore"); + throw new UnrecoverableKeyException("Didn't find valid private key entry in keystore!"); + } + + public void clearSigningKey() { + try { + // TODO: Check if this really clears the key from memory + if (loadedSigningKeyId != null) + signer.initSign(null); + loadedSigningKeyId = null; + } catch (InvalidKeyException e) { + // Do nothing + } + } + + +} diff --git a/meerkat-common/src/main/java/meerkat/crypto/concrete/GlobalCryptoSetup.java b/meerkat-common/src/main/java/meerkat/crypto/concrete/GlobalCryptoSetup.java new file mode 100644 index 0000000..764fd8d --- /dev/null +++ b/meerkat-common/src/main/java/meerkat/crypto/concrete/GlobalCryptoSetup.java @@ -0,0 +1,38 @@ +package meerkat.crypto.concrete; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.security.Security; + +/** + * A class that performs required crypto setup + */ +public class GlobalCryptoSetup { + final static Logger logger = LoggerFactory.getLogger(GlobalCryptoSetup.class); + + static boolean loadedBouncyCastle = false; + + public static boolean hasSecp256k1Curve() { + // For now we just check if the java version is at least 8 + String[] version = System.getProperty("java.version").split("\\."); + int major = Integer.parseInt(version[0]); + int minor = Integer.parseInt(version[1]); + return ((major > 1) || ((major > 0) && (minor > 7))); + } + + public static void doSetup() { + // Make bouncycastle our default provider if we're running on a JVM version < 8 + // (earlier version don't support the EC curve we use for signatures) + if (!hasSecp256k1Curve() && !loadedBouncyCastle) { + loadedBouncyCastle = true; + Security.insertProviderAt(new BouncyCastleProvider(), 1); + logger.info("Using BouncyCastle instead of native provider to support secp256k1 named curve"); + } + } + + public GlobalCryptoSetup() { + doSetup(); + } +} diff --git a/meerkat-common/src/main/java/meerkat/crypto/concrete/SHA256Digest.java b/meerkat-common/src/main/java/meerkat/crypto/concrete/SHA256Digest.java index 092aab4..dc1d2ba 100644 --- a/meerkat-common/src/main/java/meerkat/crypto/concrete/SHA256Digest.java +++ b/meerkat-common/src/main/java/meerkat/crypto/concrete/SHA256Digest.java @@ -1,5 +1,6 @@ package meerkat.crypto.concrete; +import com.google.protobuf.ByteString; import com.google.protobuf.Message; import meerkat.crypto.Digest; import org.slf4j.Logger; @@ -11,7 +12,7 @@ import java.security.NoSuchAlgorithmException; /** * Created by talm on 11/9/15. */ -public class SHA256Digest implements Digest { +public class SHA256Digest extends GlobalCryptoSetup implements Digest { final Logger logger = LoggerFactory.getLogger(getClass()); public static final String SHA256 = "SHA-256"; @@ -32,7 +33,7 @@ public class SHA256Digest implements Digest { public SHA256Digest() { this(true); } - /** + /**SHA * Instantiate with the default (SHA-256) algorithm, * or create an empty class (for cloning) */ @@ -58,6 +59,14 @@ public class SHA256Digest implements Digest { hash.update(msg.toByteString().asReadOnlyByteBuffer()); } + final public void update(ByteString msg) { + hash.update(msg.asReadOnlyByteBuffer()); + } + + final public void update(byte[] msg) { + hash.update(msg); + } + @Override public void reset() { hash.reset(); diff --git a/meerkat-common/src/main/java/meerkat/util/Hex.java b/meerkat-common/src/main/java/meerkat/util/Hex.java new file mode 100644 index 0000000..2d0e4ef --- /dev/null +++ b/meerkat-common/src/main/java/meerkat/util/Hex.java @@ -0,0 +1,26 @@ +package meerkat.util; + +import com.google.protobuf.ByteString; + +/** + * Convert to/from Hex + */ +public class Hex { + /** + * Encode a {@link ByteString} as a hex string. + * @param str + * @return + */ + public static String encode(ByteString str) { + StringBuilder s = new StringBuilder(); + for (byte b : str) { + s.append(Integer.toHexString(((int) b) & 0xff)); + } + return s.toString(); + } + + public static String encode(byte[] bytes) { + return encode(ByteString.copyFrom(bytes)); + } +} + diff --git a/meerkat-common/src/main/proto/meerkat/crypto.proto b/meerkat-common/src/main/proto/meerkat/crypto.proto index e1475da..feafc1c 100644 --- a/meerkat-common/src/main/proto/meerkat/crypto.proto +++ b/meerkat-common/src/main/proto/meerkat/crypto.proto @@ -13,14 +13,18 @@ enum SignatureType { message Signature { SignatureType type = 1; - // Data encoding depends on type; default is x509 BER-encoded + // Data encoding depends on type; default is DER-encoded bytes data = 2; + + // ID of the signer (should be the fingerprint of the signature verification key) + bytes signer_id = 3; } // Public key used to verify signatures message SignatureVerificationKey { SignatureType type = 1; + // Data encoding depends on type; default is x509 DER-encoded bytes data = 2; } diff --git a/meerkat-common/src/main/resources/logback.groovy b/meerkat-common/src/main/resources/logback.groovy new file mode 100644 index 0000000..076b6c4 --- /dev/null +++ b/meerkat-common/src/main/resources/logback.groovy @@ -0,0 +1,46 @@ + + +import ch.qos.logback.classic.encoder.PatternLayoutEncoder +import ch.qos.logback.classic.filter.ThresholdFilter +import ch.qos.logback.core.ConsoleAppender +import ch.qos.logback.core.util.Duration +import static ch.qos.logback.classic.Level.* + +if (System.getProperty("log.debug") != null) { + println "Logback configuration debugging enabled" + + statusListener(OnConsoleStatusListener) +} + +def LOG_LEVEL = toLevel(System.getProperty("log.level"), INFO) + +def haveBeagle = System.getProperty("log.beagle") != null +def logOps = System.getProperty("log.ops") != null + +appender("CONSOLE", ConsoleAppender) { + + filter(ThresholdFilter) { + level = toLevel(System.getProperty("log.level"), TRACE) + } + + encoder(PatternLayoutEncoder) { + pattern = "%d{HH:mm:ss.SSS} [%thread %file:%line] %-5level %logger{0} - %msg%n" + } +} + +def appenders = [ "CONSOLE" ] + +if (haveBeagle) { + appender("SOCKET", SocketAppender) { + includeCallerData = true + remoteHost = "localhost" + port = 4321 + reconnectionDelay = new Duration(10000) + } + + appenders += ["SOCKET"] +} + +root(LOG_LEVEL, appenders) + + diff --git a/meerkat-common/src/test/java/meerkat/crypto/concrete/TestECDSASignature.java b/meerkat-common/src/test/java/meerkat/crypto/concrete/TestECDSASignature.java new file mode 100644 index 0000000..4fbb35c --- /dev/null +++ b/meerkat-common/src/test/java/meerkat/crypto/concrete/TestECDSASignature.java @@ -0,0 +1,172 @@ +package meerkat.crypto.concrete; + +import com.google.protobuf.ByteString; +import meerkat.protobuf.Crypto; +import meerkat.protobuf.Voting; +import org.junit.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.security.KeyStore; +import java.util.Arrays; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Created by talm on 12/11/15. + */ +public class TestECDSASignature { + public static String KEYFILE_EXAMPLE = "/certs/enduser-certs/user1-key-with-password-secret.p12"; + public static String KEYFILE_PASSWORD = "secret"; + + public static String CERT1_PEM_EXAMPLE = "/certs/enduser-certs/user1.crt"; + public static String CERT2_DER_EXAMPLE = "/certs/enduser-certs/user2.der"; + + public static String MSG_PLAINTEXT_EXAMPLE = "/certs/signed-messages/helloworld.txt"; + public static String MSG_SIG_EXAMPLE = "/certs/signed-messages/helloworld.txt.sha256sig"; + + public static String HELLO_WORLD = "hello world!"; + + + @Test + public void loadSignatureKey() throws Exception { + InputStream keyStream = getClass().getResourceAsStream(KEYFILE_EXAMPLE); + char[] password = KEYFILE_PASSWORD.toCharArray(); + + ECDSASignature sig = new ECDSASignature(); + + KeyStore.Builder keyStore = sig.getPKCS12KeyStoreBuilder(keyStream, password); + sig.loadSigningCertificate(keyStore); + keyStream.close(); + } + + @Test + public void loadPEMVerificationKey() throws Exception { + InputStream certStream = getClass().getResourceAsStream(CERT1_PEM_EXAMPLE); + + ECDSASignature sig = new ECDSASignature(); + + sig.loadVerificationCertificates(certStream); + certStream.close(); + } + + @Test + public void loadDERVerificationKey() throws Exception { + InputStream certStream = getClass().getResourceAsStream(CERT2_DER_EXAMPLE); + + ECDSASignature sig = new ECDSASignature(); + + sig.loadVerificationCertificates(certStream); + certStream.close(); + } + + + @Test + public void verifyValidSig() throws Exception { + InputStream certStream = getClass().getResourceAsStream(CERT1_PEM_EXAMPLE); + InputStream msgStream = getClass().getResourceAsStream(MSG_PLAINTEXT_EXAMPLE); + InputStream sigStream = getClass().getResourceAsStream(MSG_SIG_EXAMPLE); + + ECDSASignature signer = new ECDSASignature(); + + signer.loadVerificationCertificates(certStream); + certStream.close(); + + Crypto.Signature.Builder sig = Crypto.Signature.newBuilder(); + sig.setType(Crypto.SignatureType.ECDSA); + sig.setSignerId(signer.loadedCertificates.entrySet().iterator().next().getKey()); + sig.setData(ByteString.readFrom(sigStream)); + + Crypto.Signature builtSig = sig.build(); + signer.initVerify(builtSig); + signer.updateSigner(msgStream); + assertTrue("Signature did not verify!", signer.verify()); + } + + @Test + public void verifyInvalidSig() throws Exception { + InputStream certStream = getClass().getResourceAsStream(CERT1_PEM_EXAMPLE); + InputStream msgStream = getClass().getResourceAsStream(MSG_PLAINTEXT_EXAMPLE); + InputStream sigStream = getClass().getResourceAsStream(MSG_SIG_EXAMPLE); + + ECDSASignature signer = new ECDSASignature(); + + signer.loadVerificationCertificates(certStream); + certStream.close(); + + Crypto.Signature.Builder sig = Crypto.Signature.newBuilder(); + sig.setType(Crypto.SignatureType.ECDSA); + sig.setSignerId(signer.loadedCertificates.entrySet().iterator().next().getKey()); + byte[] sigData = ByteString.readFrom(sigStream).toByteArray(); + ++sigData[0]; + + sig.setData(ByteString.copyFrom(sigData)); + + + Crypto.Signature builtSig = sig.build(); + signer.initVerify(builtSig); + signer.updateSigner(msgStream); + assertFalse("Bad Signature passed verification!", signer.verify()); + } + + + @Test + public void verifyInvalidMsg() throws Exception { + InputStream certStream = getClass().getResourceAsStream(CERT1_PEM_EXAMPLE); + InputStream msgStream = getClass().getResourceAsStream(MSG_PLAINTEXT_EXAMPLE); + InputStream sigStream = getClass().getResourceAsStream(MSG_SIG_EXAMPLE); + + ECDSASignature signer = new ECDSASignature(); + + signer.loadVerificationCertificates(certStream); + certStream.close(); + + Crypto.Signature.Builder sig = Crypto.Signature.newBuilder(); + sig.setType(Crypto.SignatureType.ECDSA); + sig.setSignerId(signer.loadedCertificates.entrySet().iterator().next().getKey()); + sig.setData(ByteString.readFrom(sigStream)); + byte[] msgData = ByteString.readFrom(msgStream).toByteArray(); + ++msgData[0]; + + Crypto.Signature builtSig = sig.build(); + signer.initVerify(builtSig); + signer.updateSigner(msgStream); + assertFalse("Signature doesn't match message but passed verification!", signer.verify()); + } + + + + @Test + public void signAndVerify() throws Exception { + InputStream keyStream = getClass().getResourceAsStream(KEYFILE_EXAMPLE); + char[] password = KEYFILE_PASSWORD.toCharArray(); + + ECDSASignature signer = new ECDSASignature(); + + KeyStore.Builder keyStore = signer.getPKCS12KeyStoreBuilder(keyStream, password); + signer.loadSigningCertificate(keyStore); + + + Voting.UnsignedBulletinBoardMessage.Builder unsignedMsgBuilder = Voting.UnsignedBulletinBoardMessage.newBuilder(); + unsignedMsgBuilder.setData(ByteString.copyFromUtf8(HELLO_WORLD)); + unsignedMsgBuilder.addTags("Tag1"); + unsignedMsgBuilder.addTags("Tag2"); + unsignedMsgBuilder.addTags("Tag3"); + + Voting.UnsignedBulletinBoardMessage usMsg = unsignedMsgBuilder.build(); + + signer.updateContent(usMsg); + Crypto.Signature sig = signer.sign(); + + signer.loadVerificationCertificates(getClass().getResourceAsStream(CERT1_PEM_EXAMPLE)); + + signer.initVerify(sig); + signer.updateContent(usMsg); + assertTrue("Couldn't verify signature on ", signer.verify()); + } + + + +} diff --git a/meerkat-common/src/test/resources/certs/README.md b/meerkat-common/src/test/resources/certs/README.md new file mode 100644 index 0000000..f7283d9 --- /dev/null +++ b/meerkat-common/src/test/resources/certs/README.md @@ -0,0 +1,6 @@ +Certs and private keys for testing generated using OpenSSL + +.crt and .pem files are in PEM format +.der files are in binary DER format + +files that have a name of the form *-with-password-xxxx.pem are encrypted with the password xxxx diff --git a/meerkat-common/src/test/resources/certs/enduser-certs/user1-key-with-password-secret.p12 b/meerkat-common/src/test/resources/certs/enduser-certs/user1-key-with-password-secret.p12 new file mode 100644 index 0000000..6281f9d Binary files /dev/null and b/meerkat-common/src/test/resources/certs/enduser-certs/user1-key-with-password-secret.p12 differ diff --git a/meerkat-common/src/test/resources/certs/enduser-certs/user1-key-with-password-secret.pem b/meerkat-common/src/test/resources/certs/enduser-certs/user1-key-with-password-secret.pem new file mode 100644 index 0000000..e859995 --- /dev/null +++ b/meerkat-common/src/test/resources/certs/enduser-certs/user1-key-with-password-secret.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,243D718A0D80C59590E582A26E87A49C + +RG6ITUTIdbJdWYX57oMn3tTCzHJSTjXAIZLjoVxy/v4UFYjluaFhGonIlbH1q2pP +ueu29Q3eT6144ypB8ARUJ1x0kRX1OL9zNHgdF9ulrCf9/nhGyC2nL+tHZ0YPbxoQ ++6yCQcRWvjUXLVzPEUnwMuHXJDpaXES8X0R4CISQKIA= +-----END EC PRIVATE KEY----- diff --git a/meerkat-common/src/test/resources/certs/enduser-certs/user1-key.der b/meerkat-common/src/test/resources/certs/enduser-certs/user1-key.der new file mode 100644 index 0000000..6f17406 Binary files /dev/null and b/meerkat-common/src/test/resources/certs/enduser-certs/user1-key.der differ diff --git a/meerkat-common/src/test/resources/certs/enduser-certs/user1-key.pem b/meerkat-common/src/test/resources/certs/enduser-certs/user1-key.pem new file mode 100644 index 0000000..6619e37 --- /dev/null +++ b/meerkat-common/src/test/resources/certs/enduser-certs/user1-key.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQge8JqCoaLoZq61aQki5Xm +GppcfAAkhHDGNQw/wLof5LmhRANCAAQJD1kW6BsNkRY9tslaugpOJOaoKX4uBz4S +Q96lPaPWkatNVgQchwNeB/hdjZwNuwE7A7XAwr69HFmhXRhsM005 +-----END PRIVATE KEY----- diff --git a/meerkat-common/src/test/resources/certs/enduser-certs/user1-pubkey.pem b/meerkat-common/src/test/resources/certs/enduser-certs/user1-pubkey.pem new file mode 100644 index 0000000..1c0a0c1 --- /dev/null +++ b/meerkat-common/src/test/resources/certs/enduser-certs/user1-pubkey.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAECQ9ZFugbDZEWPbbJWroKTiTmqCl+Lgc+ +EkPepT2j1pGrTVYEHIcDXgf4XY2cDbsBOwO1wMK+vRxZoV0YbDNNOQ== +-----END PUBLIC KEY----- diff --git a/meerkat-common/src/test/resources/certs/enduser-certs/user1.crt b/meerkat-common/src/test/resources/certs/enduser-certs/user1.crt new file mode 100644 index 0000000..d80093f --- /dev/null +++ b/meerkat-common/src/test/resources/certs/enduser-certs/user1.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDFjCCArygAwIBAgICEAAwCgYIKoZIzj0EAwIwgYIxKTAnBgNVBAMMIE1lZXJr +YXQgVm90aW5nIEludGVybWVkaWF0ZSBDQSAxMRMwEQYDVQQIDApTb21lLVN0YXRl +MQswCQYDVQQGEwJJTDEVMBMGA1UECgwMSURDIEhlcnpsaXlhMRwwGgYDVQQLDBNN +ZWVya2F0IFZvdGluZyBUZWFtMB4XDTE1MTExMTE2MTM1NFoXDTI1MTEwODE2MTM1 +NFowbjEaMBgGA1UEAwwRUG9sbGluZyBTdGF0aW9uIDExEzARBgNVBAgMClNvbWUt +U3RhdGUxCzAJBgNVBAYTAklMMRUwEwYDVQQKDAxJREMgSGVyemxpeWExFzAVBgNV +BAsMDk1lZXJrYXQgVm90aW5nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAECQ9ZFugb +DZEWPbbJWroKTiTmqCl+Lgc+EkPepT2j1pGrTVYEHIcDXgf4XY2cDbsBOwO1wMK+ +vRxZoV0YbDNNOaOCATYwggEyMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFLamS8o2 +hFNd0vWy/irEBNWVNwFXMB8GA1UdIwQYMBaAFBeyv0c75eT6PNumHo9TZ2B9vtcp +MAsGA1UdDwQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATBEBgNVHR8EPTA7MDmg +N6A1hjNodHRwOi8vY3JsLmZhY3RjZW50ZXIub3JnL21lZXJrYXQtaW50ZXJtZWRp +YXRlMS5jcmwwegYIKwYBBQUHAQEEbjBsMEEGCCsGAQUFBzAChjVodHRwOi8vcGtp +LmZhY3RjZW50ZXIub3JnL21lZXJrYXQtaW50ZXJtZWRpYXRlLWNhLmNydDAnBggr +BgEFBQcwAYYbaHR0cDovL29jc3AuZmFjdGNlbnRlci5vcmcvMAoGCCqGSM49BAMC +A0gAMEUCIQD6QbhNNmB3AVVqhmXuiLA7WF6raShw6n0g/VloVGQebQIgEvxYclpO +MMynt5wH6X65rtn4Q1EGaDMvNbFweCDsldk= +-----END CERTIFICATE----- diff --git a/meerkat-common/src/test/resources/certs/enduser-certs/user1.csr b/meerkat-common/src/test/resources/certs/enduser-certs/user1.csr new file mode 100644 index 0000000..20e1efc --- /dev/null +++ b/meerkat-common/src/test/resources/certs/enduser-certs/user1.csr @@ -0,0 +1,9 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBOjCB4QIBADCBgTELMAkGA1UEBhMCSUwxEzARBgNVBAgMClNvbWUtU3RhdGUx +ETAPBgNVBAcMCEhlcnpsaXlhMRUwEwYDVQQKDAxJREMgSGVyemxpeWExFzAVBgNV +BAsMDk1lZXJrYXQgVm90aW5nMRowGAYDVQQDDBFQb2xsaW5nIFN0YXRpb24gMTBW +MBAGByqGSM49AgEGBSuBBAAKA0IABAkPWRboGw2RFj22yVq6Ck4k5qgpfi4HPhJD +3qU9o9aRq01WBByHA14H+F2NnA27ATsDtcDCvr0cWaFdGGwzTTmgADAKBggqhkjO +PQQDAgNIADBFAiEA8gmIhALr7O5M1QLReGH3jheildTIr1mDWl14WyMf9U4CIF23 +mInyo4VqNHLzxMLg5Cn3Oddokng3OXa63y4nTfv+ +-----END CERTIFICATE REQUEST----- diff --git a/meerkat-common/src/test/resources/certs/enduser-certs/user2-key.pem b/meerkat-common/src/test/resources/certs/enduser-certs/user2-key.pem new file mode 100644 index 0000000..2d31bb8 --- /dev/null +++ b/meerkat-common/src/test/resources/certs/enduser-certs/user2-key.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgYpBEO+XWm/n6VPeMVK76 +mrZkDTpiwLsDykG7M4fU5RKhRANCAAR71/kVGyA3hdxcLBBT3NPQF6R3LholmLRN +qhnvHqzJWuy7ev+Xbuxtt9AN0ajyeFDy8Oe1bUSidnLyQi+nXC0f +-----END PRIVATE KEY----- diff --git a/meerkat-common/src/test/resources/certs/enduser-certs/user2-pubkey.pem b/meerkat-common/src/test/resources/certs/enduser-certs/user2-pubkey.pem new file mode 100644 index 0000000..5d86d4c --- /dev/null +++ b/meerkat-common/src/test/resources/certs/enduser-certs/user2-pubkey.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEe9f5FRsgN4XcXCwQU9zT0Bekdy4aJZi0 +TaoZ7x6syVrsu3r/l27sbbfQDdGo8nhQ8vDntW1EonZy8kIvp1wtHw== +-----END PUBLIC KEY----- diff --git a/meerkat-common/src/test/resources/certs/enduser-certs/user2.crt b/meerkat-common/src/test/resources/certs/enduser-certs/user2.crt new file mode 100644 index 0000000..a211365 --- /dev/null +++ b/meerkat-common/src/test/resources/certs/enduser-certs/user2.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDFjCCArygAwIBAgICEAEwCgYIKoZIzj0EAwIwgYIxKTAnBgNVBAMMIE1lZXJr +YXQgVm90aW5nIEludGVybWVkaWF0ZSBDQSAxMRMwEQYDVQQIDApTb21lLVN0YXRl +MQswCQYDVQQGEwJJTDEVMBMGA1UECgwMSURDIEhlcnpsaXlhMRwwGgYDVQQLDBNN +ZWVya2F0IFZvdGluZyBUZWFtMB4XDTE1MTExMTE2MjAzM1oXDTI1MTEwODE2MjAz +M1owbjEaMBgGA1UEAwwRUG9sbGluZyBTdGF0aW9uIDIxEzARBgNVBAgMClNvbWUt +U3RhdGUxCzAJBgNVBAYTAklMMRUwEwYDVQQKDAxJREMgSGVyemxpeWExFzAVBgNV +BAsMDk1lZXJrYXQgVm90aW5nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEe9f5FRsg +N4XcXCwQU9zT0Bekdy4aJZi0TaoZ7x6syVrsu3r/l27sbbfQDdGo8nhQ8vDntW1E +onZy8kIvp1wtH6OCATYwggEyMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFKCdquYj +DGHqAHt+4PIDlw0h2UvuMB8GA1UdIwQYMBaAFBeyv0c75eT6PNumHo9TZ2B9vtcp +MAsGA1UdDwQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATBEBgNVHR8EPTA7MDmg +N6A1hjNodHRwOi8vY3JsLmZhY3RjZW50ZXIub3JnL21lZXJrYXQtaW50ZXJtZWRp +YXRlMS5jcmwwegYIKwYBBQUHAQEEbjBsMEEGCCsGAQUFBzAChjVodHRwOi8vcGtp +LmZhY3RjZW50ZXIub3JnL21lZXJrYXQtaW50ZXJtZWRpYXRlLWNhLmNydDAnBggr +BgEFBQcwAYYbaHR0cDovL29jc3AuZmFjdGNlbnRlci5vcmcvMAoGCCqGSM49BAMC +A0gAMEUCIQDpo5B0vvEJSax3YzOMfE8l0pfDUIKLdBWJVGeq0VLtIgIgVr0+4/0e +n+R+l1OVOLh2GirloOgbv5Ch5BQ2pQNAG2Y= +-----END CERTIFICATE----- diff --git a/meerkat-common/src/test/resources/certs/enduser-certs/user2.csr b/meerkat-common/src/test/resources/certs/enduser-certs/user2.csr new file mode 100644 index 0000000..bb3c2d0 --- /dev/null +++ b/meerkat-common/src/test/resources/certs/enduser-certs/user2.csr @@ -0,0 +1,9 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBOzCB4QIBADCBgTELMAkGA1UEBhMCSUwxEzARBgNVBAgMClNvbWUtU3RhdGUx +ETAPBgNVBAcMCEhlcnpsaXlhMRUwEwYDVQQKDAxJREMgSGVyemxpeWExFzAVBgNV +BAsMDk1lZXJrYXQgVm90aW5nMRowGAYDVQQDDBFQb2xsaW5nIFN0YXRpb24gMjBW +MBAGByqGSM49AgEGBSuBBAAKA0IABHvX+RUbIDeF3FwsEFPc09AXpHcuGiWYtE2q +Ge8erMla7Lt6/5du7G230A3RqPJ4UPLw57VtRKJ2cvJCL6dcLR+gADAKBggqhkjO +PQQDAgNJADBGAiEA6Ls/ojRaZT+u4YeOBYcPbRcJE3jSTe1Sm/lR7fDyEhMCIQCk +UOca+e2b8+CqM3CURBv6TqUMmZ3HeMRvEAxFPqOWSw== +-----END CERTIFICATE REQUEST----- diff --git a/meerkat-common/src/test/resources/certs/enduser-certs/user2.der b/meerkat-common/src/test/resources/certs/enduser-certs/user2.der new file mode 100644 index 0000000..8e78409 Binary files /dev/null and b/meerkat-common/src/test/resources/certs/enduser-certs/user2.der differ diff --git a/meerkat-common/src/test/resources/certs/intermediate-ca-1/1000.pem b/meerkat-common/src/test/resources/certs/intermediate-ca-1/1000.pem new file mode 100644 index 0000000..d80093f --- /dev/null +++ b/meerkat-common/src/test/resources/certs/intermediate-ca-1/1000.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDFjCCArygAwIBAgICEAAwCgYIKoZIzj0EAwIwgYIxKTAnBgNVBAMMIE1lZXJr +YXQgVm90aW5nIEludGVybWVkaWF0ZSBDQSAxMRMwEQYDVQQIDApTb21lLVN0YXRl +MQswCQYDVQQGEwJJTDEVMBMGA1UECgwMSURDIEhlcnpsaXlhMRwwGgYDVQQLDBNN +ZWVya2F0IFZvdGluZyBUZWFtMB4XDTE1MTExMTE2MTM1NFoXDTI1MTEwODE2MTM1 +NFowbjEaMBgGA1UEAwwRUG9sbGluZyBTdGF0aW9uIDExEzARBgNVBAgMClNvbWUt +U3RhdGUxCzAJBgNVBAYTAklMMRUwEwYDVQQKDAxJREMgSGVyemxpeWExFzAVBgNV +BAsMDk1lZXJrYXQgVm90aW5nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAECQ9ZFugb +DZEWPbbJWroKTiTmqCl+Lgc+EkPepT2j1pGrTVYEHIcDXgf4XY2cDbsBOwO1wMK+ +vRxZoV0YbDNNOaOCATYwggEyMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFLamS8o2 +hFNd0vWy/irEBNWVNwFXMB8GA1UdIwQYMBaAFBeyv0c75eT6PNumHo9TZ2B9vtcp +MAsGA1UdDwQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATBEBgNVHR8EPTA7MDmg +N6A1hjNodHRwOi8vY3JsLmZhY3RjZW50ZXIub3JnL21lZXJrYXQtaW50ZXJtZWRp +YXRlMS5jcmwwegYIKwYBBQUHAQEEbjBsMEEGCCsGAQUFBzAChjVodHRwOi8vcGtp +LmZhY3RjZW50ZXIub3JnL21lZXJrYXQtaW50ZXJtZWRpYXRlLWNhLmNydDAnBggr +BgEFBQcwAYYbaHR0cDovL29jc3AuZmFjdGNlbnRlci5vcmcvMAoGCCqGSM49BAMC +A0gAMEUCIQD6QbhNNmB3AVVqhmXuiLA7WF6raShw6n0g/VloVGQebQIgEvxYclpO +MMynt5wH6X65rtn4Q1EGaDMvNbFweCDsldk= +-----END CERTIFICATE----- diff --git a/meerkat-common/src/test/resources/certs/intermediate-ca-1/1001.pem b/meerkat-common/src/test/resources/certs/intermediate-ca-1/1001.pem new file mode 100644 index 0000000..a211365 --- /dev/null +++ b/meerkat-common/src/test/resources/certs/intermediate-ca-1/1001.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDFjCCArygAwIBAgICEAEwCgYIKoZIzj0EAwIwgYIxKTAnBgNVBAMMIE1lZXJr +YXQgVm90aW5nIEludGVybWVkaWF0ZSBDQSAxMRMwEQYDVQQIDApTb21lLVN0YXRl +MQswCQYDVQQGEwJJTDEVMBMGA1UECgwMSURDIEhlcnpsaXlhMRwwGgYDVQQLDBNN +ZWVya2F0IFZvdGluZyBUZWFtMB4XDTE1MTExMTE2MjAzM1oXDTI1MTEwODE2MjAz +M1owbjEaMBgGA1UEAwwRUG9sbGluZyBTdGF0aW9uIDIxEzARBgNVBAgMClNvbWUt +U3RhdGUxCzAJBgNVBAYTAklMMRUwEwYDVQQKDAxJREMgSGVyemxpeWExFzAVBgNV +BAsMDk1lZXJrYXQgVm90aW5nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEe9f5FRsg +N4XcXCwQU9zT0Bekdy4aJZi0TaoZ7x6syVrsu3r/l27sbbfQDdGo8nhQ8vDntW1E +onZy8kIvp1wtH6OCATYwggEyMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFKCdquYj +DGHqAHt+4PIDlw0h2UvuMB8GA1UdIwQYMBaAFBeyv0c75eT6PNumHo9TZ2B9vtcp +MAsGA1UdDwQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATBEBgNVHR8EPTA7MDmg +N6A1hjNodHRwOi8vY3JsLmZhY3RjZW50ZXIub3JnL21lZXJrYXQtaW50ZXJtZWRp +YXRlMS5jcmwwegYIKwYBBQUHAQEEbjBsMEEGCCsGAQUFBzAChjVodHRwOi8vcGtp +LmZhY3RjZW50ZXIub3JnL21lZXJrYXQtaW50ZXJtZWRpYXRlLWNhLmNydDAnBggr +BgEFBQcwAYYbaHR0cDovL29jc3AuZmFjdGNlbnRlci5vcmcvMAoGCCqGSM49BAMC +A0gAMEUCIQDpo5B0vvEJSax3YzOMfE8l0pfDUIKLdBWJVGeq0VLtIgIgVr0+4/0e +n+R+l1OVOLh2GirloOgbv5Ch5BQ2pQNAG2Y= +-----END CERTIFICATE----- diff --git a/meerkat-common/src/test/resources/certs/intermediate-ca-1/certindex b/meerkat-common/src/test/resources/certs/intermediate-ca-1/certindex new file mode 100644 index 0000000..1cd80cf --- /dev/null +++ b/meerkat-common/src/test/resources/certs/intermediate-ca-1/certindex @@ -0,0 +1,2 @@ +V 251108161354Z 1000 unknown /CN=Polling Station 1/ST=Some-State/C=IL/O=IDC Herzliya/OU=Meerkat Voting +V 251108162033Z 1001 unknown /CN=Polling Station 2/ST=Some-State/C=IL/O=IDC Herzliya/OU=Meerkat Voting diff --git a/meerkat-common/src/test/resources/certs/intermediate-ca-1/certindex.attr b/meerkat-common/src/test/resources/certs/intermediate-ca-1/certindex.attr new file mode 100644 index 0000000..3a7e39e --- /dev/null +++ b/meerkat-common/src/test/resources/certs/intermediate-ca-1/certindex.attr @@ -0,0 +1 @@ +unique_subject = no diff --git a/meerkat-common/src/test/resources/certs/intermediate-ca-1/certindex.attr.old b/meerkat-common/src/test/resources/certs/intermediate-ca-1/certindex.attr.old new file mode 100644 index 0000000..3a7e39e --- /dev/null +++ b/meerkat-common/src/test/resources/certs/intermediate-ca-1/certindex.attr.old @@ -0,0 +1 @@ +unique_subject = no diff --git a/meerkat-common/src/test/resources/certs/intermediate-ca-1/certindex.old b/meerkat-common/src/test/resources/certs/intermediate-ca-1/certindex.old new file mode 100644 index 0000000..7dcd55e --- /dev/null +++ b/meerkat-common/src/test/resources/certs/intermediate-ca-1/certindex.old @@ -0,0 +1 @@ +V 251108161354Z 1000 unknown /CN=Polling Station 1/ST=Some-State/C=IL/O=IDC Herzliya/OU=Meerkat Voting diff --git a/meerkat-common/src/test/resources/certs/intermediate-ca-1/certserial b/meerkat-common/src/test/resources/certs/intermediate-ca-1/certserial new file mode 100644 index 0000000..7d802a3 --- /dev/null +++ b/meerkat-common/src/test/resources/certs/intermediate-ca-1/certserial @@ -0,0 +1 @@ +1002 diff --git a/meerkat-common/src/test/resources/certs/intermediate-ca-1/certserial.old b/meerkat-common/src/test/resources/certs/intermediate-ca-1/certserial.old new file mode 100644 index 0000000..dd11724 --- /dev/null +++ b/meerkat-common/src/test/resources/certs/intermediate-ca-1/certserial.old @@ -0,0 +1 @@ +1001 diff --git a/meerkat-common/src/test/resources/certs/intermediate-ca-1/crlnumber b/meerkat-common/src/test/resources/certs/intermediate-ca-1/crlnumber new file mode 100644 index 0000000..83b33d2 --- /dev/null +++ b/meerkat-common/src/test/resources/certs/intermediate-ca-1/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/meerkat-common/src/test/resources/certs/intermediate-ca-1/intermediate-ca-1-private-key.pem b/meerkat-common/src/test/resources/certs/intermediate-ca-1/intermediate-ca-1-private-key.pem new file mode 100644 index 0000000..cf0a641 --- /dev/null +++ b/meerkat-common/src/test/resources/certs/intermediate-ca-1/intermediate-ca-1-private-key.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgJvMhOfcQfdK/42QlBbri +IYXLM/gVHq/yppOykDqB3s6hRANCAAQoShAtCGW5c9pk/4/sKN1qjCgDKngqJpba +kku6cIDqXDr+aHsl+/KdSHd46OI3fEynl+/Pc85wRsaY6Z7b1PdS +-----END PRIVATE KEY----- diff --git a/meerkat-common/src/test/resources/certs/intermediate-ca-1/intermediate-ca-1.crt b/meerkat-common/src/test/resources/certs/intermediate-ca-1/intermediate-ca-1.crt new file mode 100644 index 0000000..751d8e7 --- /dev/null +++ b/meerkat-common/src/test/resources/certs/intermediate-ca-1/intermediate-ca-1.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDfDCCAyGgAwIBAgICEAAwCgYIKoZIzj0EAwIwgbAxCzAJBgNVBAYTAklMMRMw +EQYDVQQIDApTb21lLVN0YXRlMREwDwYDVQQHDAhIZXJ6bGl5YTEUMBIGA1UECgwL +SURDIEhlcmxpeWExHzAdBgNVBAsMFk1lZXJrYXQgVm90aW5nIFByb2plY3QxGDAW +BgNVBAMMD1Rlc3RpbmcgUm9vdCBDQTEoMCYGCSqGSIb3DQEJARYZdGVzdGluZy1j +YUBmYWN0Y2VudGVyLm9yZzAeFw0xNTExMTExNjA4MDJaFw0yNTExMDgxNjA4MDJa +MIGCMSkwJwYDVQQDDCBNZWVya2F0IFZvdGluZyBJbnRlcm1lZGlhdGUgQ0EgMTET +MBEGA1UECAwKU29tZS1TdGF0ZTELMAkGA1UEBhMCSUwxFTATBgNVBAoMDElEQyBI +ZXJ6bGl5YTEcMBoGA1UECwwTTWVlcmthdCBWb3RpbmcgVGVhbTBWMBAGByqGSM49 +AgEGBSuBBAAKA0IABChKEC0IZblz2mT/j+wo3WqMKAMqeComltqSS7pwgOpcOv5o +eyX78p1Id3jo4jd8TKeX789zznBGxpjpntvU91KjggFYMIIBVDAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBQXsr9HO+Xk+jzbph6PU2dgfb7XKTAfBgNVHSMEGDAW +gBSJD9L1fLmX4A9CBoLsYXn3OPy1ojALBgNVHQ8EBAMCAaYwEwYDVR0lBAwwCgYI +KwYBBQUHAwEwPgYDVR0fBDcwNTAzoDGgL4YtaHR0cDovL2NybC5mYWN0Y2VudGVy +Lm9yZy9tZWVya2F0LXJvb3QtY2EuY3JsMCsGA1UdEQQkMCKCIE1lZXJrYXQgVm90 +aW5nIEludGVybWVkaWF0ZSBDQSAxMHIGCCsGAQUFBwEBBGYwZDA5BggrBgEFBQcw +AoYtaHR0cDovL3BraS5mYWN0Y2VudGVyLm9yZy9tZWVya2F0LXJvb3QtY2EuY3J0 +MCcGCCsGAQUFBzABhhtodHRwOi8vb2NzcC5mYWN0Y2VudGVyLm9yZy8wCgYIKoZI +zj0EAwIDSQAwRgIhALEMHq2ssC9rLXiG8v6NcZetwwxdu3B3LW9s0KeGoNIEAiEA +skA56tMnhiZe38msyanRyRrAHyBI2fGs6GP3UBrg2P8= +-----END CERTIFICATE----- diff --git a/meerkat-common/src/test/resources/certs/intermediate-ca-1/intermediate-ca-1.csr b/meerkat-common/src/test/resources/certs/intermediate-ca-1/intermediate-ca-1.csr new file mode 100644 index 0000000..fce3021 --- /dev/null +++ b/meerkat-common/src/test/resources/certs/intermediate-ca-1/intermediate-ca-1.csr @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBTTCB9QIBADCBlTELMAkGA1UEBhMCSUwxEzARBgNVBAgMClNvbWUtU3RhdGUx +ETAPBgNVBAcMCEhlcnpsaXlhMRUwEwYDVQQKDAxJREMgSGVyemxpeWExHDAaBgNV +BAsME01lZXJrYXQgVm90aW5nIFRlYW0xKTAnBgNVBAMMIE1lZXJrYXQgVm90aW5n +IEludGVybWVkaWF0ZSBDQSAxMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEKEoQLQhl +uXPaZP+P7CjdaowoAyp4KiaW2pJLunCA6lw6/mh7JfvynUh3eOjiN3xMp5fvz3PO +cEbGmOme29T3UqAAMAoGCCqGSM49BAMCA0cAMEQCIFlyJO5NFqnMUu5hOlQa872E +yy0V3zkqeN6Aly+LtEQqAiAfHwbi1lkJOZT2tOX8gfJzcac2jKmbgIhmITNq7uma +Wg== +-----END CERTIFICATE REQUEST----- diff --git a/meerkat-common/src/test/resources/certs/intermediate-ca-1/openssl-intermediate-ca.conf b/meerkat-common/src/test/resources/certs/intermediate-ca-1/openssl-intermediate-ca.conf new file mode 100644 index 0000000..090ca1a --- /dev/null +++ b/meerkat-common/src/test/resources/certs/intermediate-ca-1/openssl-intermediate-ca.conf @@ -0,0 +1,46 @@ +[ ca ] +default_ca = myca + +[ crl_ext ] +issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always + + [ myca ] + dir = ./ + new_certs_dir = $dir + unique_subject = no + certificate = $dir/intermediate-ca-1.crt + database = $dir/certindex + private_key = $dir/intermediate-ca-1-private-key.pem + serial = $dir/certserial + default_days = 3650 + default_md = sha256 + policy = myca_policy + x509_extensions = myca_extensions + crlnumber = $dir/crlnumber + default_crl_days = 3650 + + [ myca_policy ] + commonName = supplied + stateOrProvinceName = optional + countryName = optional + emailAddress = optional + organizationName = supplied + organizationalUnitName = optional + + [ myca_extensions ] + basicConstraints = critical,CA:FALSE + keyUsage = critical,any + subjectKeyIdentifier = hash + authorityKeyIdentifier = keyid:always,issuer + keyUsage = digitalSignature,keyEncipherment + extendedKeyUsage = serverAuth + crlDistributionPoints = @crl_section + authorityInfoAccess = @ocsp_section + + [crl_section] + URI.0 = http://crl.factcenter.org/meerkat-intermediate1.crl + + [ocsp_section] + caIssuers;URI.0 = http://pki.factcenter.org/meerkat-intermediate-ca.crt + OCSP;URI.0 = http://ocsp.factcenter.org/ diff --git a/meerkat-common/src/test/resources/certs/root-ca/1000.pem b/meerkat-common/src/test/resources/certs/root-ca/1000.pem new file mode 100644 index 0000000..751d8e7 --- /dev/null +++ b/meerkat-common/src/test/resources/certs/root-ca/1000.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDfDCCAyGgAwIBAgICEAAwCgYIKoZIzj0EAwIwgbAxCzAJBgNVBAYTAklMMRMw +EQYDVQQIDApTb21lLVN0YXRlMREwDwYDVQQHDAhIZXJ6bGl5YTEUMBIGA1UECgwL +SURDIEhlcmxpeWExHzAdBgNVBAsMFk1lZXJrYXQgVm90aW5nIFByb2plY3QxGDAW +BgNVBAMMD1Rlc3RpbmcgUm9vdCBDQTEoMCYGCSqGSIb3DQEJARYZdGVzdGluZy1j +YUBmYWN0Y2VudGVyLm9yZzAeFw0xNTExMTExNjA4MDJaFw0yNTExMDgxNjA4MDJa +MIGCMSkwJwYDVQQDDCBNZWVya2F0IFZvdGluZyBJbnRlcm1lZGlhdGUgQ0EgMTET +MBEGA1UECAwKU29tZS1TdGF0ZTELMAkGA1UEBhMCSUwxFTATBgNVBAoMDElEQyBI +ZXJ6bGl5YTEcMBoGA1UECwwTTWVlcmthdCBWb3RpbmcgVGVhbTBWMBAGByqGSM49 +AgEGBSuBBAAKA0IABChKEC0IZblz2mT/j+wo3WqMKAMqeComltqSS7pwgOpcOv5o +eyX78p1Id3jo4jd8TKeX789zznBGxpjpntvU91KjggFYMIIBVDAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBQXsr9HO+Xk+jzbph6PU2dgfb7XKTAfBgNVHSMEGDAW +gBSJD9L1fLmX4A9CBoLsYXn3OPy1ojALBgNVHQ8EBAMCAaYwEwYDVR0lBAwwCgYI +KwYBBQUHAwEwPgYDVR0fBDcwNTAzoDGgL4YtaHR0cDovL2NybC5mYWN0Y2VudGVy +Lm9yZy9tZWVya2F0LXJvb3QtY2EuY3JsMCsGA1UdEQQkMCKCIE1lZXJrYXQgVm90 +aW5nIEludGVybWVkaWF0ZSBDQSAxMHIGCCsGAQUFBwEBBGYwZDA5BggrBgEFBQcw +AoYtaHR0cDovL3BraS5mYWN0Y2VudGVyLm9yZy9tZWVya2F0LXJvb3QtY2EuY3J0 +MCcGCCsGAQUFBzABhhtodHRwOi8vb2NzcC5mYWN0Y2VudGVyLm9yZy8wCgYIKoZI +zj0EAwIDSQAwRgIhALEMHq2ssC9rLXiG8v6NcZetwwxdu3B3LW9s0KeGoNIEAiEA +skA56tMnhiZe38msyanRyRrAHyBI2fGs6GP3UBrg2P8= +-----END CERTIFICATE----- diff --git a/meerkat-common/src/test/resources/certs/root-ca/certindex b/meerkat-common/src/test/resources/certs/root-ca/certindex new file mode 100644 index 0000000..e4550ca --- /dev/null +++ b/meerkat-common/src/test/resources/certs/root-ca/certindex @@ -0,0 +1 @@ +V 251108160802Z 1000 unknown /CN=Meerkat Voting Intermediate CA 1/ST=Some-State/C=IL/O=IDC Herzliya/OU=Meerkat Voting Team diff --git a/meerkat-common/src/test/resources/certs/root-ca/certindex.attr b/meerkat-common/src/test/resources/certs/root-ca/certindex.attr new file mode 100644 index 0000000..3a7e39e --- /dev/null +++ b/meerkat-common/src/test/resources/certs/root-ca/certindex.attr @@ -0,0 +1 @@ +unique_subject = no diff --git a/meerkat-common/src/test/resources/certs/root-ca/certindex.old b/meerkat-common/src/test/resources/certs/root-ca/certindex.old new file mode 100644 index 0000000..e69de29 diff --git a/meerkat-common/src/test/resources/certs/root-ca/certserial b/meerkat-common/src/test/resources/certs/root-ca/certserial new file mode 100644 index 0000000..dd11724 --- /dev/null +++ b/meerkat-common/src/test/resources/certs/root-ca/certserial @@ -0,0 +1 @@ +1001 diff --git a/meerkat-common/src/test/resources/certs/root-ca/certserial.old b/meerkat-common/src/test/resources/certs/root-ca/certserial.old new file mode 100644 index 0000000..83b33d2 --- /dev/null +++ b/meerkat-common/src/test/resources/certs/root-ca/certserial.old @@ -0,0 +1 @@ +1000 diff --git a/meerkat-common/src/test/resources/certs/root-ca/crlnumber b/meerkat-common/src/test/resources/certs/root-ca/crlnumber new file mode 100644 index 0000000..83b33d2 --- /dev/null +++ b/meerkat-common/src/test/resources/certs/root-ca/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/meerkat-common/src/test/resources/certs/root-ca/openssl-ca.conf b/meerkat-common/src/test/resources/certs/root-ca/openssl-ca.conf new file mode 100644 index 0000000..39e8b00 --- /dev/null +++ b/meerkat-common/src/test/resources/certs/root-ca/openssl-ca.conf @@ -0,0 +1,61 @@ +[ ca ] +default_ca = myca + +[ crl_ext ] +issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always + + [ myca ] + dir = ./ + new_certs_dir = $dir + unique_subject = no + certificate = $dir/root-ca.crt + database = $dir/certindex + private_key = $dir/root-ca-private-key.pem + serial = $dir/certserial + default_days = 3650 + default_md = sha256 + policy = myca_policy + x509_extensions = myca_extensions + crlnumber = $dir/crlnumber + default_crl_days = 3650 + + [ myca_policy ] + commonName = supplied + stateOrProvinceName = optional + countryName = optional + emailAddress = optional + organizationName = supplied + organizationalUnitName = optional + + [ myca_extensions ] + basicConstraints = critical,CA:TRUE + keyUsage = critical,any + subjectKeyIdentifier = hash + authorityKeyIdentifier = keyid:always,issuer + keyUsage = digitalSignature,keyEncipherment,cRLSign,keyCertSign + extendedKeyUsage = serverAuth + crlDistributionPoints = @crl_section + subjectAltName = @alt_names + authorityInfoAccess = @ocsp_section + + [ v3_ca ] + basicConstraints = critical,CA:TRUE,pathlen:0 + keyUsage = critical,any + subjectKeyIdentifier = hash + authorityKeyIdentifier = keyid:always,issuer + keyUsage = digitalSignature,keyEncipherment,cRLSign,keyCertSign + extendedKeyUsage = serverAuth + crlDistributionPoints = @crl_section + subjectAltName = @alt_names + authorityInfoAccess = @ocsp_section + + [alt_names] + DNS.0 = Meerkat Voting Intermediate CA 1 + + [crl_section] + URI.0 = http://crl.factcenter.org/meerkat-root-ca.crl + + [ocsp_section] + caIssuers;URI.0 = http://pki.factcenter.org/meerkat-root-ca.crt + OCSP;URI.0 = http://ocsp.factcenter.org/ diff --git a/meerkat-common/src/test/resources/certs/root-ca/root-ca-private-key-with-password-secret.pem b/meerkat-common/src/test/resources/certs/root-ca/root-ca-private-key-with-password-secret.pem new file mode 100644 index 0000000..a0c442d --- /dev/null +++ b/meerkat-common/src/test/resources/certs/root-ca/root-ca-private-key-with-password-secret.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,B8CA131346FD6C9568A6C80935F2AF14 + +8q1seEln39/tQTo5KqN+qNRhd0fQ0oC71dYpfTHsP0NlNmjMtwKo2niFwzjxnSyP +vpJjGzUlnq30ucbeJA7CDm/1cmYAU5gGQ7gldgpi2TQVS+EBjqi/Y5P9AlrgLv6K +tKe4AvkqQcpi4ZvlUL9xmNaM9jEH4syopR9YClEMfa8= +-----END EC PRIVATE KEY----- diff --git a/meerkat-common/src/test/resources/certs/root-ca/root-ca-private-key.der b/meerkat-common/src/test/resources/certs/root-ca/root-ca-private-key.der new file mode 100644 index 0000000..008e65b Binary files /dev/null and b/meerkat-common/src/test/resources/certs/root-ca/root-ca-private-key.der differ diff --git a/meerkat-common/src/test/resources/certs/root-ca/root-ca-private-key.pem b/meerkat-common/src/test/resources/certs/root-ca/root-ca-private-key.pem new file mode 100644 index 0000000..7966a28 --- /dev/null +++ b/meerkat-common/src/test/resources/certs/root-ca/root-ca-private-key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHQCAQEEIEi9y6pSKu1kDZcIfQQAnojl1iFxm32W0DVCp2P6HRrkoAcGBSuBBAAK +oUQDQgAEoijIYF12bpA0tcjyQnWZGQ4lzdBGR+hK/5al/M+zFgFwvWHoWf6yJsSB +ymviB5yUaH+cE+/3LXlGbpRzYKLBYQ== +-----END EC PRIVATE KEY----- diff --git a/meerkat-common/src/test/resources/certs/root-ca/root-ca.crt b/meerkat-common/src/test/resources/certs/root-ca/root-ca.crt new file mode 100644 index 0000000..d0bd1fa --- /dev/null +++ b/meerkat-common/src/test/resources/certs/root-ca/root-ca.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICpTCCAkygAwIBAgIJAJoVb07aGgNaMAoGCCqGSM49BAMCMIGwMQswCQYDVQQG +EwJJTDETMBEGA1UECAwKU29tZS1TdGF0ZTERMA8GA1UEBwwISGVyemxpeWExFDAS +BgNVBAoMC0lEQyBIZXJsaXlhMR8wHQYDVQQLDBZNZWVya2F0IFZvdGluZyBQcm9q +ZWN0MRgwFgYDVQQDDA9UZXN0aW5nIFJvb3QgQ0ExKDAmBgkqhkiG9w0BCQEWGXRl +c3RpbmctY2FAZmFjdGNlbnRlci5vcmcwHhcNMTUxMTExMTUzODE4WhcNMjUxMTA4 +MTUzODE4WjCBsDELMAkGA1UEBhMCSUwxEzARBgNVBAgMClNvbWUtU3RhdGUxETAP +BgNVBAcMCEhlcnpsaXlhMRQwEgYDVQQKDAtJREMgSGVybGl5YTEfMB0GA1UECwwW +TWVlcmthdCBWb3RpbmcgUHJvamVjdDEYMBYGA1UEAwwPVGVzdGluZyBSb290IENB +MSgwJgYJKoZIhvcNAQkBFhl0ZXN0aW5nLWNhQGZhY3RjZW50ZXIub3JnMFYwEAYH +KoZIzj0CAQYFK4EEAAoDQgAEoijIYF12bpA0tcjyQnWZGQ4lzdBGR+hK/5al/M+z +FgFwvWHoWf6yJsSBymviB5yUaH+cE+/3LXlGbpRzYKLBYaNQME4wHQYDVR0OBBYE +FIkP0vV8uZfgD0IGguxhefc4/LWiMB8GA1UdIwQYMBaAFIkP0vV8uZfgD0IGguxh +efc4/LWiMAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIgNftHrW30Git8 +VFQKyMCkasauSpEHpAGdcRAhRHqUQMUCIDxw++trz/Iv8818xVB1ARr9EQAmH0aC +7MHETGuiBC7L +-----END CERTIFICATE----- diff --git a/meerkat-common/src/test/resources/certs/secp256k1.pem b/meerkat-common/src/test/resources/certs/secp256k1.pem new file mode 100644 index 0000000..32d952e --- /dev/null +++ b/meerkat-common/src/test/resources/certs/secp256k1.pem @@ -0,0 +1,3 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQACg== +-----END EC PARAMETERS----- diff --git a/meerkat-common/src/test/resources/certs/signed-messages/helloworld.txt b/meerkat-common/src/test/resources/certs/signed-messages/helloworld.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/meerkat-common/src/test/resources/certs/signed-messages/helloworld.txt @@ -0,0 +1 @@ + diff --git a/meerkat-common/src/test/resources/certs/signed-messages/helloworld.txt.sha256sig b/meerkat-common/src/test/resources/certs/signed-messages/helloworld.txt.sha256sig new file mode 100644 index 0000000..7e717d1 Binary files /dev/null and b/meerkat-common/src/test/resources/certs/signed-messages/helloworld.txt.sha256sig differ