1 // Copyright 2017 Google Inc. 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 specified language governing permissions and 13 // limitations under the License. 14 // 15 //////////////////////////////////////////////////////////////////////////////// 16 17 package com.google.crypto.tink.testing; 18 19 import com.google.crypto.tink.internal.testing.TestFiles; 20 import com.google.crypto.tink.subtle.EllipticCurves; 21 import com.google.crypto.tink.subtle.Enums.HashType; 22 import com.google.gson.JsonArray; 23 import com.google.gson.JsonObject; 24 import com.google.gson.JsonParser; 25 import java.io.ByteArrayOutputStream; 26 import java.io.IOException; 27 import java.io.InputStream; 28 import java.nio.charset.Charset; 29 import java.security.NoSuchAlgorithmException; 30 31 /** Wycheproof Test helpers. */ 32 public final class WycheproofTestUtil { 33 private static final Charset UTF_8 = Charset.forName("UTF-8"); 34 35 /** 36 * Gets hash type from hash name. 37 * 38 * @param md the name of the message digest (e.g. "SHA-256"). 39 * @return the hash type. 40 * @throws NoSuchAlgorithmException iff the hash name is unknown. 41 */ getHashType(String md)42 public static HashType getHashType(String md) throws NoSuchAlgorithmException { 43 switch (md) { 44 case "SHA-256": 45 return HashType.SHA256; 46 case "SHA-512": 47 return HashType.SHA512; 48 case "SHA-1": 49 return HashType.SHA1; 50 default: 51 throw new NoSuchAlgorithmException("Unsupported hash name: " + md); 52 } 53 } 54 55 /** 56 * Returns the algorithm name for a digital signature algorithm with a given message digest. The 57 * algorithm names used in JCA are a bit inconsequential. E.g. a dash is necessary for message 58 * digests (e.g. "SHA-256") but are not used in the corresponding names for digital signatures 59 * (e.g. "SHA256WITHECDSA"). 60 * 61 * <p>See http://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html 62 * 63 * @param md the name of the message digest (e.g. "SHA-256") 64 * @param signatureAlgorithm the name of the signature algorithm (e.g. "ECDSA") 65 * @return the algorithm name for the signature scheme with the given hash. 66 */ getSignatureAlgorithmName(String md, String signatureAlgorithm)67 public static String getSignatureAlgorithmName(String md, String signatureAlgorithm) { 68 if (md.equals("SHA-256")) { 69 md = "SHA256"; 70 } else if (md.equals("SHA-512")) { 71 md = "SHA512"; 72 } else { 73 return ""; 74 } 75 return md + "WITH" + signatureAlgorithm; 76 } 77 78 /** 79 * Reads all bytes from {@code inputStream}. 80 */ readAll(InputStream inputStream)81 private static byte[] readAll(InputStream inputStream) throws IOException { 82 ByteArrayOutputStream result = new ByteArrayOutputStream(); 83 byte[] buf = new byte[1024]; 84 int count; 85 while ((count = inputStream.read(buf)) != -1) { 86 result.write(buf, 0, count); 87 } 88 return result.toByteArray(); 89 } 90 91 /** Gets JsonObject from file. */ readJson(String path)92 public static JsonObject readJson(String path) throws IOException { 93 JsonObject result; 94 try (InputStream inputStream = TestFiles.openInputFile(path)) { 95 result = JsonParser.parseString(new String(readAll(inputStream), UTF_8)).getAsJsonObject(); 96 } 97 String algorithm = result.get("algorithm").getAsString(); 98 String generatorVersion = result.get("generatorVersion").getAsString(); 99 int numTests = result.get("numberOfTests").getAsInt(); 100 System.out.println( 101 String.format( 102 "Read from %s total %d test cases for algorithm %s with generator version %s", 103 path, numTests, algorithm, generatorVersion)); 104 return result; 105 } 106 /** 107 * Gets curve type from curve name. 108 * 109 * @throws NoSuchAlgorithmException iff the curve name is unknown. 110 */ getCurveType(String curveName)111 public static EllipticCurves.CurveType getCurveType(String curveName) 112 throws NoSuchAlgorithmException { 113 switch (curveName) { 114 case "secp256r1": 115 return EllipticCurves.CurveType.NIST_P256; 116 case "secp384r1": 117 return EllipticCurves.CurveType.NIST_P384; 118 case "secp521r1": 119 return EllipticCurves.CurveType.NIST_P521; 120 default: 121 throw new NoSuchAlgorithmException("Unknown curve name: " + curveName); 122 } 123 } 124 125 /** @return true if the test case has one of the flags. */ checkFlags(JsonObject testcase, String... flags)126 public static boolean checkFlags(JsonObject testcase, String... flags) throws Exception { 127 JsonArray entries = testcase.get("flags").getAsJsonArray(); 128 for (int i = 0; i < entries.size(); i++) { 129 for (String flag : flags) { 130 if (flag.equals(entries.get(i).getAsString())) { 131 return true; 132 } 133 } 134 } 135 return false; 136 } 137 WycheproofTestUtil()138 private WycheproofTestUtil() {} 139 } 140