| 
 | 1 | +/*  | 
 | 2 | + * Licensed to the Apache Software Foundation (ASF) under one  | 
 | 3 | + * or more contributor license agreements.  See the NOTICE file  | 
 | 4 | + * distributed with this work for additional information  | 
 | 5 | + * regarding copyright ownership.  The ASF licenses this file  | 
 | 6 | + * to you under the Apache License, Version 2.0 (the  | 
 | 7 | + * "License"); you may not use this file except in compliance  | 
 | 8 | + * with the License.  You may obtain a copy of the License at  | 
 | 9 | + *  | 
 | 10 | + *   http://www.apache.org/licenses/LICENSE-2.0  | 
 | 11 | + *  | 
 | 12 | + * Unless required by applicable law or agreed to in writing,  | 
 | 13 | + * software distributed under the License is distributed on an  | 
 | 14 | + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY  | 
 | 15 | + * KIND, either express or implied.  See the License for the  | 
 | 16 | + * specific language governing permissions and limitations  | 
 | 17 | + * under the License.  | 
 | 18 | + */  | 
 | 19 | +package org.apache.polaris.service.auth;  | 
 | 20 | + | 
 | 21 | +import static org.junit.jupiter.api.Assertions.assertEquals;  | 
 | 22 | +import static org.junit.jupiter.api.Assertions.assertThrows;  | 
 | 23 | + | 
 | 24 | +import java.io.IOException;  | 
 | 25 | +import java.nio.file.Files;  | 
 | 26 | +import java.nio.file.Path;  | 
 | 27 | +import java.security.KeyPair;  | 
 | 28 | +import java.security.KeyPairGenerator;  | 
 | 29 | +import java.security.NoSuchAlgorithmException;  | 
 | 30 | +import java.security.PrivateKey;  | 
 | 31 | +import java.security.PublicKey;  | 
 | 32 | +import java.util.Base64;  | 
 | 33 | +import org.junit.jupiter.api.BeforeAll;  | 
 | 34 | +import org.junit.jupiter.api.Test;  | 
 | 35 | +import org.junit.jupiter.api.io.TempDir;  | 
 | 36 | + | 
 | 37 | +public class PemUtilsTest {  | 
 | 38 | +  private static final String RSA_ALGORITHM = "RSA";  | 
 | 39 | + | 
 | 40 | +  private static final String PUBLIC_KEY_HEADER = "-----BEGIN PUBLIC KEY-----";  | 
 | 41 | + | 
 | 42 | +  private static final String PUBLIC_KEY_FOOTER = "-----END PUBLIC KEY-----";  | 
 | 43 | + | 
 | 44 | +  private static final String PRIVATE_KEY_HEADER = "-----BEGIN PRIVATE KEY-----";  | 
 | 45 | + | 
 | 46 | +  private static final String PRIVATE_KEY_FOOTER = "-----END PRIVATE KEY-----";  | 
 | 47 | + | 
 | 48 | +  private static final String LINE_SEPARATOR = System.lineSeparator();  | 
 | 49 | + | 
 | 50 | +  private static final String RSA_PUBLIC_KEY_FILE = "rsa-public-key.pem";  | 
 | 51 | + | 
 | 52 | +  private static final String RSA_PRIVATE_KEY_FILE = "rsa-private-key.pem";  | 
 | 53 | + | 
 | 54 | +  private static final String RSA_PUBLIC_KEY_AND_PRIVATE_KEY_FILE = "rsa-public-key-pair.pem";  | 
 | 55 | + | 
 | 56 | +  private static final String EMPTY_FILE = "empty.pem";  | 
 | 57 | + | 
 | 58 | +  private static final Base64.Encoder encoder = Base64.getMimeEncoder();  | 
 | 59 | + | 
 | 60 | +  @TempDir private static Path tempDir;  | 
 | 61 | + | 
 | 62 | +  private static Path rsaRublicKeyPath;  | 
 | 63 | + | 
 | 64 | +  private static PublicKey rsaPublicKey;  | 
 | 65 | + | 
 | 66 | +  private static Path rsaPrivateKeyPath;  | 
 | 67 | + | 
 | 68 | +  private static PrivateKey rsaPrivateKey;  | 
 | 69 | + | 
 | 70 | +  private static Path rsaPublicKeyAndPrivateKeyPath;  | 
 | 71 | + | 
 | 72 | +  private static Path emptyFilePath;  | 
 | 73 | + | 
 | 74 | +  @BeforeAll  | 
 | 75 | +  public static void setKeyPair() throws NoSuchAlgorithmException, IOException {  | 
 | 76 | +    final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA_ALGORITHM);  | 
 | 77 | +    final KeyPair keyPair = keyPairGenerator.generateKeyPair();  | 
 | 78 | +    rsaPublicKey = keyPair.getPublic();  | 
 | 79 | +    rsaPrivateKey = keyPair.getPrivate();  | 
 | 80 | + | 
 | 81 | +    final String publicKeyEncoded = getPublicKeyEncoded(rsaPublicKey);  | 
 | 82 | +    final String privateKeyEncoded = getPrivateKeyEncoded(rsaPrivateKey);  | 
 | 83 | + | 
 | 84 | +    rsaRublicKeyPath = tempDir.resolve(RSA_PUBLIC_KEY_FILE);  | 
 | 85 | +    Files.writeString(rsaRublicKeyPath, publicKeyEncoded);  | 
 | 86 | + | 
 | 87 | +    rsaPrivateKeyPath = tempDir.resolve(RSA_PRIVATE_KEY_FILE);  | 
 | 88 | +    Files.writeString(rsaPrivateKeyPath, privateKeyEncoded);  | 
 | 89 | + | 
 | 90 | +    rsaPublicKeyAndPrivateKeyPath = tempDir.resolve(RSA_PUBLIC_KEY_AND_PRIVATE_KEY_FILE);  | 
 | 91 | +    final String rsaPublicKeyAndPrivateKey = publicKeyEncoded + LINE_SEPARATOR + privateKeyEncoded;  | 
 | 92 | +    Files.writeString(rsaPublicKeyAndPrivateKeyPath, rsaPublicKeyAndPrivateKey);  | 
 | 93 | + | 
 | 94 | +    emptyFilePath = tempDir.resolve(EMPTY_FILE);  | 
 | 95 | +    Files.write(emptyFilePath, new byte[0]);  | 
 | 96 | +  }  | 
 | 97 | + | 
 | 98 | +  @Test  | 
 | 99 | +  public void testReadPublicKeyFromFileRSA() throws IOException {  | 
 | 100 | +    final PublicKey publicKeyRead = PemUtils.readPublicKeyFromFile(rsaRublicKeyPath, RSA_ALGORITHM);  | 
 | 101 | + | 
 | 102 | +    assertEquals(rsaPublicKey, publicKeyRead);  | 
 | 103 | +  }  | 
 | 104 | + | 
 | 105 | +  @Test  | 
 | 106 | +  public void testReadPrivateKeyFromFileRSA() throws IOException {  | 
 | 107 | +    final PrivateKey privateKeyRead =  | 
 | 108 | +        PemUtils.readPrivateKeyFromFile(rsaPrivateKeyPath, RSA_ALGORITHM);  | 
 | 109 | + | 
 | 110 | +    assertEquals(rsaPrivateKey, privateKeyRead);  | 
 | 111 | +  }  | 
 | 112 | + | 
 | 113 | +  @Test  | 
 | 114 | +  public void testReadPublicKeyFromFileRSAWithPrivateKeyIgnored() throws IOException {  | 
 | 115 | +    final PublicKey publicKeyRead =  | 
 | 116 | +        PemUtils.readPublicKeyFromFile(rsaPublicKeyAndPrivateKeyPath, RSA_ALGORITHM);  | 
 | 117 | + | 
 | 118 | +    assertEquals(rsaPublicKey, publicKeyRead);  | 
 | 119 | +  }  | 
 | 120 | + | 
 | 121 | +  @Test  | 
 | 122 | +  public void testReadEmptyFIle() {  | 
 | 123 | +    assertThrows(  | 
 | 124 | +        IOException.class, () -> PemUtils.readPublicKeyFromFile(emptyFilePath, RSA_ALGORITHM));  | 
 | 125 | +  }  | 
 | 126 | + | 
 | 127 | +  private static String getPublicKeyEncoded(final PublicKey publicKey) {  | 
 | 128 | +    final StringBuilder builder = new StringBuilder();  | 
 | 129 | + | 
 | 130 | +    builder.append(PUBLIC_KEY_HEADER);  | 
 | 131 | +    builder.append(LINE_SEPARATOR);  | 
 | 132 | + | 
 | 133 | +    final byte[] publicKeyEncoded = publicKey.getEncoded();  | 
 | 134 | +    final String encoded = encoder.encodeToString(publicKeyEncoded);  | 
 | 135 | +    builder.append(encoded);  | 
 | 136 | +    builder.append(LINE_SEPARATOR);  | 
 | 137 | + | 
 | 138 | +    builder.append(PUBLIC_KEY_FOOTER);  | 
 | 139 | +    builder.append(LINE_SEPARATOR);  | 
 | 140 | + | 
 | 141 | +    return builder.toString();  | 
 | 142 | +  }  | 
 | 143 | + | 
 | 144 | +  private static String getPrivateKeyEncoded(final PrivateKey privateKey) {  | 
 | 145 | +    final StringBuilder builder = new StringBuilder();  | 
 | 146 | + | 
 | 147 | +    builder.append(PRIVATE_KEY_HEADER);  | 
 | 148 | +    builder.append(LINE_SEPARATOR);  | 
 | 149 | + | 
 | 150 | +    final byte[] privateKeyEncoded = privateKey.getEncoded();  | 
 | 151 | +    final String encoded = encoder.encodeToString(privateKeyEncoded);  | 
 | 152 | +    builder.append(encoded);  | 
 | 153 | +    builder.append(LINE_SEPARATOR);  | 
 | 154 | + | 
 | 155 | +    builder.append(PRIVATE_KEY_FOOTER);  | 
 | 156 | +    builder.append(LINE_SEPARATOR);  | 
 | 157 | + | 
 | 158 | +    return builder.toString();  | 
 | 159 | +  }  | 
 | 160 | +}  | 
0 commit comments