| /* GENERATED SOURCE. DO NOT MODIFY. */ |
| package com.android.org.conscrypt; |
| |
| import java.security.PrivateKey; |
| import java.security.spec.InvalidKeySpecException; |
| import java.security.spec.PKCS8EncodedKeySpec; |
| import java.util.Arrays; |
| |
| /** |
| * @hide This class is not part of the Android public SDK API |
| */ |
| public class OpenSSLX25519PrivateKey implements OpenSSLX25519Key, PrivateKey { |
| private static final long serialVersionUID = -3136201500221850916L; |
| private static final byte[] PKCS8_PREAMBLE = new byte[]{ |
| 0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x6e, 0x04, 0x22, 0x04, 0x20, |
| }; |
| |
| private static final byte[] PKCS8_PREAMBLE_WITH_NULL = new byte[] { |
| 0x30, 0x30, 0x02, 0x01, 0x00, 0x30, 0x07, 0x06, 0x03, 0x2B, 0x65, 0x6E, 0x05, 0x00, 0x04, 0x22, 0x04, 0x20, |
| }; |
| |
| private byte[] uCoordinate; |
| |
| public OpenSSLX25519PrivateKey(PKCS8EncodedKeySpec keySpec) throws InvalidKeySpecException { |
| byte[] encoded = keySpec.getEncoded(); |
| if (encoded == null || !"PKCS#8".equals(keySpec.getFormat())) { |
| throw new InvalidKeySpecException("Key must be encoded in PKCS#8 format"); |
| } |
| |
| int preambleLength = matchesPreamble(PKCS8_PREAMBLE, encoded) | matchesPreamble(PKCS8_PREAMBLE_WITH_NULL, encoded); |
| if (preambleLength == 0) { |
| throw new InvalidKeySpecException("Key size is not correct size"); |
| } |
| |
| uCoordinate = Arrays.copyOfRange(encoded, PKCS8_PREAMBLE.length, encoded.length); |
| } |
| |
| private static int matchesPreamble(byte[] preamble, byte[] encoded) { |
| if (encoded.length != (preamble.length + X25519_KEY_SIZE_BYTES)) { |
| return 0; |
| } |
| int cmp = 0; |
| for (int i = 0; i < preamble.length; i++) { |
| cmp |= encoded[i] ^ preamble[i]; |
| } |
| if (cmp != 0) { |
| return 0; |
| } |
| return preamble.length; |
| } |
| |
| public OpenSSLX25519PrivateKey(byte[] coordinateBytes) { |
| uCoordinate = coordinateBytes.clone(); |
| } |
| |
| @Override |
| public String getAlgorithm() { |
| return "XDH"; |
| } |
| |
| @Override |
| public String getFormat() { |
| return "PKCS#8"; |
| } |
| |
| @Override |
| public byte[] getEncoded() { |
| if (uCoordinate == null) { |
| throw new IllegalStateException("key is destroyed"); |
| } |
| |
| byte[] encoded = Arrays.copyOf(PKCS8_PREAMBLE, PKCS8_PREAMBLE.length + uCoordinate.length); |
| System.arraycopy(uCoordinate, 0, encoded, PKCS8_PREAMBLE.length, uCoordinate.length); |
| return encoded; |
| } |
| |
| @Override |
| public byte[] getU() { |
| if (uCoordinate == null) { |
| throw new IllegalStateException("key is destroyed"); |
| } |
| |
| return uCoordinate.clone(); |
| } |
| |
| @Override |
| public void destroy() { |
| if (uCoordinate != null) { |
| Arrays.fill(uCoordinate, (byte) 0); |
| uCoordinate = null; |
| } |
| } |
| |
| @Override |
| public boolean isDestroyed() { |
| return uCoordinate == null; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) return true; |
| if (!(o instanceof OpenSSLX25519PrivateKey)) return false; |
| OpenSSLX25519PrivateKey that = (OpenSSLX25519PrivateKey) o; |
| return Arrays.equals(uCoordinate, that.uCoordinate); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Arrays.hashCode(uCoordinate); |
| } |
| } |