1 // Copyright 2021 Google LLC 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 specific language governing permissions and 13 // limitations under the License. 14 // 15 //////////////////////////////////////////////////////////////////////////////// 16 17 package com.google.crypto.tink.jwt; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static org.junit.Assert.assertThrows; 21 import static org.junit.Assert.assertTrue; 22 23 import com.google.crypto.tink.InsecureSecretKeyAccess; 24 import com.google.crypto.tink.KeyTemplates; 25 import com.google.crypto.tink.KeysetHandle; 26 import com.google.crypto.tink.RegistryConfiguration; 27 import com.google.crypto.tink.TinkJsonProtoKeysetFormat; 28 import com.google.crypto.tink.TinkProtoKeysetFormat; 29 import com.google.crypto.tink.proto.KeyData; 30 import com.google.crypto.tink.proto.KeyData.KeyMaterialType; 31 import com.google.crypto.tink.proto.KeyStatusType; 32 import com.google.crypto.tink.proto.Keyset; 33 import com.google.crypto.tink.subtle.Base64; 34 import com.google.crypto.tink.testing.TestUtil; 35 import com.google.crypto.tink.tinkkey.KeyAccess; 36 import com.google.gson.JsonArray; 37 import com.google.gson.JsonObject; 38 import com.google.gson.JsonParser; 39 import com.google.protobuf.ByteString; 40 import java.security.GeneralSecurityException; 41 import org.junit.Before; 42 import org.junit.Test; 43 import org.junit.experimental.theories.DataPoints; 44 import org.junit.experimental.theories.FromDataPoints; 45 import org.junit.experimental.theories.Theories; 46 import org.junit.experimental.theories.Theory; 47 import org.junit.runner.RunWith; 48 49 /** Unit tests for JwkSetConverter */ 50 @RunWith(Theories.class) 51 public final class JwkSetConverterTest { 52 53 @Before setup()54 public void setup() throws Exception { 55 JwtSignatureConfig.register(); 56 } 57 58 private static final String ES256_KEYSET = 59 "{\"primaryKeyId\":282600252,\"key\":[{\"keyData\":{" 60 + "\"typeUrl\":\"type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey\"," 61 + "\"value\":\"EAEaIBDPI66hjLHvjxmUJ2nyHIBDmdOtQ4gPsvWgYYgZ0gygIiBTEK0rTACpAb97m+mvtJKAk0" 62 + "q3mHjPcUZm0C4EueDW4Q==\"," 63 + "\"keyMaterialType\":\"ASYMMETRIC_PUBLIC\"" 64 + "},\"status\":\"ENABLED\",\"keyId\":282600252,\"outputPrefixType\":\"RAW\"}]}"; 65 private static final String ES256_JWK_SET = 66 "{\"keys\":[{" 67 + "\"kty\":\"EC\"," 68 + "\"crv\":\"P-256\"," 69 + "\"x\":\"EM8jrqGMse-PGZQnafIcgEOZ061DiA-y9aBhiBnSDKA\"," 70 + "\"y\":\"UxCtK0wAqQG_e5vpr7SSgJNKt5h4z3FGZtAuBLng1uE\"," 71 + "\"use\":\"sig\",\"alg\":\"ES256\",\"key_ops\":[\"verify\"]}]}"; 72 73 private static final String ES256_KEYSET_TINK = 74 "{\"primaryKeyId\":282600252,\"key\":[{\"keyData\":{" 75 + "\"typeUrl\":\"type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey\"," 76 + "\"value\":\"EAEaIBDPI66hjLHvjxmUJ2nyHIBDmdOtQ4gPsvWgYYgZ0gygIiBTEK0rTACpAb97m+mvtJKAk0" 77 + "q3mHjPcUZm0C4EueDW4Q==\"," 78 + "\"keyMaterialType\":\"ASYMMETRIC_PUBLIC\"" 79 + "},\"status\":\"ENABLED\",\"keyId\":282600252,\"outputPrefixType\":\"TINK\"}]}"; 80 private static final String ES256_JWK_SET_KID = 81 "{\"keys\":[{" 82 + "\"kty\":\"EC\"," 83 + "\"crv\":\"P-256\"," 84 + "\"x\":\"EM8jrqGMse-PGZQnafIcgEOZ061DiA-y9aBhiBnSDKA\"," 85 + "\"y\":\"UxCtK0wAqQG_e5vpr7SSgJNKt5h4z3FGZtAuBLng1uE\"," 86 + "\"use\":\"sig\",\"alg\":\"ES256\",\"key_ops\":[\"verify\"]," 87 + "\"kid\":\"ENgjPA\"}]}"; 88 private static final String ES256_JWK_SET_KID_TINK = 89 "{\"primaryKeyId\":1623060913,\"key\":[{\"keyData\":{" 90 + "\"typeUrl\":\"type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey\"," 91 + "\"value\":\"EAEaIQAQzyOuoYyx748ZlCdp8hyAQ5nTrUOID7L1oGGIGdIMoCIhAFMQrStMAKkBv3ub6a+0ko" 92 + "CTSreYeM9xRmbQLgS54NbhKggKBkVOZ2pQQQ==\"," 93 + "\"keyMaterialType\":\"ASYMMETRIC_PUBLIC\"}," 94 + "\"status\":\"ENABLED\",\"keyId\":1623060913,\"outputPrefixType\":\"RAW\"}]}"; 95 96 private static final String ES384_KEYSET = 97 "{\"primaryKeyId\":456087424,\"key\":[{\"keyData\":{" 98 + "\"typeUrl\":\"type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey\"," 99 + "\"value\":\"EAIaMQDSjvWihoKGmr4nlDuI/KkvuPvEZr+B4bU0MuXQQXgyNMGApFm2iTeotv7LCSsG3mQiME" 100 + "HIMGx4wa+Y8yeJQWMiSpukpPM7jP9GqaykZQQ2GY/NLg/n9+BJtntgvFhG5gWLTg==\"," 101 + "\"keyMaterialType\":\"ASYMMETRIC_PUBLIC\"" 102 + "},\"status\":\"ENABLED\",\"keyId\":456087424,\"outputPrefixType\":\"RAW\"}]}"; 103 private static final String ES384_JWK_SET = 104 "{\"keys\":[{\"kty\":\"EC\",\"crv\":\"P-384\"," 105 + "\"x\":\"0o71ooaChpq-J5Q7iPypL7j7xGa_geG1NDLl0EF4MjTBgKRZtok3qLb-ywkrBt5k\"," 106 + "\"y\":\"QcgwbHjBr5jzJ4lBYyJKm6Sk8zuM_0aprKRlBDYZj80uD-f34Em2e2C8WEbmBYtO\"," 107 + "\"use\":\"sig\",\"alg\":\"ES384\",\"key_ops\":[\"verify\"]}]}"; 108 109 private static final String ES512_KEYSET = 110 "{\"primaryKeyId\":1570200439,\"key\":[{\"keyData\":{" 111 + "\"typeUrl\":\"type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey\"," 112 + "\"value\":\"EAMaQgEV3nweRej6Z1/aPTqCkc1tQla5eVI68+qfwR1kB/wXCuYCB5otarhomUt64Fah/8Tjf0" 113 + "WJHMZyFr86RUitiRQm1SJCATht/NOX8RcbaEr1MaH+0BFTaepvpTzSfQ04C2P8VCoURB3GeVKk4VQh8O/KLSYf" 114 + "X+58bqEnaZ0G7W9qjHa2ols2\"," 115 + "\"keyMaterialType\":\"ASYMMETRIC_PUBLIC\"" 116 + "},\"status\":\"ENABLED\",\"keyId\":1570200439,\"outputPrefixType\":\"RAW\"}]}"; 117 private static final String ES512_JWK_SET = 118 "{\"keys\":[{\"kty\":\"EC\",\"crv\":\"P-521\"," 119 + "\"x\":\"ARXefB5F6PpnX9o9OoKRzW1CVrl5Ujrz6p_BHWQH_BcK5gIHmi1quGiZS3rgVqH_xON_RYkcxnIWvzpFSK2JFCbV\"," 120 + "\"y\":\"ATht_NOX8RcbaEr1MaH-0BFTaepvpTzSfQ04C2P8VCoURB3GeVKk4VQh8O_KLSYfX-58bqEnaZ0G7W9qjHa2ols2\"," 121 + "\"use\":\"sig\",\"alg\":\"ES512\",\"key_ops\":[\"verify\"]}]}"; 122 123 private static final String RS256_KEYSET = 124 "{\"primaryKeyId\":482168993,\"key\":[{\"keyData\":{" 125 + "\"typeUrl\":\"type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PublicKey\"," 126 + "\"value\":\"EAEagQIAkspk37lGBqXmPPq2CL5KdDeRx7xFiTadpL3jc4nXaqftCtpM6qExfrc2JLaIsnwpwf" 127 + "GMClfe/alIs2GrT9fpM8oDeCccvC39DzZhsSFnAELggi3hnWNKRLfSV0UJzBI+5hZ6ifUsv8W8mSHKlsVMmvOf" 128 + "C2P5+l72qTwN6Le3hy6CxFp5s9pw011B7J3PU65sty6GI9sehB2B/n7nfiWw9YN5++pfwyoitzoMoVKOOpj7fF" 129 + "q88f8ArpC7kR1SBTe20Bt1AmpZDT2Dmfmlb/Q1UFjj/F3C77NCNQ344ZcAEI42HY+uighy5GdKQRHMoTT1OzyD" 130 + "G90ABjggQqDGW+zXzyIDAQAB\"," 131 + "\"keyMaterialType\":\"ASYMMETRIC_PUBLIC\"" 132 + "},\"status\":\"ENABLED\",\"keyId\":482168993,\"outputPrefixType\":\"RAW\"}]}"; 133 // 134 private static final String RS256_JWK_SET = 135 "{\"keys\":[{\"kty\":\"RSA\"," 136 + "\"n\":\"kspk37lGBqXmPPq2CL5KdDeRx7xFiTadpL3jc4nXaqftCtpM6qExfrc2JLaIsnwpwfGMClfe_alIs2" 137 + "GrT9fpM8oDeCccvC39DzZhsSFnAELggi3hnWNKRLfSV0UJzBI-5hZ6ifUsv8W8mSHKlsVMmvOfC2P5-l72qTwN" 138 + "6Le3hy6CxFp5s9pw011B7J3PU65sty6GI9sehB2B_n7nfiWw9YN5--pfwyoitzoMoVKOOpj7fFq88f8ArpC7kR" 139 + "1SBTe20Bt1AmpZDT2Dmfmlb_Q1UFjj_F3C77NCNQ344ZcAEI42HY-uighy5GdKQRHMoTT1OzyDG90ABjggQqDG" 140 + "W-zXzw\"," 141 + "\"e\":\"AQAB\",\"use\":\"sig\",\"alg\":\"RS256\",\"key_ops\":[\"verify\"]}]}"; 142 143 private static final String RS256_KEYSET_TINK = 144 "{\"primaryKeyId\":482168993,\"key\":[{\"keyData\":{" 145 + "\"typeUrl\":\"type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PublicKey\"," 146 + "\"value\":\"EAEagQIAkspk37lGBqXmPPq2CL5KdDeRx7xFiTadpL3jc4nXaqftCtpM6qExfrc2JLaIsnwpwf" 147 + "GMClfe/alIs2GrT9fpM8oDeCccvC39DzZhsSFnAELggi3hnWNKRLfSV0UJzBI+5hZ6ifUsv8W8mSHKlsVMmvOf" 148 + "C2P5+l72qTwN6Le3hy6CxFp5s9pw011B7J3PU65sty6GI9sehB2B/n7nfiWw9YN5++pfwyoitzoMoVKOOpj7fF" 149 + "q88f8ArpC7kR1SBTe20Bt1AmpZDT2Dmfmlb/Q1UFjj/F3C77NCNQ344ZcAEI42HY+uighy5GdKQRHMoTT1OzyD" 150 + "G90ABjggQqDGW+zXzyIDAQAB\"," 151 + "\"keyMaterialType\":\"ASYMMETRIC_PUBLIC\"" 152 + "},\"status\":\"ENABLED\",\"keyId\":482168993,\"outputPrefixType\":\"TINK\"}]}"; 153 private static final String RS256_JWK_SET_KID = 154 "{\"keys\":[{\"kty\":\"RSA\"," 155 + "\"n\":\"kspk37lGBqXmPPq2CL5KdDeRx7xFiTadpL3jc4nXaqftCtpM6qExfrc2JLaIsnwpwfGMClfe_alIs2" 156 + "GrT9fpM8oDeCccvC39DzZhsSFnAELggi3hnWNKRLfSV0UJzBI-5hZ6ifUsv8W8mSHKlsVMmvOfC2P5-l72qTwN" 157 + "6Le3hy6CxFp5s9pw011B7J3PU65sty6GI9sehB2B_n7nfiWw9YN5--pfwyoitzoMoVKOOpj7fFq88f8ArpC7kR" 158 + "1SBTe20Bt1AmpZDT2Dmfmlb_Q1UFjj_F3C77NCNQ344ZcAEI42HY-uighy5GdKQRHMoTT1OzyDG90ABjggQqDG" 159 + "W-zXzw\"," 160 + "\"e\":\"AQAB\",\"use\":\"sig\",\"alg\":\"RS256\",\"key_ops\":[\"verify\"]," 161 + "\"kid\":\"HL1QoQ\"}]}"; 162 private static final String RS256_JWK_SET_KID_TINK = 163 "{\"primaryKeyId\":1204986267,\"key\":[{\"keyData\":{" 164 + "\"typeUrl\":\"type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PublicKey\"," 165 + "\"value\":\"EAEagQIAkspk37lGBqXmPPq2CL5KdDeRx7xFiTadpL3jc4nXaqftCtpM6qExfrc2JLaIsnwpwf" 166 + "GMClfe/alIs2GrT9fpM8oDeCccvC39DzZhsSFnAELggi3hnWNKRLfSV0UJzBI+5hZ6ifUsv8W8mSHKlsVMmvOf" 167 + "C2P5+l72qTwN6Le3hy6CxFp5s9pw011B7J3PU65sty6GI9sehB2B/n7nfiWw9YN5++pfwyoitzoMoVKOOpj7fF" 168 + "q88f8ArpC7kR1SBTe20Bt1AmpZDT2Dmfmlb/Q1UFjj/F3C77NCNQ344ZcAEI42HY+uighy5GdKQRHMoTT1OzyD" 169 + "G90ABjggQqDGW+zXzyIDAQABKggKBkhMMVFvUQ==\"," 170 + "\"keyMaterialType\":\"ASYMMETRIC_PUBLIC\"}," 171 + "\"status\":\"ENABLED\",\"keyId\":1204986267,\"outputPrefixType\":\"RAW\"}]}"; 172 173 private static final String RS384_KEYSET = 174 "{\"primaryKeyId\":333504275,\"key\":[{\"keyData\":{" 175 + "\"typeUrl\":\"type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PublicKey\"," 176 + "\"value\":\"EAIagQMAnlBY5WD7gVQjNKvrS2whLKzt0Eql72B6haZ17eKifNn4S49eGdBy9RLj/mvHXAbacr" 177 + "ngt9fzi0iv/WQ57jUmtO1b/wLt5LYk9APsBYjywDCIe+u9UouikP7c3SBqjjQijZ50jgYbMY6cL7s2Gx5lI1vl" 178 + "GX3ZExLVYbNoI9VBFAWjSDefd6GugESxXQFnnO3p2GHOKryZLeDH/KzVacTq2/pVXKVH/9/EQzcLB0oYUljZ4v" 179 + "YQ4HCAcwnUZbirsRwA0350Dz0Mlj+3+9sSAF8FPA+F/wlIBkPqjJ26b80V5FU4mBTzvYoXGTjkD7+bxH9p28hu" 180 + "JSU96P4WdG5PYVwI1VEYwGipkUIpMWjJ7dXAtmltHzM9vkUt2bsBe9vyJjmRXyoC6mHSJbSyOm9Dd8BENobcUL" 181 + "9h+aBoxruY+mU49kAHzzeAntn8C+vIrxN+X6N2EU9N8t9BF+mwYiBEsY54wx99RbRrY9yICfPBmQJGwXSxNCXB" 182 + "RrbJyxkIVuqvACP5IgMBAAE=\"," 183 + "\"keyMaterialType\":\"ASYMMETRIC_PUBLIC\"" 184 + "},\"status\":\"ENABLED\",\"keyId\":333504275,\"outputPrefixType\":\"RAW\"}]}"; 185 private static final String RS384_JWK_SET = 186 "{\"keys\":[{\"kty\":\"RSA\"," 187 + "\"n\":\"nlBY5WD7gVQjNKvrS2whLKzt0Eql72B6haZ17eKifNn4S49eGdBy9RLj_mvHXAbacrngt9fzi0iv_W" 188 + "Q57jUmtO1b_wLt5LYk9APsBYjywDCIe-u9UouikP7c3SBqjjQijZ50jgYbMY6cL7s2Gx5lI1vlGX3ZExLVYbNo" 189 + "I9VBFAWjSDefd6GugESxXQFnnO3p2GHOKryZLeDH_KzVacTq2_pVXKVH_9_EQzcLB0oYUljZ4vYQ4HCAcwnUZb" 190 + "irsRwA0350Dz0Mlj-3-9sSAF8FPA-F_wlIBkPqjJ26b80V5FU4mBTzvYoXGTjkD7-bxH9p28huJSU96P4WdG5P" 191 + "YVwI1VEYwGipkUIpMWjJ7dXAtmltHzM9vkUt2bsBe9vyJjmRXyoC6mHSJbSyOm9Dd8BENobcUL9h-aBoxruY-m" 192 + "U49kAHzzeAntn8C-vIrxN-X6N2EU9N8t9BF-mwYiBEsY54wx99RbRrY9yICfPBmQJGwXSxNCXBRrbJyxkIVuqv" 193 + "ACP5\"," 194 + "\"e\":\"AQAB\",\"use\":\"sig\",\"alg\":\"RS384\",\"key_ops\":[\"verify\"]}]}"; 195 196 private static final String RS512_KEYSET = 197 "{\"primaryKeyId\":705596479,\"key\":[{\"keyData\":{" 198 + "\"typeUrl\":\"type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PublicKey\"," 199 + "\"value\":\"EAMagQQAkKxZ9IRzF56gh47RXLJzQ6lffcnBmQSwvxUDJ0wHpKZzfAawOn1uidbgEoQ3XWOgtN" 200 + "vi7QeKLE4GjQa5bY0xdRnu8nKjFcsvH+eu1sV8oVoZ984J5mT1mhwU6nt26p4xKyeapMhzYYNvKudQjQJ8SbpV" 201 + "OFpEiJ7j0ECMUd4Q8mCUqWsrXYE8+1CcHjprsIxdot+haCARc72RBj9cLuBIhJNzlFXNmsYh8yoSiEYr/auRvg" 202 + "/kIlNlnlOK/rJM/jMXbB6FuWdePrtqZ+ce2TVyARqjZJ0G0vZcPuvOhgS4LM7/Aeal84ZhIcHladSo/g8pK1eU" 203 + "hnRqRXJpsltwux+1XVJeg2a0FQ0BN3Ft25uu5jhfvGWXeTkQOR7LbpbxKTI+vumSy9dmY4UrgAG37N8Xj5/Neq" 204 + "BT51L3qE6tk2ZLoO7yjRjhADK5lnbb4iYWWvWd3kqyv0JVlxfDzjAaYtiduEUIdCe45MGk8DpCn9Lnjlunhm4Q" 205 + "yQufK8k8UPiBbWNEODI8pjTSEjs0wyMqhegBKAvtVEhr029bg3Lv7YjN9FDvx4usuWGc16bXkTqNgCK4KzPG7P" 206 + "wV120r6IVGflfpSkd5rrkzDY01fsP0mW57QCHA67bxqLUECr2dAfNzz6ddS9pqXQyXZWCyWKcvTFsGrr1oECwD" 207 + "OmW+nUIHGklr9Q0iAwEAAQ==\"," 208 + "\"keyMaterialType\":\"ASYMMETRIC_PUBLIC\"" 209 + "},\"status\":\"ENABLED\",\"keyId\":705596479,\"outputPrefixType\":\"RAW\"}]}"; 210 private static final String RS512_JWK_SET = 211 "{\"keys\":[{\"kty\":\"RSA\"," 212 + "\"n\":\"kKxZ9IRzF56gh47RXLJzQ6lffcnBmQSwvxUDJ0wHpKZzfAawOn1uidbgEoQ3XWOgtNvi7QeKLE4GjQ" 213 + "a5bY0xdRnu8nKjFcsvH-eu1sV8oVoZ984J5mT1mhwU6nt26p4xKyeapMhzYYNvKudQjQJ8SbpVOFpEiJ7j0ECM" 214 + "Ud4Q8mCUqWsrXYE8-1CcHjprsIxdot-haCARc72RBj9cLuBIhJNzlFXNmsYh8yoSiEYr_auRvg_kIlNlnlOK_r" 215 + "JM_jMXbB6FuWdePrtqZ-ce2TVyARqjZJ0G0vZcPuvOhgS4LM7_Aeal84ZhIcHladSo_g8pK1eUhnRqRXJpsltw" 216 + "ux-1XVJeg2a0FQ0BN3Ft25uu5jhfvGWXeTkQOR7LbpbxKTI-vumSy9dmY4UrgAG37N8Xj5_NeqBT51L3qE6tk2" 217 + "ZLoO7yjRjhADK5lnbb4iYWWvWd3kqyv0JVlxfDzjAaYtiduEUIdCe45MGk8DpCn9Lnjlunhm4QyQufK8k8UPiB" 218 + "bWNEODI8pjTSEjs0wyMqhegBKAvtVEhr029bg3Lv7YjN9FDvx4usuWGc16bXkTqNgCK4KzPG7PwV120r6IVGfl" 219 + "fpSkd5rrkzDY01fsP0mW57QCHA67bxqLUECr2dAfNzz6ddS9pqXQyXZWCyWKcvTFsGrr1oECwDOmW-nUIHGklr" 220 + "9Q0\"," 221 + "\"e\":\"AQAB\",\"use\":\"sig\",\"alg\":\"RS512\",\"key_ops\":[\"verify\"]}]}"; 222 223 private static final String PS256_KEYSET = 224 "{\"primaryKeyId\":1508587714,\"key\":[{\"keyData\":{" 225 + "\"typeUrl\":\"type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPublicKey\"," 226 + "\"value\":\"EAEagQMAj7Eud2n5G11qsdtjpgGWjW4cAKalSE1atm7d+Cp8biRX9wbmLJRMUvoO2j7Sp9Szx1" 227 + "TMmksY2Ugf/7+Nv9fY7vBbmxOiBQVTvikWn0FgPwhFTXTz+9fhGjM6E6sdSOUzjM6nsPulKqOQ8Aed+TLIlgvw" 228 + "uSTF4B5d6QkZWBymq7My6vV+epzWnoLpVDzCHh+c35r81Pyrj6tiTPQzPLN2ixeanclMjx8deNwlak3vwBdMDg" 229 + "wQ63rVCo2eWDS/BYK4rG22luSTDVfQVHU1NXlwXEnb/eONFSF6ZbD6JXFMT3uHT4okTOrX4Kd34stbPIUtZFUy" 230 + "3XiSeCGtghBXLMf/ge113Q9WDJ+RN1Xa4vgHJCO0+VO+cAugVkiu9UgsPP8o/r7tA2aP/Ps8EHYa1IaZg75vnr" 231 + "MZPvsTH7WG2SjSgW9GLLsbNJLFFqLFMwPuZPe8BbgvimPdStXasX/PN6DLKoK2PaT0I+iLK9mRi1Z4OjFbl9KA" 232 + "ZXXElhAQTzrEI2adIgMBAAE=\"," 233 + "\"keyMaterialType\":\"ASYMMETRIC_PUBLIC\"" 234 + "},\"status\":\"ENABLED\",\"keyId\":1508587714,\"outputPrefixType\":\"RAW\"}]}"; 235 236 private static final String PS256_JWK_SET = 237 "{\"keys\":[{\"kty\":\"RSA\"," 238 + "\"n\":\"j7Eud2n5G11qsdtjpgGWjW4cAKalSE1atm7d-Cp8biRX9wbmLJRMUvoO2j7Sp9Szx1TMmksY2Ugf_7" 239 + "-Nv9fY7vBbmxOiBQVTvikWn0FgPwhFTXTz-9fhGjM6E6sdSOUzjM6nsPulKqOQ8Aed-TLIlgvwuSTF4B5d6QkZ" 240 + "WBymq7My6vV-epzWnoLpVDzCHh-c35r81Pyrj6tiTPQzPLN2ixeanclMjx8deNwlak3vwBdMDgwQ63rVCo2eWD" 241 + "S_BYK4rG22luSTDVfQVHU1NXlwXEnb_eONFSF6ZbD6JXFMT3uHT4okTOrX4Kd34stbPIUtZFUy3XiSeCGtghBX" 242 + "LMf_ge113Q9WDJ-RN1Xa4vgHJCO0-VO-cAugVkiu9UgsPP8o_r7tA2aP_Ps8EHYa1IaZg75vnrMZPvsTH7WG2S" 243 + "jSgW9GLLsbNJLFFqLFMwPuZPe8BbgvimPdStXasX_PN6DLKoK2PaT0I-iLK9mRi1Z4OjFbl9KAZXXElhAQTzrE" 244 + "I2ad\"," 245 + "\"e\":\"AQAB\",\"use\":\"sig\",\"alg\":\"PS256\",\"key_ops\":[\"verify\"]}]}"; 246 247 private static final String PS256_KEYSET_TINK = 248 "{\"primaryKeyId\":1508587714,\"key\":[{\"keyData\":{" 249 + "\"typeUrl\":\"type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPublicKey\"," 250 + "\"value\":\"EAEagQMAj7Eud2n5G11qsdtjpgGWjW4cAKalSE1atm7d+Cp8biRX9wbmLJRMUvoO2j7Sp9Szx1" 251 + "TMmksY2Ugf/7+Nv9fY7vBbmxOiBQVTvikWn0FgPwhFTXTz+9fhGjM6E6sdSOUzjM6nsPulKqOQ8Aed+TLIlgvw" 252 + "uSTF4B5d6QkZWBymq7My6vV+epzWnoLpVDzCHh+c35r81Pyrj6tiTPQzPLN2ixeanclMjx8deNwlak3vwBdMDg" 253 + "wQ63rVCo2eWDS/BYK4rG22luSTDVfQVHU1NXlwXEnb/eONFSF6ZbD6JXFMT3uHT4okTOrX4Kd34stbPIUtZFUy" 254 + "3XiSeCGtghBXLMf/ge113Q9WDJ+RN1Xa4vgHJCO0+VO+cAugVkiu9UgsPP8o/r7tA2aP/Ps8EHYa1IaZg75vnr" 255 + "MZPvsTH7WG2SjSgW9GLLsbNJLFFqLFMwPuZPe8BbgvimPdStXasX/PN6DLKoK2PaT0I+iLK9mRi1Z4OjFbl9KA" 256 + "ZXXElhAQTzrEI2adIgMBAAE=\"," 257 + "\"keyMaterialType\":\"ASYMMETRIC_PUBLIC\"" 258 + "},\"status\":\"ENABLED\",\"keyId\":1508587714,\"outputPrefixType\":\"TINK\"}]}"; 259 private static final String PS256_JWK_SET_KID = 260 "{\"keys\":[{\"kty\":\"RSA\"," 261 + "\"n\":\"j7Eud2n5G11qsdtjpgGWjW4cAKalSE1atm7d-Cp8biRX9wbmLJRMUvoO2j7Sp9Szx1TMmksY2Ugf_7" 262 + "-Nv9fY7vBbmxOiBQVTvikWn0FgPwhFTXTz-9fhGjM6E6sdSOUzjM6nsPulKqOQ8Aed-TLIlgvwuSTF4B5d6QkZ" 263 + "WBymq7My6vV-epzWnoLpVDzCHh-c35r81Pyrj6tiTPQzPLN2ixeanclMjx8deNwlak3vwBdMDgwQ63rVCo2eWD" 264 + "S_BYK4rG22luSTDVfQVHU1NXlwXEnb_eONFSF6ZbD6JXFMT3uHT4okTOrX4Kd34stbPIUtZFUy3XiSeCGtghBX" 265 + "LMf_ge113Q9WDJ-RN1Xa4vgHJCO0-VO-cAugVkiu9UgsPP8o_r7tA2aP_Ps8EHYa1IaZg75vnrMZPvsTH7WG2S" 266 + "jSgW9GLLsbNJLFFqLFMwPuZPe8BbgvimPdStXasX_PN6DLKoK2PaT0I-iLK9mRi1Z4OjFbl9KAZXXElhAQTzrE" 267 + "I2ad\"," 268 + "\"e\":\"AQAB\",\"use\":\"sig\",\"alg\":\"PS256\",\"key_ops\":[\"verify\"]," 269 + "\"kid\":\"Wes4wg\"}]}"; 270 private static final String PS256_JWK_SET_KID_TINK = 271 "{\"primaryKeyId\":1004877962,\"key\":[{\"keyData\":{" 272 + "\"typeUrl\":\"type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPublicKey\"," 273 + "\"value\":\"EAEagQMAj7Eud2n5G11qsdtjpgGWjW4cAKalSE1atm7d+Cp8biRX9wbmLJRMUvoO2j7Sp9Szx1" 274 + "TMmksY2Ugf/7+Nv9fY7vBbmxOiBQVTvikWn0FgPwhFTXTz+9fhGjM6E6sdSOUzjM6nsPulKqOQ8Aed+TLIlgvw" 275 + "uSTF4B5d6QkZWBymq7My6vV+epzWnoLpVDzCHh+c35r81Pyrj6tiTPQzPLN2ixeanclMjx8deNwlak3vwBdMDg" 276 + "wQ63rVCo2eWDS/BYK4rG22luSTDVfQVHU1NXlwXEnb/eONFSF6ZbD6JXFMT3uHT4okTOrX4Kd34stbPIUtZFUy" 277 + "3XiSeCGtghBXLMf/ge113Q9WDJ+RN1Xa4vgHJCO0+VO+cAugVkiu9UgsPP8o/r7tA2aP/Ps8EHYa1IaZg75vnr" 278 + "MZPvsTH7WG2SjSgW9GLLsbNJLFFqLFMwPuZPe8BbgvimPdStXasX/PN6DLKoK2PaT0I+iLK9mRi1Z4OjFbl9KA" 279 + "ZXXElhAQTzrEI2adIgMBAAEqCAoGV2VzNHdn\"," 280 + "\"keyMaterialType\":\"ASYMMETRIC_PUBLIC\"}," 281 + "\"status\":\"ENABLED\",\"keyId\":1004877962,\"outputPrefixType\":\"RAW\"}]}"; 282 283 private static final String PS384_KEYSET = 284 "{\"primaryKeyId\":1042230435,\"key\":[{\"keyData\":{" 285 + "\"typeUrl\":\"type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPublicKey\"," 286 + "\"value\":\"EAIagQMAv6a0OergWYmY1k6l6vx6Of5+RxCeeQ9jMTXQyvO0GCgMDExxtqVS8S25ehZ5LNDIiG" 287 + "jhE3v2++D7QEjnzOC5UqI1ZwPxUBSrOaf5oDbJ9vBc2c7wDyJhRV8UobQSpzunD4kXypVhytjwRdiP61vG0C/e" 288 + "L0x+LijtM/XVee1Y+5mWrypVrB6EHKtdkMx2WIYNpsFOForFrr6JzLbWfDRWoqbCXKYivnw+CSE38ddW1XsrAT" 289 + "76E2Vf+womuwyBbkjLaiWvNxNFBTap2IaBLKAni6x7pqYCeu1n9eMUi41oz9QM8xfOvpH+wubc2PjwyTsb1FDT" 290 + "LnhV36tQLTVGdQdCDMF2Z8Agrnio3n1SFjSbYgFyVtpCwFKM2Z0zfO7k9jVbYYkzglzkJfp/lQrsuWqe4CVJjF" 291 + "E1H4BxcU7L0j8755kGJI08h1b7LPgqJcPgtHjcqbxHFU2yOf7mNGlW7YTnoQBO0StzQUk7kEw3X0+niEwX/L8j" 292 + "qW4YMbxrGdAfkTnPIgMBAAE=\"," 293 + "\"keyMaterialType\":\"ASYMMETRIC_PUBLIC\"" 294 + "},\"status\":\"ENABLED\",\"keyId\":1042230435,\"outputPrefixType\":\"RAW\"}]}"; 295 296 private static final String PS384_JWK_SET = 297 "{\"keys\":[{\"kty\":\"RSA\"," 298 + "\"n\":\"v6a0OergWYmY1k6l6vx6Of5-RxCeeQ9jMTXQyvO0GCgMDExxtqVS8S25ehZ5LNDIiGjhE3v2--D7QE" 299 + "jnzOC5UqI1ZwPxUBSrOaf5oDbJ9vBc2c7wDyJhRV8UobQSpzunD4kXypVhytjwRdiP61vG0C_eL0x-LijtM_XV" 300 + "ee1Y-5mWrypVrB6EHKtdkMx2WIYNpsFOForFrr6JzLbWfDRWoqbCXKYivnw-CSE38ddW1XsrAT76E2Vf-womuw" 301 + "yBbkjLaiWvNxNFBTap2IaBLKAni6x7pqYCeu1n9eMUi41oz9QM8xfOvpH-wubc2PjwyTsb1FDTLnhV36tQLTVG" 302 + "dQdCDMF2Z8Agrnio3n1SFjSbYgFyVtpCwFKM2Z0zfO7k9jVbYYkzglzkJfp_lQrsuWqe4CVJjFE1H4BxcU7L0j" 303 + "8755kGJI08h1b7LPgqJcPgtHjcqbxHFU2yOf7mNGlW7YTnoQBO0StzQUk7kEw3X0-niEwX_L8jqW4YMbxrGdAf" 304 + "kTnP\"," 305 + "\"e\":\"AQAB\",\"use\":\"sig\",\"alg\":\"PS384\",\"key_ops\":[\"verify\"]}]}"; 306 307 private static final String PS512_KEYSET = 308 "{\"primaryKeyId\":257081135,\"key\":[{\"keyData\":{" 309 + "\"typeUrl\":\"type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPublicKey\"," 310 + "\"value\":\"EAMagQQAnOUQvBwNRgeI3zlzIhVo4NzFVCsQn9hd2EIclz6cWBRMFr4EX5lXLK0StSIB7EQP4c" 311 + "iHa+vr59sOgMFMC2kiXRUXNtl99QhGwH0YjbWeDC50PKEAjH1hhhPgSw2dFcUVs4jbScDrwNn1sQ8rkgSNczvQ" 312 + "NpV1MtBhS/CC1PxVF88JaejG2zr+unoFlw7xnqxBWMzNrMHZHwqga2vL3inSbvA/RGQjnE2DzQSwZkXthGSwYB" 313 + "jOYbGawMN4onkAx/myHMyTg/TLAqG9GUyB0DVelvVoGZG/QJBY2Fp2FlpOQRKeBr6pC7Lk8zZL4GJk264KoOpG" 314 + "8v1t7PveN+STIdTE2D548K+GDOvsvrO4ZhofS/iqN9xLucuU1HkqKUqyLvMxsWum8Zhp7zinFdBnDOgeheOHUg" 315 + "N/iwjupk6u1Svt+RWNJsfb2l0jrvzf0cRMbPeLZRmpDwBxBvXWo61u6uaBEVb+ooZ6K5+hx3Rld7wXktjYIZzH" 316 + "qUr39P5yTw28b8Y2dPFWR4vwr2/0zBxcDmTRRtQ7vPOtZPD0/LVIXkgbBiLILpycnucWt9Lq9Hc62KFiTQOAuu" 317 + "Oxz7ObBegXjnFupiZZ9PyzO5WgT9lRpH7U7tzGLAjV+AUpjH6HA1o6bRLKOHFBPS+I9IqAYb/RpF6M/6hCmC2R" 318 + "z64yYzR3y4vHKGMiAwEAAQ==\"," 319 + "\"keyMaterialType\":\"ASYMMETRIC_PUBLIC\"" 320 + "},\"status\":\"ENABLED\",\"keyId\":257081135,\"outputPrefixType\":\"RAW\"}]}"; 321 322 private static final String PS512_JWK_SET = 323 "{\"keys\":[{\"kty\":\"RSA\"," 324 + "\"n\":\"nOUQvBwNRgeI3zlzIhVo4NzFVCsQn9hd2EIclz6cWBRMFr4EX5lXLK0StSIB7EQP4ciHa-vr59sOgM" 325 + "FMC2kiXRUXNtl99QhGwH0YjbWeDC50PKEAjH1hhhPgSw2dFcUVs4jbScDrwNn1sQ8rkgSNczvQNpV1MtBhS_CC" 326 + "1PxVF88JaejG2zr-unoFlw7xnqxBWMzNrMHZHwqga2vL3inSbvA_RGQjnE2DzQSwZkXthGSwYBjOYbGawMN4on" 327 + "kAx_myHMyTg_TLAqG9GUyB0DVelvVoGZG_QJBY2Fp2FlpOQRKeBr6pC7Lk8zZL4GJk264KoOpG8v1t7PveN-ST" 328 + "IdTE2D548K-GDOvsvrO4ZhofS_iqN9xLucuU1HkqKUqyLvMxsWum8Zhp7zinFdBnDOgeheOHUgN_iwjupk6u1S" 329 + "vt-RWNJsfb2l0jrvzf0cRMbPeLZRmpDwBxBvXWo61u6uaBEVb-ooZ6K5-hx3Rld7wXktjYIZzHqUr39P5yTw28" 330 + "b8Y2dPFWR4vwr2_0zBxcDmTRRtQ7vPOtZPD0_LVIXkgbBiLILpycnucWt9Lq9Hc62KFiTQOAuuOxz7ObBegXjn" 331 + "FupiZZ9PyzO5WgT9lRpH7U7tzGLAjV-AUpjH6HA1o6bRLKOHFBPS-I9IqAYb_RpF6M_6hCmC2Rz64yYzR3y4vH" 332 + "KGM\"," 333 + "\"e\":\"AQAB\",\"use\":\"sig\",\"alg\":\"PS512\",\"key_ops\":[\"verify\"]}]}"; 334 335 private static final String P256_PUBLIC_KEYSET_SMALL_COORDINATES = 336 "{\"primaryKeyId\":2124611562,\"key\":[{\"keyData\":{\"typeUrl\":" 337 + " \"type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey\"" 338 + " ,\"value\":\"EAEaH2lFjtbwLgtzRDh7dV9sYmW4IWl3ZKA+WghvrQPiCNoiIEJ8pQXMy" 339 + " A/JywaGWT+IHmWxuVYWqdxkPsUSHLhSQm51\",\"keyMaterialType\":\"ASYMMETRIC_PUBLIC\"}" 340 + " ,\"status\":\"ENABLED\",\"keyId\":2124611562,\"outputPrefixType\":\"TINK\"}]}"; 341 private static final String P384_PUBLIC_KEYSET_SMALL_COORDINATES = 342 "{\"primaryKeyId\":4159170178,\"key\":[{\"keyData\":{" 343 + " \"typeUrl\":\"type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey\"," 344 + " \"value\":\"EAIaL/bm1+e6X7gat+MJK3e65BGlZzKIf6I1q0Ro8zAKeyryUxgvZl8Ww/NlcVN2XJhEI" 345 + " jA3b73hm8eDfSEEUAAaJbrLZFOFGnSdTWng116r+hOvszYiov+WrsTyIgnL/9aRdN8=\"," 346 + " \"keyMaterialType\":\"ASYMMETRIC_PUBLIC\"},\"status\":\"ENABLED\"," 347 + " \"keyId\":4159170178,\"outputPrefixType\":\"TINK\"}]}"; 348 private static final String P521_PUBLIC_KEYSET_SMALL_COORDINATES = 349 "{\"primaryKeyId\":1286030637,\"key\":[{\"keyData\":{" 350 + " \"typeUrl\":\"type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey\"," 351 + " \"value\":\"EAMaQUgdEssWf+tdFT3vSoy/OAotV501af+XQ6JSXDjnOPCzZnFh8fYwrJ8Yu8XYF3" 352 + " 3IeHBdAIKyicKuW884JkjYR1qJIkH2OWoa4SOmk0FtpeRBZHPbs7U8SMFXVkaV+HZtjmfl11QGiQU9hqU" 353 + " hoW9ock2K0xg6wdcWBe67YTVFdQbThFmtCg==\",\"keyMaterialType\":\"ASYMMETRIC_PUBLIC\"}," 354 + " \"status\":\"ENABLED\",\"keyId\":1286030637,\"outputPrefixType\":\"TINK\"}]}"; 355 356 private static final String PRIVATEKEY_KEYSET = 357 "{\"primaryKeyId\":152493399,\"key\":[{\"keyData\":{" 358 + "\"typeUrl\":\"type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey\"," 359 + "\"value\":\"EkYQARogaHkaakArEB51RyZ236S5x3BxaNTFycWuXIGZF8adZ2UiIFlZT7MFogZ8ARbS1URIAP" 360 + "cpw8A0g2uwAHRkBqGUiCU2GiBI4jtU/59Zajohgeezi2BXB13O8IJh8V3b0itq5zyy5Q==\"," 361 + "\"keyMaterialType\":\"ASYMMETRIC_PRIVATE\"" 362 + "},\"status\":\"ENABLED\",\"keyId\":152493399,\"outputPrefixType\":\"RAW\"}]}"; 363 364 private static final String KEYSET_WITH_TWO_KEYS = 365 "{\"primaryKeyId\":282600252,\"key\":[" 366 + "{\"keyData\":{" 367 + "\"typeUrl\":\"type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey\"," 368 + "\"value\":\"EAEaIBDPI66hjLHvjxmUJ2nyHIBDmdOtQ4gPsvWgYYgZ0gygIiBTEK0rTACpAb97m+mvtJKAk0" 369 + "q3mHjPcUZm0C4EueDW4Q==\"," 370 + "\"keyMaterialType\":\"ASYMMETRIC_PUBLIC\"" 371 + "},\"status\":\"ENABLED\",\"keyId\":282600252,\"outputPrefixType\":\"RAW\"}," 372 + "{\"keyData\":{" 373 + "\"typeUrl\":\"type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PublicKey\"," 374 + "\"value\":\"EAEagQIAkspk37lGBqXmPPq2CL5KdDeRx7xFiTadpL3jc4nXaqftCtpM6qExfrc2JLaIsnwpwf" 375 + "GMClfe/alIs2GrT9fpM8oDeCccvC39DzZhsSFnAELggi3hnWNKRLfSV0UJzBI+5hZ6ifUsv8W8mSHKlsVMmvOf" 376 + "C2P5+l72qTwN6Le3hy6CxFp5s9pw011B7J3PU65sty6GI9sehB2B/n7nfiWw9YN5++pfwyoitzoMoVKOOpj7fF" 377 + "q88f8ArpC7kR1SBTe20Bt1AmpZDT2Dmfmlb/Q1UFjj/F3C77NCNQ344ZcAEI42HY+uighy5GdKQRHMoTT1OzyD" 378 + "G90ABjggQqDGW+zXzyIDAQAB\"," 379 + "\"keyMaterialType\":\"ASYMMETRIC_PUBLIC\"" 380 + "},\"status\":\"ENABLED\",\"keyId\":482168993,\"outputPrefixType\":\"RAW\"}]}"; 381 private static final String JWK_SET_WITH_TWO_KEYS = 382 "{\"keys\":[{" 383 + "\"kty\":\"EC\"," 384 + "\"crv\":\"P-256\"," 385 + "\"x\":\"EM8jrqGMse-PGZQnafIcgEOZ061DiA-y9aBhiBnSDKA\"," 386 + "\"y\":\"UxCtK0wAqQG_e5vpr7SSgJNKt5h4z3FGZtAuBLng1uE\"," 387 + "\"use\":\"sig\",\"alg\":\"ES256\",\"key_ops\":[\"verify\"]}," 388 + "{\"kty\":\"RSA\"," 389 + "\"n\":\"kspk37lGBqXmPPq2CL5KdDeRx7xFiTadpL3jc4nXaqftCtpM6qExfrc2JLaIsnwpwfGMClfe_alIs2" 390 + "GrT9fpM8oDeCccvC39DzZhsSFnAELggi3hnWNKRLfSV0UJzBI-5hZ6ifUsv8W8mSHKlsVMmvOfC2P5-l72qTwN" 391 + "6Le3hy6CxFp5s9pw011B7J3PU65sty6GI9sehB2B_n7nfiWw9YN5--pfwyoitzoMoVKOOpj7fFq88f8ArpC7kR" 392 + "1SBTe20Bt1AmpZDT2Dmfmlb_Q1UFjj_F3C77NCNQ344ZcAEI42HY-uighy5GdKQRHMoTT1OzyDG90ABjggQqDG" 393 + "W-zXzw\"," 394 + "\"e\":\"AQAB\",\"use\":\"sig\",\"alg\":\"RS256\",\"key_ops\":[\"verify\"]}]}"; 395 assertEqualJwkSets(String jwkSet1, String jwkSet2)396 private static void assertEqualJwkSets(String jwkSet1, String jwkSet2) throws Exception { 397 // Consider these strings equal, if their equal after parsing them. 398 // The keys may have any order. 399 JsonObject parsedjwkSet1 = JsonParser.parseString(jwkSet1).getAsJsonObject(); 400 JsonObject parsedjwkSet2 = JsonParser.parseString(jwkSet2).getAsJsonObject(); 401 JsonArray keys1 = parsedjwkSet1.remove("keys").getAsJsonArray(); 402 JsonArray keys2 = parsedjwkSet2.remove("keys").getAsJsonArray(); 403 assertThat(keys1).containsExactlyElementsIn(keys2); 404 assertThat(parsedjwkSet1).isEqualTo(parsedjwkSet2); 405 } 406 407 @Test assertEqualJwkSets_equal()408 public void assertEqualJwkSets_equal() throws Exception { 409 // Whitespace, order of object properties, and order of keys is ignored. 410 assertEqualJwkSets( 411 "{\"keys\":[{\"kty\": \"EC\"}, {\"e\":\"f\",\"kty\": \"RSA\"}]}", 412 "{\"keys\":[{\"kty\":\"RSA\",\"e\":\"f\"}, {\"kty\":\"EC\"}]}"); 413 } 414 415 @Test assertEqualJwkSets_notEequal()416 public void assertEqualJwkSets_notEequal() throws Exception { 417 // Order of arrays (except "keys" array) is not ignored. 418 assertThrows( 419 AssertionError.class, 420 () -> 421 assertEqualJwkSets( 422 "{\"keys\":[{\"kty\":\"EC\",\"key_ops\":[\"b\",\"c\"]}]}", 423 "{\"keys\":[{\"kty\":\"EC\",\"key_ops\":[\"c\",\"b\"]}]}")); 424 } 425 convertToJwkSet(String jsonKeyset)426 private static String convertToJwkSet(String jsonKeyset) throws Exception { 427 KeysetHandle handle = 428 TinkJsonProtoKeysetFormat.parseKeyset(jsonKeyset, InsecureSecretKeyAccess.get()); 429 return JwkSetConverter.fromPublicKeysetHandle(handle); 430 } 431 getCoordinate(JsonObject jwkSet, String coordinate)432 private static byte[] getCoordinate(JsonObject jwkSet, String coordinate) throws Exception { 433 return Base64.urlSafeDecode( 434 jwkSet.get("keys").getAsJsonArray().get(0).getAsJsonObject().get(coordinate).getAsString()); 435 } 436 437 @Test convertEcdsaKeysets_encodesFixedSizeCordinates()438 public void convertEcdsaKeysets_encodesFixedSizeCordinates() throws Exception { 439 JsonObject jwkSet = 440 JsonParser.parseString(convertToJwkSet(P256_PUBLIC_KEYSET_SMALL_COORDINATES)) 441 .getAsJsonObject(); 442 assertThat(getCoordinate(jwkSet, "x")).hasLength(32); 443 assertThat(getCoordinate(jwkSet, "y")).hasLength(32); 444 jwkSet = 445 JsonParser.parseString(convertToJwkSet(P384_PUBLIC_KEYSET_SMALL_COORDINATES)) 446 .getAsJsonObject(); 447 assertThat(getCoordinate(jwkSet, "x")).hasLength(48); 448 assertThat(getCoordinate(jwkSet, "y")).hasLength(48); 449 jwkSet = 450 JsonParser.parseString(convertToJwkSet(P521_PUBLIC_KEYSET_SMALL_COORDINATES)) 451 .getAsJsonObject(); 452 assertThat(getCoordinate(jwkSet, "x")).hasLength(66); 453 assertThat(getCoordinate(jwkSet, "y")).hasLength(66); 454 } 455 456 @Test convertEcdsaKeysets_success()457 public void convertEcdsaKeysets_success() throws Exception { 458 assertEqualJwkSets(convertToJwkSet(ES256_KEYSET), ES256_JWK_SET); 459 assertEqualJwkSets(convertToJwkSet(ES384_KEYSET), ES384_JWK_SET); 460 assertEqualJwkSets(convertToJwkSet(ES512_KEYSET), ES512_JWK_SET); 461 assertEqualJwkSets(convertToJwkSet(ES256_KEYSET_TINK), ES256_JWK_SET_KID); 462 } 463 464 @Test convertRsaSsaPkcs1Keysets_success()465 public void convertRsaSsaPkcs1Keysets_success() throws Exception { 466 assertEqualJwkSets(convertToJwkSet(RS256_KEYSET), RS256_JWK_SET); 467 assertEqualJwkSets(convertToJwkSet(RS384_KEYSET), RS384_JWK_SET); 468 assertEqualJwkSets(convertToJwkSet(RS512_KEYSET), RS512_JWK_SET); 469 assertEqualJwkSets(convertToJwkSet(RS256_KEYSET_TINK), RS256_JWK_SET_KID); 470 } 471 472 @Test convertRsaSsaPssKeysets_success()473 public void convertRsaSsaPssKeysets_success() throws Exception { 474 assertEqualJwkSets(convertToJwkSet(PS256_KEYSET), PS256_JWK_SET); 475 assertEqualJwkSets(convertToJwkSet(PS384_KEYSET), PS384_JWK_SET); 476 assertEqualJwkSets(convertToJwkSet(PS512_KEYSET), PS512_JWK_SET); 477 assertEqualJwkSets(convertToJwkSet(PS256_KEYSET_TINK), PS256_JWK_SET_KID); 478 } 479 480 @Test toPublicKeysetHandlefromPublicKeysetHandle_success()481 public void toPublicKeysetHandlefromPublicKeysetHandle_success() throws Exception { 482 assertEqualJwkSets( 483 JwkSetConverter.fromPublicKeysetHandle(JwkSetConverter.toPublicKeysetHandle(ES256_JWK_SET)), 484 ES256_JWK_SET); 485 assertEqualJwkSets( 486 JwkSetConverter.fromPublicKeysetHandle(JwkSetConverter.toPublicKeysetHandle(ES384_JWK_SET)), 487 ES384_JWK_SET); 488 assertEqualJwkSets( 489 JwkSetConverter.fromPublicKeysetHandle(JwkSetConverter.toPublicKeysetHandle(ES512_JWK_SET)), 490 ES512_JWK_SET); 491 assertEqualJwkSets( 492 JwkSetConverter.fromPublicKeysetHandle(JwkSetConverter.toPublicKeysetHandle(RS256_JWK_SET)), 493 RS256_JWK_SET); 494 assertEqualJwkSets( 495 JwkSetConverter.fromPublicKeysetHandle(JwkSetConverter.toPublicKeysetHandle(RS384_JWK_SET)), 496 RS384_JWK_SET); 497 assertEqualJwkSets( 498 JwkSetConverter.fromPublicKeysetHandle(JwkSetConverter.toPublicKeysetHandle(RS512_JWK_SET)), 499 RS512_JWK_SET); 500 assertEqualJwkSets( 501 JwkSetConverter.fromPublicKeysetHandle(JwkSetConverter.toPublicKeysetHandle(PS256_JWK_SET)), 502 PS256_JWK_SET); 503 assertEqualJwkSets( 504 JwkSetConverter.fromPublicKeysetHandle(JwkSetConverter.toPublicKeysetHandle(PS384_JWK_SET)), 505 PS384_JWK_SET); 506 assertEqualJwkSets( 507 JwkSetConverter.fromPublicKeysetHandle(JwkSetConverter.toPublicKeysetHandle(PS512_JWK_SET)), 508 PS512_JWK_SET); 509 } 510 511 @Test toPublicKeysetHandleWithValidKid_fromPublicKeysetHandle_sameJwkSet()512 public void toPublicKeysetHandleWithValidKid_fromPublicKeysetHandle_sameJwkSet() 513 throws Exception { 514 // When the kid can be decoded into a key ID, the output prefix type of the key will be TINK, 515 // and the same kid value will be generated again when converted to JWK Set. 516 assertEqualJwkSets( 517 JwkSetConverter.fromPublicKeysetHandle( 518 JwkSetConverter.toPublicKeysetHandle(ES256_JWK_SET_KID)), 519 ES256_JWK_SET_KID); 520 assertEqualJwkSets( 521 JwkSetConverter.fromPublicKeysetHandle( 522 JwkSetConverter.toPublicKeysetHandle(RS256_JWK_SET_KID)), 523 RS256_JWK_SET_KID); 524 assertEqualJwkSets( 525 JwkSetConverter.fromPublicKeysetHandle( 526 JwkSetConverter.toPublicKeysetHandle(PS256_JWK_SET_KID)), 527 PS256_JWK_SET_KID); 528 } 529 530 @Test jwkEs256WithKid_isImportedAsRaw()531 public void jwkEs256WithKid_isImportedAsRaw() throws Exception { 532 KeysetHandle converted = JwkSetConverter.toPublicKeysetHandle(ES256_JWK_SET_KID); 533 KeysetHandle expected = 534 TinkJsonProtoKeysetFormat.parseKeyset( 535 ES256_JWK_SET_KID_TINK, InsecureSecretKeyAccess.get()); 536 // The KeyID is picked at random, hence we just compare the keys. 537 assertTrue(converted.getAt(0).getKey().equalsKey(expected.getAt(0).getKey())); 538 } 539 540 @Test jwkRs256WithKid_isImportedAsRaw()541 public void jwkRs256WithKid_isImportedAsRaw() throws Exception { 542 KeysetHandle converted = JwkSetConverter.toPublicKeysetHandle(RS256_JWK_SET_KID); 543 KeysetHandle expected = 544 TinkJsonProtoKeysetFormat.parseKeyset( 545 RS256_JWK_SET_KID_TINK, InsecureSecretKeyAccess.get()); 546 // The KeyID is picked at random, hence we just compare the keys. 547 assertTrue(converted.getAt(0).getKey().equalsKey(expected.getAt(0).getKey())); 548 } 549 550 @Test jwkPs256WithKid_isImportedAsRaw()551 public void jwkPs256WithKid_isImportedAsRaw() throws Exception { 552 KeysetHandle converted = JwkSetConverter.toPublicKeysetHandle(PS256_JWK_SET_KID); 553 KeysetHandle expected = 554 TinkJsonProtoKeysetFormat.parseKeyset( 555 PS256_JWK_SET_KID_TINK, InsecureSecretKeyAccess.get()); 556 // The KeyID is picked at random, hence we just compare the keys. 557 assertTrue(converted.getAt(0).getKey().equalsKey(expected.getAt(0).getKey())); 558 } 559 560 @Test jwkWithEmptyKid_kidIsPreserved()561 public void jwkWithEmptyKid_kidIsPreserved() throws Exception { 562 String esWithEmptyKid = ES256_JWK_SET_KID.replace("\"ENgjPA\"", "\"\""); 563 assertEqualJwkSets( 564 JwkSetConverter.fromPublicKeysetHandle( 565 JwkSetConverter.toPublicKeysetHandle(esWithEmptyKid)), 566 esWithEmptyKid); 567 String rsWithEmptyKid = RS256_JWK_SET_KID.replace("\"HL1QoQ\"", "\"\""); 568 assertEqualJwkSets( 569 JwkSetConverter.fromPublicKeysetHandle( 570 JwkSetConverter.toPublicKeysetHandle(rsWithEmptyKid)), 571 rsWithEmptyKid); 572 String psWithEmptyKid = PS256_JWK_SET_KID.replace("\"Wes4wg\"", "\"\""); 573 assertEqualJwkSets( 574 JwkSetConverter.fromPublicKeysetHandle( 575 JwkSetConverter.toPublicKeysetHandle(psWithEmptyKid)), 576 psWithEmptyKid); 577 } 578 579 @Test toPublicKeysetHandleSetsKeyIdsAndPrimaryKeyId()580 public void toPublicKeysetHandleSetsKeyIdsAndPrimaryKeyId() throws Exception { 581 KeysetHandle handle = JwkSetConverter.toPublicKeysetHandle(JWK_SET_WITH_TWO_KEYS); 582 assertThat(handle.size()).isEqualTo(2); 583 assertThat(handle.getAt(0).getKey()).isInstanceOf(JwtEcdsaPublicKey.class); 584 assertThat(handle.getAt(1).getKey()).isInstanceOf(JwtRsaSsaPkcs1PublicKey.class); 585 } 586 587 @DataPoints("templatesNames") 588 public static final String[] TEMPLATE_NAMES = 589 new String[] { 590 "JWT_ES256", 591 "JWT_ES384", 592 "JWT_ES512", 593 "JWT_ES256_RAW", 594 "JWT_RS256_2048_F4", 595 "JWT_RS256_3072_F4", 596 "JWT_RS384_3072_F4", 597 "JWT_RS512_4096_F4", 598 "JWT_RS256_2048_F4_RAW", 599 "JWT_PS256_2048_F4", 600 "JWT_PS256_3072_F4", 601 "JWT_PS384_3072_F4", 602 "JWT_PS512_4096_F4", 603 "JWT_PS256_2048_F4_RAW", 604 }; 605 606 @Theory convertTinkToJwksTokenVerification_success( @romDataPoints"templatesNames") String templateName)607 public void convertTinkToJwksTokenVerification_success( 608 @FromDataPoints("templatesNames") String templateName) throws Exception { 609 if (TestUtil.isTsan()) { 610 // KeysetHandle.generateNew is too slow in Tsan. 611 return; 612 } 613 KeysetHandle keysetHandle = KeysetHandle.generateNew(KeyTemplates.get(templateName)); 614 615 String jwksString = 616 JwkSetConverter.fromPublicKeysetHandle(keysetHandle.getPublicKeysetHandle()); 617 618 KeysetHandle publicKeysetHandle = JwkSetConverter.toPublicKeysetHandle(jwksString); 619 620 JwtPublicKeySign signer = 621 keysetHandle.getPrimitive(RegistryConfiguration.get(), JwtPublicKeySign.class); 622 JwtPublicKeyVerify verifier = 623 publicKeysetHandle.getPrimitive(RegistryConfiguration.get(), JwtPublicKeyVerify.class); 624 625 RawJwt rawToken = RawJwt.newBuilder().setJwtId("jwtId").withoutExpiration().build(); 626 String signedCompact = signer.signAndEncode(rawToken); 627 JwtValidator validator = JwtValidator.newBuilder().allowMissingExpiration().build(); 628 VerifiedJwt verifiedToken = verifier.verifyAndDecode(signedCompact, validator); 629 assertThat(verifiedToken.getJwtId()).isEqualTo("jwtId"); 630 } 631 632 @Test keysetWithTwoKeys_fromPublicKeysetHandleSuccess()633 public void keysetWithTwoKeys_fromPublicKeysetHandleSuccess() throws Exception { 634 assertEqualJwkSets(convertToJwkSet(KEYSET_WITH_TWO_KEYS), JWK_SET_WITH_TWO_KEYS); 635 } 636 637 @Test primaryKeyIdMissing_fromPublicKeysetHandleSuccess()638 public void primaryKeyIdMissing_fromPublicKeysetHandleSuccess() throws Exception { 639 String keyset = ES256_KEYSET.replace("\"primaryKeyId\":282600252,", ""); 640 assertThrows(GeneralSecurityException.class, () -> convertToJwkSet(keyset)); 641 } 642 643 @Test legacyEcdsaKeysets_fromPublicKeysetHandleFails()644 public void legacyEcdsaKeysets_fromPublicKeysetHandleFails() throws Exception { 645 String keyset = ES256_KEYSET.replace("RAW", "LEGACY"); 646 assertThrows(GeneralSecurityException.class, () -> convertToJwkSet(keyset)); 647 } 648 649 @Test crunchyEcdsaKeysets_fromPublicKeysetHandleFails()650 public void crunchyEcdsaKeysets_fromPublicKeysetHandleFails() throws Exception { 651 String keyset = ES256_KEYSET.replace("RAW", "CRUNCHY"); 652 assertThrows(GeneralSecurityException.class, () -> convertToJwkSet(keyset)); 653 } 654 655 @Test privateKey_fromPublicKeysetHandleFails()656 public void privateKey_fromPublicKeysetHandleFails() throws Exception { 657 assertThrows(GeneralSecurityException.class, () -> convertToJwkSet(PRIVATEKEY_KEYSET)); 658 } 659 660 @Test legacyRsaSsaPkcs1Keysets_fromPublicKeysetHandleFails()661 public void legacyRsaSsaPkcs1Keysets_fromPublicKeysetHandleFails() throws Exception { 662 String keyset = RS256_KEYSET.replace("RAW", "LEGACY"); 663 assertThrows(GeneralSecurityException.class, () -> convertToJwkSet(keyset)); 664 } 665 666 @Test crunchyRsaSsaPkcs1Keysets_fromPublicKeysetHandleFails()667 public void crunchyRsaSsaPkcs1Keysets_fromPublicKeysetHandleFails() throws Exception { 668 String keyset = RS256_KEYSET.replace("RAW", "CRUNCHY"); 669 assertThrows(GeneralSecurityException.class, () -> convertToJwkSet(keyset)); 670 } 671 672 @Test legacyRsaSsaPssKeysets_fromPublicKeysetHandleFails()673 public void legacyRsaSsaPssKeysets_fromPublicKeysetHandleFails() throws Exception { 674 String keyset = PS256_KEYSET.replace("RAW", "LEGACY"); 675 assertThrows(GeneralSecurityException.class, () -> convertToJwkSet(keyset)); 676 } 677 678 @Test crunchyRsaSsaPssKeysets_fromPublicKeysetHandleFails()679 public void crunchyRsaSsaPssKeysets_fromPublicKeysetHandleFails() throws Exception { 680 String keyset = PS256_KEYSET.replace("RAW", "CRUNCHY"); 681 assertThrows(GeneralSecurityException.class, () -> convertToJwkSet(keyset)); 682 } 683 684 @Test fromPublicKeysetHandle_throwsOnInvalidKeysetHandle()685 public void fromPublicKeysetHandle_throwsOnInvalidKeysetHandle() throws Exception { 686 Keyset keyset = 687 Keyset.newBuilder() 688 .setPrimaryKeyId(1) 689 .addKey( 690 Keyset.Key.newBuilder() 691 .setKeyId(1) 692 // Keysets with unknown status are not parsed properly and will throw unchecked 693 // at getAt() 694 .setStatus(KeyStatusType.UNKNOWN_STATUS) 695 .setKeyData( 696 KeyData.newBuilder() 697 .setTypeUrl("somenonexistenttypeurl") 698 .setKeyMaterialType(KeyMaterialType.ASYMMETRIC_PUBLIC) 699 .setValue(ByteString.EMPTY))) 700 .build(); 701 KeysetHandle handle = TinkProtoKeysetFormat.parseKeysetWithoutSecret(keyset.toByteArray()); 702 assertThrows( 703 GeneralSecurityException.class, () -> JwkSetConverter.fromPublicKeysetHandle(handle)); 704 } 705 706 @Test ecdsaWithoutUseAndKeyOps_toPublicKeysetHandleSuccess()707 public void ecdsaWithoutUseAndKeyOps_toPublicKeysetHandleSuccess() throws Exception { 708 String jwksString = 709 "{" 710 + "\"keys\":[{" 711 + "\"kty\":\"EC\"," 712 + "\"crv\":\"P-256\"," 713 + "\"x\":\"KUPydf4k4cS5EGS82npjEUxKIiBfUGP3wlN49A2GxTY\"," 714 + "\"y\":\"b22m_Y4sT-jUJSxBVqjrW_DxWyBLopxYHTuFVfx70ZI\"," 715 + "\"alg\":\"ES256\"" 716 + "}]}"; 717 // ignore returned value, we only test that it worked. 718 Object unused = JwkSetConverter.toPublicKeysetHandle(jwksString); 719 } 720 721 @Test ecdsaPrivateKey_fails()722 public void ecdsaPrivateKey_fails() throws Exception { 723 // Example from https://datatracker.ietf.org/doc/html/rfc7517#appendix-A.2 724 String jwksString = 725 "{" 726 + "\"keys\":[{" 727 + "\"kty\":\"EC\"," 728 + "\"crv\":\"P-256\"," 729 + "\"x\":\"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4\"," 730 + "\"y\":\"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM\"," 731 + "\"d\":\"870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE\"," 732 + "\"alg\":\"ES256\"" 733 + "}]}"; 734 assertThrows( 735 UnsupportedOperationException.class, 736 () -> JwkSetConverter.toPublicKeysetHandle(jwksString)); 737 } 738 739 @Test ecdsaWithUnknownField_toPublicKeysetHandleSuccess()740 public void ecdsaWithUnknownField_toPublicKeysetHandleSuccess() throws Exception { 741 String jwksString = 742 "{" 743 + "\"keys\":[{" 744 + "\"kty\":\"EC\"," 745 + "\"crv\":\"P-256\"," 746 + "\"x\":\"KUPydf4k4cS5EGS82npjEUxKIiBfUGP3wlN49A2GxTY\"," 747 + "\"y\":\"b22m_Y4sT-jUJSxBVqjrW_DxWyBLopxYHTuFVfx70ZI\"," 748 + "\"alg\":\"ES256\"," 749 + "\"unknown\":1234," 750 + "\"use\":\"sig\"," 751 + "\"key_ops\":[\"verify\"]" 752 + "}]}"; 753 // ignore returned value, we only test that it worked. 754 Object unused = JwkSetConverter.toPublicKeysetHandle(jwksString); 755 } 756 757 @Test ecdsaWithoutAlg_toPublicKeysetHandleFails()758 public void ecdsaWithoutAlg_toPublicKeysetHandleFails() throws Exception { 759 String jwksString = 760 "{" 761 + "\"keys\":[{" 762 + "\"kty\":\"EC\"," 763 + "\"crv\":\"P-256\"," 764 + "\"x\":\"KUPydf4k4cS5EGS82npjEUxKIiBfUGP3wlN49A2GxTY\"," 765 + "\"y\":\"b22m_Y4sT-jUJSxBVqjrW_DxWyBLopxYHTuFVfx70ZI\"," 766 + "\"use\":\"sig\"," 767 + "\"key_ops\":[\"verify\"]" 768 + "}]}"; 769 assertThrows( 770 GeneralSecurityException.class, () -> JwkSetConverter.toPublicKeysetHandle(jwksString)); 771 } 772 773 @Test ecdsaWithoutKty_toPublicKeysetHandleFails()774 public void ecdsaWithoutKty_toPublicKeysetHandleFails() throws Exception { 775 String jwksString = 776 "{" 777 + "\"keys\":[{" 778 + "\"crv\":\"P-256\"," 779 + "\"x\":\"KUPydf4k4cS5EGS82npjEUxKIiBfUGP3wlN49A2GxTY\"," 780 + "\"y\":\"b22m_Y4sT-jUJSxBVqjrW_DxWyBLopxYHTuFVfx70ZI\"," 781 + "\"use\":\"sig\"," 782 + "\"alg\":\"ES256\"," 783 + "\"key_ops\":[\"verify\"]" 784 + "}]}"; 785 assertThrows( 786 GeneralSecurityException.class, () -> JwkSetConverter.toPublicKeysetHandle(jwksString)); 787 } 788 789 @Test ecdsaWithoutCrv_toPublicKeysetHandleFails()790 public void ecdsaWithoutCrv_toPublicKeysetHandleFails() throws Exception { 791 String jwksString = 792 "{" 793 + "\"keys\":[{" 794 + "\"kty\":\"EC\"," 795 + "\"x\":\"KUPydf4k4cS5EGS82npjEUxKIiBfUGP3wlN49A2GxTY\"," 796 + "\"y\":\"b22m_Y4sT-jUJSxBVqjrW_DxWyBLopxYHTuFVfx70ZI\"," 797 + "\"use\":\"sig\"," 798 + "\"alg\":\"ES256\"," 799 + "\"key_ops\":[\"verify\"]" 800 + "}]}"; 801 assertThrows( 802 GeneralSecurityException.class, () -> JwkSetConverter.toPublicKeysetHandle(jwksString)); 803 } 804 805 @Test ecdsa_pointNotOnCurve_getPrimitiveFails()806 public void ecdsa_pointNotOnCurve_getPrimitiveFails() throws Exception { 807 String jwksString = 808 "{" 809 + "\"keys\":[{" 810 + "\"kty\":\"EC\"," 811 + "\"crv\":\"P-256\"," 812 + "\"x\":\"KUPydf4k4cS5EGS82npjEUxKIiBfUGP3wlN49A2GxTY\"," 813 + "\"y\":\"AAAwOQ\"," 814 + "\"use\":\"sig\"," 815 + "\"alg\":\"ES256\"," 816 + "\"key_ops\":[\"verify\"]" 817 + "}]}"; 818 assertThrows( 819 GeneralSecurityException.class, () -> JwkSetConverter.toPublicKeysetHandle(jwksString)); 820 } 821 822 @Test ecdsaWithInvalidKty_toPublicKeysetHandleFails()823 public void ecdsaWithInvalidKty_toPublicKeysetHandleFails() throws Exception { 824 String jwksString = 825 "{" 826 + "\"keys\":[{" 827 + "\"kty\":\"RSA\"," 828 + "\"crv\":\"P-256\"," 829 + "\"x\":\"KUPydf4k4cS5EGS82npjEUxKIiBfUGP3wlN49A2GxTY\"," 830 + "\"y\":\"b22m_Y4sT-jUJSxBVqjrW_DxWyBLopxYHTuFVfx70ZI\"," 831 + "\"use\":\"sig\"," 832 + "\"alg\":\"ES256\"," 833 + "\"key_ops\":[\"verify\"]" 834 + "}]}"; 835 assertThrows( 836 GeneralSecurityException.class, () -> JwkSetConverter.toPublicKeysetHandle(jwksString)); 837 } 838 839 @Test ecdsaWithInvalidCrv_toPublicKeysetHandleFails()840 public void ecdsaWithInvalidCrv_toPublicKeysetHandleFails() throws Exception { 841 String jwksString = 842 "{" 843 + "\"keys\":[{" 844 + "\"kty\":\"EC\"," 845 + "\"crv\":\"P-384\"," 846 + "\"x\":\"KUPydf4k4cS5EGS82npjEUxKIiBfUGP3wlN49A2GxTY\"," 847 + "\"y\":\"b22m_Y4sT-jUJSxBVqjrW_DxWyBLopxYHTuFVfx70ZI\"," 848 + "\"use\":\"sig\"," 849 + "\"alg\":\"ES256\"," 850 + "\"key_ops\":[\"verify\"]" 851 + "}]}"; 852 assertThrows( 853 GeneralSecurityException.class, () -> JwkSetConverter.toPublicKeysetHandle(jwksString)); 854 } 855 856 @Test ecdsaWithInvalidUse_toPublicKeysetHandleFails()857 public void ecdsaWithInvalidUse_toPublicKeysetHandleFails() throws Exception { 858 String jwksString = 859 "{" 860 + "\"keys\":[{" 861 + "\"kty\":\"EC\"," 862 + "\"crv\":\"P-256\"," 863 + "\"x\":\"KUPydf4k4cS5EGS82npjEUxKIiBfUGP3wlN49A2GxTY\"," 864 + "\"y\":\"b22m_Y4sT-jUJSxBVqjrW_DxWyBLopxYHTuFVfx70ZI\"," 865 + "\"use\":\"invalid\"," 866 + "\"alg\":\"ES256\"," 867 + "\"key_ops\":[\"verify\"]" 868 + "}]}"; 869 assertThrows( 870 GeneralSecurityException.class, () -> JwkSetConverter.toPublicKeysetHandle(jwksString)); 871 } 872 873 @Test ecdsaWithInvalidKeyOps_toPublicKeysetHandleFails()874 public void ecdsaWithInvalidKeyOps_toPublicKeysetHandleFails() throws Exception { 875 String jwksString = 876 "{" 877 + "\"keys\":[{" 878 + "\"kty\":\"EC\"," 879 + "\"crv\":\"P-256\"," 880 + "\"x\":\"KUPydf4k4cS5EGS82npjEUxKIiBfUGP3wlN49A2GxTY\"," 881 + "\"y\":\"b22m_Y4sT-jUJSxBVqjrW_DxWyBLopxYHTuFVfx70ZI\"," 882 + "\"use\":\"sig\"," 883 + "\"alg\":\"ES256\"," 884 + "\"key_ops\":[\"invalid\"]" 885 + "}]}"; 886 assertThrows( 887 GeneralSecurityException.class, () -> JwkSetConverter.toPublicKeysetHandle(jwksString)); 888 } 889 890 @Test ecdsaWithStringKeyOps_toPublicKeysetHandleFails()891 public void ecdsaWithStringKeyOps_toPublicKeysetHandleFails() throws Exception { 892 String jwksString = 893 "{" 894 + "\"keys\":[{" 895 + "\"kty\":\"EC\"," 896 + "\"crv\":\"P-256\"," 897 + "\"x\":\"KUPydf4k4cS5EGS82npjEUxKIiBfUGP3wlN49A2GxTY\"," 898 + "\"y\":\"b22m_Y4sT-jUJSxBVqjrW_DxWyBLopxYHTuFVfx70ZI\"," 899 + "\"use\":\"sig\"," 900 + "\"alg\":\"ES256\"," 901 + "\"key_ops\":\"verify\"" 902 + "}]}"; 903 assertThrows( 904 GeneralSecurityException.class, () -> JwkSetConverter.toPublicKeysetHandle(jwksString)); 905 } 906 907 @Test rsaWithoutUseAndKeyOps_toPublicKeysetHandleSuccess()908 public void rsaWithoutUseAndKeyOps_toPublicKeysetHandleSuccess() throws Exception { 909 String jwksString = 910 "{\"keys\":[{\"kty\":\"RSA\"," 911 + "\"n\":\"AM90NXQrAtt6KPSevzv9nbLJ2g_WPDH4zTwOo1slR8qC2chi6mH4TONOyAracdhQaoPwtMKge2ks" 912 + "dJi1GaYwl975uvZEd9J1G078tlGrKPpy5I_OHseYDoeP8EgXawNII5ayFo-Ch_ZTxyzOuWmeb3DJft177D7T" 913 + "Foz-zrMoTDGV4gwhBPeVfSk5DYvY06hF740KZq89nXBX_51KE5C-M9hBJMK9VA7BiGM8qjeu7l7ppXdzfvf6" 914 + "azfkIogKMV7Xk0aw6nCW6h49BYuIu3TVjiToLEu5kX0z501whcCI8SA1tlicl7CzOCvVF70vg03RAB5vZQWY" 915 + "2oFr3AwKBYDHvsc\"," 916 + "\"e\":\"AQAB\",\"alg\":\"RS256\"}]}"; 917 // ignore returned value, we only test that it worked. 918 Object unused = JwkSetConverter.toPublicKeysetHandle(jwksString); 919 920 String psJwksString = jwksString.replace("RS256", "PS256"); 921 // ignore returned value, we only test that it worked. 922 unused = JwkSetConverter.toPublicKeysetHandle(psJwksString); 923 } 924 925 @Test rsaWithUnknownField_toPublicKeysetHandleSuccess()926 public void rsaWithUnknownField_toPublicKeysetHandleSuccess() throws Exception { 927 String jwksString = 928 "{\"keys\":[{\"kty\":\"RSA\"," 929 + "\"n\":\"AM90NXQrAtt6KPSevzv9nbLJ2g_WPDH4zTwOo1slR8qC2chi6mH4TONOyAracdhQaoPwtMKge2ks" 930 + "dJi1GaYwl975uvZEd9J1G078tlGrKPpy5I_OHseYDoeP8EgXawNII5ayFo-Ch_ZTxyzOuWmeb3DJft177D7T" 931 + "Foz-zrMoTDGV4gwhBPeVfSk5DYvY06hF740KZq89nXBX_51KE5C-M9hBJMK9VA7BiGM8qjeu7l7ppXdzfvf6" 932 + "azfkIogKMV7Xk0aw6nCW6h49BYuIu3TVjiToLEu5kX0z501whcCI8SA1tlicl7CzOCvVF70vg03RAB5vZQWY" 933 + "2oFr3AwKBYDHvsc\"," 934 + "\"unknown\":1234," 935 + "\"e\":\"AQAB\",\"use\":\"sig\",\"alg\":\"RS256\",\"key_ops\":[\"verify\"]}]}"; 936 // ignore returned value, we only test that it worked. 937 Object unused = JwkSetConverter.toPublicKeysetHandle(jwksString); 938 939 String psJwksString = jwksString.replace("RS256", "PS256"); 940 // ignore returned value, we only test that it worked. 941 unused = JwkSetConverter.toPublicKeysetHandle(psJwksString); 942 } 943 944 @Test rsaPrivateKey_fails()945 public void rsaPrivateKey_fails() throws Exception { 946 // Example from https://datatracker.ietf.org/doc/html/rfc7517#appendix-A.2 947 String jwksString = 948 "{\"keys\":[" 949 + "{\"kty\":\"RSA\"," 950 + "\"n\":\"0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4" 951 + "cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMst" 952 + "n64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2Q" 953 + "vzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbIS" 954 + "D08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw" 955 + "0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw\"," 956 + "\"e\":\"AQAB\"," 957 + "\"d\":\"X4cTteJY_gn4FYPsXB8rdXix5vwsg1FLN5E3EaG6RJoVH-HLLKD9" 958 + "M7dx5oo7GURknchnrRweUkC7hT5fJLM0WbFAKNLWY2vv7B6NqXSzUvxT0_YSfqij" 959 + "wp3RTzlBaCxWp4doFk5N2o8Gy_nHNKroADIkJ46pRUohsXywbReAdYaMwFs9tv8d" 960 + "_cPVY3i07a3t8MN6TNwm0dSawm9v47UiCl3Sk5ZiG7xojPLu4sbg1U2jx4IBTNBz" 961 + "nbJSzFHK66jT8bgkuqsk0GjskDJk19Z4qwjwbsnn4j2WBii3RL-Us2lGVkY8fkFz" 962 + "me1z0HbIkfz0Y6mqnOYtqc0X4jfcKoAC8Q\"," 963 + "\"p\":\"83i-7IvMGXoMXCskv73TKr8637FiO7Z27zv8oj6pbWUQyLPQBQxtPV" 964 + "nwD20R-60eTDmD2ujnMt5PoqMrm8RfmNhVWDtjjMmCMjOpSXicFHj7XOuVIYQyqV" 965 + "WlWEh6dN36GVZYk93N8Bc9vY41xy8B9RzzOGVQzXvNEvn7O0nVbfs\"," 966 + "\"q\":\"3dfOR9cuYq-0S-mkFLzgItgMEfFzB2q3hWehMuG0oCuqnb3vobLyum" 967 + "qjVZQO1dIrdwgTnCdpYzBcOfW5r370AFXjiWft_NGEiovonizhKpo9VVS78TzFgx" 968 + "kIdrecRezsZ-1kYd_s1qDbxtkDEgfAITAG9LUnADun4vIcb6yelxk\"," 969 + "\"dp\":\"G4sPXkc6Ya9y8oJW9_ILj4xuppu0lzi_H7VTkS8xj5SdX3coE0oim" 970 + "YwxIi2emTAue0UOa5dpgFGyBJ4c8tQ2VF402XRugKDTP8akYhFo5tAA77Qe_Nmtu" 971 + "YZc3C3m3I24G2GvR5sSDxUyAN2zq8Lfn9EUms6rY3Ob8YeiKkTiBj0\"," 972 + "\"dq\":\"s9lAH9fggBsoFR8Oac2R_E2gw282rT2kGOAhvIllETE1efrA6huUU" 973 + "vMfBcMpn8lqeW6vzznYY5SSQF7pMdC_agI3nG8Ibp1BUb0JUiraRNqUfLhcQb_d9" 974 + "GF4Dh7e74WbRsobRonujTYN1xCaP6TO61jvWrX-L18txXw494Q_cgk\"," 975 + "\"qi\":\"GyM_p6JrXySiz1toFgKbWV-JdI3jQ4ypu9rbMWx3rQJBfmt0FoYzg" 976 + "UIZEVFEcOqwemRN81zoDAaa-Bk0KWNGDjJHZDdDmFhW3AN7lI-puxk_mHZGJ11rx" 977 + "yR8O55XLSe3SPmRfKwZI6yU24ZxvQKFYItdldUKGzO6Ia6zTKhAVRU\"," 978 + "\"alg\":\"RS256\"," 979 + "\"kid\":\"2011-04-29\"}]}"; 980 assertThrows( 981 UnsupportedOperationException.class, 982 () -> JwkSetConverter.toPublicKeysetHandle(jwksString)); 983 984 String psJwksString = jwksString.replace("RS256", "PS256"); 985 assertThrows( 986 UnsupportedOperationException.class, 987 () -> JwkSetConverter.toPublicKeysetHandle(psJwksString)); 988 } 989 990 @Test rsaWithoutAlg_toPublicKeysetHandleFails()991 public void rsaWithoutAlg_toPublicKeysetHandleFails() throws Exception { 992 String jwksString = 993 "{\"keys\":[{\"kty\":\"RSA\"," 994 + "\"n\":\"AM90NXQrAtt6KPSevzv9nbLJ2g_WPDH4zTwOo1slR8qC2chi6mH4TONOyAracdhQaoPwtMKge2ks" 995 + "dJi1GaYwl975uvZEd9J1G078tlGrKPpy5I_OHseYDoeP8EgXawNII5ayFo-Ch_ZTxyzOuWmeb3DJft177D7T" 996 + "Foz-zrMoTDGV4gwhBPeVfSk5DYvY06hF740KZq89nXBX_51KE5C-M9hBJMK9VA7BiGM8qjeu7l7ppXdzfvf6" 997 + "azfkIogKMV7Xk0aw6nCW6h49BYuIu3TVjiToLEu5kX0z501whcCI8SA1tlicl7CzOCvVF70vg03RAB5vZQWY" 998 + "2oFr3AwKBYDHvsc\"," 999 + "\"e\":\"AQAB\",\"use\":\"sig\",\"key_ops\":[\"verify\"]}]}"; 1000 assertThrows( 1001 GeneralSecurityException.class, () -> JwkSetConverter.toPublicKeysetHandle(jwksString)); 1002 } 1003 1004 @Test rsaWithoutKty_toPublicKeysetHandleFails()1005 public void rsaWithoutKty_toPublicKeysetHandleFails() throws Exception { 1006 String jwksString = 1007 "{\"keys\":[{" 1008 + "\"n\":\"AM90NXQrAtt6KPSevzv9nbLJ2g_WPDH4zTwOo1slR8qC2chi6mH4TONOyAracdhQaoPwtMKge2ks" 1009 + "dJi1GaYwl975uvZEd9J1G078tlGrKPpy5I_OHseYDoeP8EgXawNII5ayFo-Ch_ZTxyzOuWmeb3DJft177D7T" 1010 + "Foz-zrMoTDGV4gwhBPeVfSk5DYvY06hF740KZq89nXBX_51KE5C-M9hBJMK9VA7BiGM8qjeu7l7ppXdzfvf6" 1011 + "azfkIogKMV7Xk0aw6nCW6h49BYuIu3TVjiToLEu5kX0z501whcCI8SA1tlicl7CzOCvVF70vg03RAB5vZQWY" 1012 + "2oFr3AwKBYDHvsc\"," 1013 + "\"e\":\"AQAB\",\"use\":\"sig\",\"alg\":\"RS256\",\"key_ops\":[\"verify\"]}]}"; 1014 assertThrows( 1015 GeneralSecurityException.class, () -> JwkSetConverter.toPublicKeysetHandle(jwksString)); 1016 1017 String psJwksString = jwksString.replace("RS256", "PS256"); 1018 assertThrows( 1019 GeneralSecurityException.class, () -> JwkSetConverter.toPublicKeysetHandle(psJwksString)); 1020 } 1021 1022 @Test rsaWithSmallN_getPrimitiveFails()1023 public void rsaWithSmallN_getPrimitiveFails() throws Exception { 1024 String jwksString = 1025 "{\"keys\":[{\"kty\":\"RSA\"," 1026 + "\"n\":\"AAAwOQ\"," 1027 + "\"e\":\"AQAB\",\"use\":\"sig\",\"alg\":\"RS256\",\"key_ops\":[\"verify\"]}]}"; 1028 assertThrows( 1029 GeneralSecurityException.class, () -> JwkSetConverter.toPublicKeysetHandle(jwksString)); 1030 1031 String psJwksString = jwksString.replace("RS256", "PS256"); 1032 assertThrows( 1033 GeneralSecurityException.class, () -> JwkSetConverter.toPublicKeysetHandle(psJwksString)); 1034 } 1035 1036 @Test rsaWithInvalidKty_toPublicKeysetHandleFails()1037 public void rsaWithInvalidKty_toPublicKeysetHandleFails() throws Exception { 1038 String jwksString = 1039 "{\"keys\":[{\"kty\":\"EC\"," 1040 + "\"n\":\"AM90NXQrAtt6KPSevzv9nbLJ2g_WPDH4zTwOo1slR8qC2chi6mH4TONOyAracdhQaoPwtMKge2ks" 1041 + "dJi1GaYwl975uvZEd9J1G078tlGrKPpy5I_OHseYDoeP8EgXawNII5ayFo-Ch_ZTxyzOuWmeb3DJft177D7T" 1042 + "Foz-zrMoTDGV4gwhBPeVfSk5DYvY06hF740KZq89nXBX_51KE5C-M9hBJMK9VA7BiGM8qjeu7l7ppXdzfvf6" 1043 + "azfkIogKMV7Xk0aw6nCW6h49BYuIu3TVjiToLEu5kX0z501whcCI8SA1tlicl7CzOCvVF70vg03RAB5vZQWY" 1044 + "2oFr3AwKBYDHvsc\"," 1045 + "\"e\":\"AQAB\",\"use\":\"sig\",\"alg\":\"RS256\",\"key_ops\":[\"verify\"]}]}"; 1046 assertThrows( 1047 GeneralSecurityException.class, () -> JwkSetConverter.toPublicKeysetHandle(jwksString)); 1048 1049 String psJwksString = jwksString.replace("RS256", "PS256"); 1050 assertThrows( 1051 GeneralSecurityException.class, () -> JwkSetConverter.toPublicKeysetHandle(psJwksString)); 1052 } 1053 1054 @Test rsaWithInvalidUse_toPublicKeysetHandleFails()1055 public void rsaWithInvalidUse_toPublicKeysetHandleFails() throws Exception { 1056 String jwksString = 1057 "{\"keys\":[{\"kty\":\"RSA\"," 1058 + "\"n\":\"AM90NXQrAtt6KPSevzv9nbLJ2g_WPDH4zTwOo1slR8qC2chi6mH4TONOyAracdhQaoPwtMKge2ks" 1059 + "dJi1GaYwl975uvZEd9J1G078tlGrKPpy5I_OHseYDoeP8EgXawNII5ayFo-Ch_ZTxyzOuWmeb3DJft177D7T" 1060 + "Foz-zrMoTDGV4gwhBPeVfSk5DYvY06hF740KZq89nXBX_51KE5C-M9hBJMK9VA7BiGM8qjeu7l7ppXdzfvf6" 1061 + "azfkIogKMV7Xk0aw6nCW6h49BYuIu3TVjiToLEu5kX0z501whcCI8SA1tlicl7CzOCvVF70vg03RAB5vZQWY" 1062 + "2oFr3AwKBYDHvsc\"," 1063 + "\"e\":\"AQAB\",\"use\":\"invalid\",\"alg\":\"RS256\",\"key_ops\":[\"verify\"]}]}"; 1064 assertThrows( 1065 GeneralSecurityException.class, () -> JwkSetConverter.toPublicKeysetHandle(jwksString)); 1066 1067 String psJwksString = jwksString.replace("RS256", "PS256"); 1068 assertThrows( 1069 GeneralSecurityException.class, () -> JwkSetConverter.toPublicKeysetHandle(psJwksString)); 1070 } 1071 1072 @Test rsaWithInvalidKeyOps_toPublicKeysetHandleFails()1073 public void rsaWithInvalidKeyOps_toPublicKeysetHandleFails() throws Exception { 1074 String jwksString = 1075 "{\"keys\":[{\"kty\":\"RSA\"," 1076 + "\"n\":\"AM90NXQrAtt6KPSevzv9nbLJ2g_WPDH4zTwOo1slR8qC2chi6mH4TONOyAracdhQaoPwtMKge2ks" 1077 + "dJi1GaYwl975uvZEd9J1G078tlGrKPpy5I_OHseYDoeP8EgXawNII5ayFo-Ch_ZTxyzOuWmeb3DJft177D7T" 1078 + "Foz-zrMoTDGV4gwhBPeVfSk5DYvY06hF740KZq89nXBX_51KE5C-M9hBJMK9VA7BiGM8qjeu7l7ppXdzfvf6" 1079 + "azfkIogKMV7Xk0aw6nCW6h49BYuIu3TVjiToLEu5kX0z501whcCI8SA1tlicl7CzOCvVF70vg03RAB5vZQWY" 1080 + "2oFr3AwKBYDHvsc\"," 1081 + "\"e\":\"AQAB\",\"use\":\"sig\",\"alg\":\"RS256\",\"key_ops\":[\"invalid\"]}]}"; 1082 assertThrows( 1083 GeneralSecurityException.class, () -> JwkSetConverter.toPublicKeysetHandle(jwksString)); 1084 1085 String psJwksString = jwksString.replace("RS256", "PS256"); 1086 assertThrows( 1087 GeneralSecurityException.class, () -> JwkSetConverter.toPublicKeysetHandle(psJwksString)); 1088 } 1089 1090 @Test rsaWithStringKeyOps_toPublicKeysetHandleFails()1091 public void rsaWithStringKeyOps_toPublicKeysetHandleFails() throws Exception { 1092 String jwksString = 1093 "{\"keys\":[{\"kty\":\"RSA\"," 1094 + "\"n\":\"AM90NXQrAtt6KPSevzv9nbLJ2g_WPDH4zTwOo1slR8qC2chi6mH4TONOyAracdhQaoPwtMKge2ks" 1095 + "dJi1GaYwl975uvZEd9J1G078tlGrKPpy5I_OHseYDoeP8EgXawNII5ayFo-Ch_ZTxyzOuWmeb3DJft177D7T" 1096 + "Foz-zrMoTDGV4gwhBPeVfSk5DYvY06hF740KZq89nXBX_51KE5C-M9hBJMK9VA7BiGM8qjeu7l7ppXdzfvf6" 1097 + "azfkIogKMV7Xk0aw6nCW6h49BYuIu3TVjiToLEu5kX0z501whcCI8SA1tlicl7CzOCvVF70vg03RAB5vZQWY" 1098 + "2oFr3AwKBYDHvsc\"," 1099 + "\"e\":\"AQAB\",\"use\":\"sig\",\"alg\":\"RS256\",\"key_ops\":\"verify\"}]}"; 1100 assertThrows( 1101 GeneralSecurityException.class, () -> JwkSetConverter.toPublicKeysetHandle(jwksString)); 1102 1103 String psJwksString = jwksString.replace("RS256", "PS256"); 1104 assertThrows( 1105 GeneralSecurityException.class, () -> JwkSetConverter.toPublicKeysetHandle(psJwksString)); 1106 } 1107 1108 @Test jwksetWithDuplicateMapKey_fails()1109 public void jwksetWithDuplicateMapKey_fails() throws Exception { 1110 String jwkSetWithDuplicateMapKey = 1111 "{\"keys\":[{" 1112 + "\"kty\":\"EC\"," 1113 + "\"kty\":\"EC\"," 1114 + "\"crv\":\"P-256\"," 1115 + "\"x\":\"EM8jrqGMse-PGZQnafIcgEOZ061DiA-y9aBhiBnSDKA\"," 1116 + "\"y\":\"UxCtK0wAqQG_e5vpr7SSgJNKt5h4z3FGZtAuBLng1uE\"," 1117 + "\"use\":\"sig\",\"alg\":\"ES256\",\"key_ops\":[\"verify\"]}]}"; 1118 assertThrows( 1119 GeneralSecurityException.class, 1120 () -> JwkSetConverter.toPublicKeysetHandle(jwkSetWithDuplicateMapKey)); 1121 } 1122 1123 @Test jwksetAsJsonArray_fails()1124 public void jwksetAsJsonArray_fails() throws Exception { 1125 String jwksetAsJsonArray = 1126 "[{" 1127 + "\"kty\":\"EC\"," 1128 + "\"crv\":\"P-256\"," 1129 + "\"x\":\"EM8jrqGMse-PGZQnafIcgEOZ061DiA-y9aBhiBnSDKA\"," 1130 + "\"y\":\"UxCtK0wAqQG_e5vpr7SSgJNKt5h4z3FGZtAuBLng1uE\"," 1131 + "\"use\":\"sig\",\"alg\":\"ES256\",\"key_ops\":[\"verify\"]}]"; 1132 assertThrows( 1133 GeneralSecurityException.class, 1134 () -> JwkSetConverter.toPublicKeysetHandle(jwksetAsJsonArray)); 1135 } 1136 1137 @Test 1138 @SuppressWarnings("InlineMeInliner") deprecatedFromKeysetHandle_sameAs_fromPublicKeysetHandle()1139 public void deprecatedFromKeysetHandle_sameAs_fromPublicKeysetHandle() 1140 throws Exception { 1141 KeysetHandle handle = 1142 TinkJsonProtoKeysetFormat.parseKeyset(ES256_KEYSET, InsecureSecretKeyAccess.get()); 1143 assertEqualJwkSets( 1144 JwkSetConverter.fromKeysetHandle(handle, KeyAccess.publicAccess()), 1145 JwkSetConverter.fromPublicKeysetHandle(handle)); 1146 } 1147 1148 @Test 1149 @SuppressWarnings("InlineMeInliner") deprecatedToKeysetHandle_sameAs_toPublicKeysetHandle()1150 public void deprecatedToKeysetHandle_sameAs_toPublicKeysetHandle() 1151 throws Exception { 1152 KeysetHandle handle = JwkSetConverter.toPublicKeysetHandle(ES256_JWK_SET); 1153 KeysetHandle deprecatedHandle = 1154 JwkSetConverter.toKeysetHandle(ES256_JWK_SET, KeyAccess.publicAccess()); 1155 assertEqualJwkSets( 1156 JwkSetConverter.fromPublicKeysetHandle(handle), 1157 JwkSetConverter.fromPublicKeysetHandle(deprecatedHandle)); 1158 } 1159 } 1160