// Path: src/main/java/com/spotify/crtauth/Fingerprint.java
// public class Fingerprint {
// 
//   private static final int FINGERPRINT_LENGTH = 6;
//   // The size of a newly generated public part of a 4096 bit key
//   private static final int TYPICAL_KEY_SIZE = 535;
// 
//   private final byte[] bytes;
// 
//   // TODO: Move CrtAuthCodec into the same package, and make this constructor package local
//   public Fingerprint(byte[] fingerprint) {
//     this.bytes = fingerprint;
//   }
// 
//   /**
//    * Calculate a bytes from the provided public key.
//    *
//    * @param publicKey the RSAPublicKey instance to make this fingerprint match
//    */
//   public Fingerprint(RSAPublicKey publicKey) {
//     byte[] digestBytes = Hashing.sha1().hashBytes(getDerEncoding(publicKey)).asBytes();
//     checkPositionIndex(FINGERPRINT_LENGTH, digestBytes.length);
//     this.bytes = Arrays.copyOf(digestBytes, FINGERPRINT_LENGTH);
//   }
// 
//   public byte[] getBytes() {
//     return bytes;
//   }
// 
//   /**
//    * Returns true if this Fingerprint matches the public key other
//    *
//    * @param other the other RSAPublicKey to match
//    * @return true if this Fingerprint matches other, else false
//    */
//   public boolean matches(RSAPublicKey other) {
//     return this.equals(new Fingerprint(other));
//   }
// 
//   private static byte[] getDerEncoding(RSAPublicKey key) {
//     ByteArrayOutputStream buffer = new ByteArrayOutputStream(TYPICAL_KEY_SIZE);
//     DataOutputStream dataOutput = new DataOutputStream(buffer);
//     writeVariableLengthOpaque("ssh-rsa".getBytes(), dataOutput);
//     writeVariableLengthOpaque(key.getPublicExponent().toByteArray(), dataOutput);
//     writeVariableLengthOpaque(key.getModulus().toByteArray(), dataOutput);
//     return buffer.toByteArray();
//   }
// 
//   private static void writeVariableLengthOpaque(byte[] opaque, DataOutput byteBuffer) {
//     try {
//       byteBuffer.writeInt(opaque.length);
//       byteBuffer.write(opaque);
//     } catch (IOException e) {
//       throw new RuntimeException(e);
//     }
//   }
// 
//   @Override
//   public boolean equals(Object o) {
//     if (this == o) {
//       return true;
//     }
//     if (o == null || getClass() != o.getClass()) {
//       return false;
//     }
// 
//     Fingerprint that = (Fingerprint) o;
// 
//     return Arrays.equals(bytes, that.bytes);
//   }
// 
//   @Override
//   public int hashCode() {
//     return Arrays.hashCode(bytes);
//   }
// }


import com.google.common.io.BaseEncoding;
import com.spotify.crtauth.Fingerprint;
import org.junit.Before;
import org.junit.Test;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
/*
 * Copyright (c) 2015 Spotify AB.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package com.spotify.crtauth.signer;



public abstract class SignerTest<T extends Signer> {
  private static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
  // RSA private key, PKCS#8, PEM
  private static final String PRIVATE_KEY_STRING =
      "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDjKPW24a0Go7ET" +
      "iMP/j8DsnG+E6bB2DvCuX5hJLbBKE/oBMsZ3eB8MyROXmv/h0b0OzugEx+llxIo0" +
      "FpnsuJxMlF7xpEp7dHKHTUdxWIclmGjI6tzurX+sDerUuJk9gNj3SK67lcZI5tsr" +
      "XjDsy+ZpVQWcL/6trB9r69VDGm+GfnC8JIItLesAbJ1IcSq4/oU3e0mRjiaf5X/b" +
      "My1lRejcqEOARWhTVTw3D+EdPqAWZPh1IzREPnoNVp5MeSVU4hRdoZmJPwP9qF4f" +
      "2qbhsw0cDDPNFigU/UDw2kW9CUlGscrPs+0sj9wim4ZwMC9hmiFS/yfzHOaoTylF" +
      "kG6ia9W/AgMBAAECggEBAN9HJmWw4uJwyR+7QXOUN/waM59AF7ujKb0rp0LejrXx" +
      "dr3wy5UoU9S8W+6bYsHy51KD2xi/6tCl43YZdQhx2OeIut3nL3KzXdNSCVQGwSgZ" +
      "63z5JVnQ3XofX9/g5nbGi/xby6wEJpcHmwvAlHRcYsjL0izYHAtW8LeiYceIV3Co" +
// Path: src/main/java/com/spotify/crtauth/Fingerprint.java
// public class Fingerprint {
// 
//   private static final int FINGERPRINT_LENGTH = 6;
//   // The size of a newly generated public part of a 4096 bit key
//   private static final int TYPICAL_KEY_SIZE = 535;
// 
//   private final byte[] bytes;
// 
//   // TODO: Move CrtAuthCodec into the same package, and make this constructor package local
//   public Fingerprint(byte[] fingerprint) {
//     this.bytes = fingerprint;
//   }
// 
//   /**
//    * Calculate a bytes from the provided public key.
//    *
//    * @param publicKey the RSAPublicKey instance to make this fingerprint match
//    */
//   public Fingerprint(RSAPublicKey publicKey) {
//     byte[] digestBytes = Hashing.sha1().hashBytes(getDerEncoding(publicKey)).asBytes();
//     checkPositionIndex(FINGERPRINT_LENGTH, digestBytes.length);
//     this.bytes = Arrays.copyOf(digestBytes, FINGERPRINT_LENGTH);
//   }
// 
//   public byte[] getBytes() {
//     return bytes;
//   }
// 
//   /**
//    * Returns true if this Fingerprint matches the public key other
//    *
//    * @param other the other RSAPublicKey to match
//    * @return true if this Fingerprint matches other, else false
//    */
//   public boolean matches(RSAPublicKey other) {
//     return this.equals(new Fingerprint(other));
//   }
// 
//   private static byte[] getDerEncoding(RSAPublicKey key) {
//     ByteArrayOutputStream buffer = new ByteArrayOutputStream(TYPICAL_KEY_SIZE);
//     DataOutputStream dataOutput = new DataOutputStream(buffer);
//     writeVariableLengthOpaque("ssh-rsa".getBytes(), dataOutput);
//     writeVariableLengthOpaque(key.getPublicExponent().toByteArray(), dataOutput);
//     writeVariableLengthOpaque(key.getModulus().toByteArray(), dataOutput);
//     return buffer.toByteArray();
//   }
// 
//   private static void writeVariableLengthOpaque(byte[] opaque, DataOutput byteBuffer) {
//     try {
//       byteBuffer.writeInt(opaque.length);
//       byteBuffer.write(opaque);
//     } catch (IOException e) {
//       throw new RuntimeException(e);
//     }
//   }
// 
//   @Override
//   public boolean equals(Object o) {
//     if (this == o) {
//       return true;
//     }
//     if (o == null || getClass() != o.getClass()) {
//       return false;
//     }
// 
//     Fingerprint that = (Fingerprint) o;
// 
//     return Arrays.equals(bytes, that.bytes);
//   }
// 
//   @Override
//   public int hashCode() {
//     return Arrays.hashCode(bytes);
//   }
// }


// Path: src/test/java/com/spotify/crtauth/signer/SignerTest.java
import com.google.common.io.BaseEncoding;
import com.spotify.crtauth.Fingerprint;
import org.junit.Before;
import org.junit.Test;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/*
 * Copyright (c) 2015 Spotify AB.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package com.spotify.crtauth.signer;



public abstract class SignerTest<T extends Signer> {
  private static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
  // RSA private key, PKCS#8, PEM
  private static final String PRIVATE_KEY_STRING =
      "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDjKPW24a0Go7ET" +
      "iMP/j8DsnG+E6bB2DvCuX5hJLbBKE/oBMsZ3eB8MyROXmv/h0b0OzugEx+llxIo0" +
      "FpnsuJxMlF7xpEp7dHKHTUdxWIclmGjI6tzurX+sDerUuJk9gNj3SK67lcZI5tsr" +
      "XjDsy+ZpVQWcL/6trB9r69VDGm+GfnC8JIItLesAbJ1IcSq4/oU3e0mRjiaf5X/b" +
      "My1lRejcqEOARWhTVTw3D+EdPqAWZPh1IzREPnoNVp5MeSVU4hRdoZmJPwP9qF4f" +
      "2qbhsw0cDDPNFigU/UDw2kW9CUlGscrPs+0sj9wim4ZwMC9hmiFS/yfzHOaoTylF" +
      "kG6ia9W/AgMBAAECggEBAN9HJmWw4uJwyR+7QXOUN/waM59AF7ujKb0rp0LejrXx" +
      "dr3wy5UoU9S8W+6bYsHy51KD2xi/6tCl43YZdQhx2OeIut3nL3KzXdNSCVQGwSgZ" +
      "63z5JVnQ3XofX9/g5nbGi/xby6wEJpcHmwvAlHRcYsjL0izYHAtW8LeiYceIV3Co" +
      "Qq99W98mgpXJ2zSeyPvBV+f/P0kUJSesRuukk9jD3Yj/iAKgaimL3YAqAnM6ZRWz" +