/* * Copyright (C) 2014 Intel Corporation * All rights reserved. */ package com.intel.mtwilson.tls.policy.formats; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.MappingIterator; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyNamingStrategy; import com.fasterxml.jackson.dataformat.csv.CsvMapper; import com.fasterxml.jackson.dataformat.csv.CsvParser; import com.fasterxml.jackson.dataformat.csv.CsvSchema; import com.intel.dcsg.cpg.crypto.CryptographyException; import com.intel.dcsg.cpg.crypto.RsaUtil; import com.intel.dcsg.cpg.crypto.Sha256Digest; import com.intel.dcsg.cpg.x509.X509Util; import java.io.IOException; import java.security.KeyPair; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.util.ArrayList; import java.util.List; import org.apache.commons.codec.binary.Base64; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * * @author jbuhacoff */ public class PublicKeyTlsPolicyTest { private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(PublicKeyTlsPolicyTest.class); private static List<PublicKey> publicKeys = new ArrayList<>(); @BeforeClass public static void createPublicKeys() throws NoSuchAlgorithmException { for(int i=0; i<3; i++) { KeyPair keypair = RsaUtil.generateRsaKeyPair(1028); publicKeys.add(keypair.getPublic()); } } public static class PublicKeyTlsPolicy { public List<PublicKey> publicKeys; } @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonIgnoreProperties(ignoreUnknown=true) public static class PublicKeyDigest { public PublicKeyDigest() { } public PublicKeyDigest(String algorithm, byte[] digest) { this.algorithm = algorithm; this.digest = digest; } public String algorithm; public byte[] digest; } public static class PublicKeyDigestTlsPolicy { public List<PublicKeyDigest> publicKeyDigests; } @Test public void testPublicKeyPem() throws CryptographyException { StringBuilder pem = new StringBuilder(); for(PublicKey publicKey : publicKeys) { pem.append(RsaUtil.encodePemPublicKey(publicKey)); } String text = pem.toString(); log.debug("PEM:\n{}", text); List<PublicKey> decoded = RsaUtil.decodePemPublicKeys(text); int max = publicKeys.size(); for(int i=0; i<max; i++) { assertArrayEquals(String.format("record %d", i),publicKeys.get(i).getEncoded(), decoded.get(i).getEncoded()); } } @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonIgnoreProperties(ignoreUnknown=true) public static class PublicKeyJsonMeta { public PublicKeyJsonMeta() { } public int version = 1; } @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonIgnoreProperties(ignoreUnknown=true) public static class PublicKeyDigestJsonMeta { public PublicKeyDigestJsonMeta() { } public int version = 1; public String algorithm = null; } @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonIgnoreProperties(ignoreUnknown=true) public static class PublicKeyJson { public PublicKeyJson() { } public PublicKeyJsonMeta meta = null; public List<String> publicKeys = new ArrayList<>(); } @Test public void testPublicKeyJson() throws CryptographyException, JsonProcessingException, IOException { ObjectMapper mapper = new ObjectMapper(); mapper.setPropertyNamingStrategy(new PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy()); PublicKeyJson json = new PublicKeyJson(); json.meta = new PublicKeyJsonMeta(); for(PublicKey publicKey : publicKeys) { json.publicKeys.add(Base64.encodeBase64String(publicKey.getEncoded())); } String text = mapper.writeValueAsString(json); log.debug("JSON:\n{}", text); PublicKeyJson decoded = mapper.readValue(text, PublicKeyJson.class); int max = publicKeys.size(); for(int i=0; i<max; i++) { assertEquals(String.format("record %d", i),Base64.encodeBase64String(publicKeys.get(i).getEncoded()), decoded.publicKeys.get(i)); } } public static class PublicKeyDigestCsv { public PublicKeyDigestCsv() { } public PublicKeyDigestCsv(String algorithm, String digest) { this.algorithm = algorithm; this.digest = digest; } public String algorithm; public String digest; } @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonIgnoreProperties(ignoreUnknown=true) public static class PublicKeyDigestJson { public PublicKeyDigestJson() { } public PublicKeyDigestJsonMeta meta = null; public List<PublicKeyDigest> publicKeyDigests = new ArrayList<>(); } @Test public void testPublicKeyDigestCsv() throws JsonProcessingException, IOException { CsvSchema schema = CsvSchema.builder() .addColumn("algorithm", CsvSchema.ColumnType.STRING) .addColumn("digest", CsvSchema.ColumnType.STRING) .build(); CsvMapper mapper = new CsvMapper(); ArrayList<PublicKeyDigestCsv> lines = new ArrayList<>(); for(PublicKey publicKey : publicKeys) { lines.add(new PublicKeyDigestCsv("sha256", Sha256Digest.digestOf(publicKey.getEncoded()).toBase64())); } String text = "# inserting a comment here\n"+mapper.writer(schema).writeValueAsString(lines); log.debug("CSV:\n{}", text); mapper.enable(CsvParser.Feature.TRIM_SPACES); // mapper.enable(CsvParser.Feature.WRAP_AS_ARRAY); // not needed. ArrayList<PublicKeyDigestCsv> decoded = new ArrayList<>(); MappingIterator<PublicKeyDigestCsv> it = mapper.reader(PublicKeyDigestCsv.class).with(schema).readValues(text); while(it.hasNext()) { PublicKeyDigestCsv csv = it.next(); if( csv.algorithm != null && csv.algorithm.startsWith("#")) { continue; // ignore comment lines } decoded.add(csv); } // ArrayList<PublicKeyDigestCsv> decoded = mapper.reader(PublicKeyDigestCsv.class).with(schema).readValue(text); // does not work: cannot cast PublicKeyDigestCsv to ArrayList int max = publicKeys.size(); for(int i=0; i<max; i++) { assertEquals(Sha256Digest.digestOf(publicKeys.get(i).getEncoded()).toBase64(), decoded.get(i).digest); } } @Test public void testPublicKeyDigestJson() throws CryptographyException, JsonProcessingException, IOException { ObjectMapper mapper = new ObjectMapper(); mapper.setPropertyNamingStrategy(new PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy()); PublicKeyDigestJson json = new PublicKeyDigestJson(); for(PublicKey publicKey : publicKeys) { json.publicKeyDigests.add(new PublicKeyDigest("sha256",Sha256Digest.digestOf(publicKey.getEncoded()).toByteArray())); } String text = mapper.writeValueAsString(json); log.debug("JSON:\n{}", text); PublicKeyDigestJson decoded = mapper.readValue(text, PublicKeyDigestJson.class); int max = publicKeys.size(); for(int i=0; i<max; i++) { assertArrayEquals(String.format("record %d", i),Sha256Digest.digestOf(publicKeys.get(i).getEncoded()).toByteArray(), decoded.publicKeyDigests.get(i).digest); } } @Test public void testPublicKeyDigestJsonWithMeta() throws CryptographyException, JsonProcessingException, IOException { ObjectMapper mapper = new ObjectMapper(); mapper.setPropertyNamingStrategy(new PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy()); PublicKeyDigestJson json = new PublicKeyDigestJson(); json.meta = new PublicKeyDigestJsonMeta(); json.meta.algorithm = "sha256"; // can set it here if they are all the same for(PublicKey publicKey : publicKeys) { json.publicKeyDigests.add(new PublicKeyDigest(null,Sha256Digest.digestOf(publicKey.getEncoded()).toByteArray())); } String text = mapper.writeValueAsString(json); log.debug("JSON:\n{}", text); PublicKeyDigestJson decoded = mapper.readValue(text, PublicKeyDigestJson.class); int max = publicKeys.size(); for(int i=0; i<max; i++) { assertArrayEquals(String.format("record %d", i),Sha256Digest.digestOf(publicKeys.get(i).getEncoded()).toByteArray(), decoded.publicKeyDigests.get(i).digest); } } }