All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.crypto.tink.signature.SignaturePemKeysetReader Maven / Gradle / Ivy

Go to download

Tink is a small cryptographic library that provides a safe, simple, agile and fast way to accomplish some common cryptographic tasks.

The newest version!
// Copyright 2017 Google LLC
//
// 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.google.crypto.tink.signature;

import com.google.crypto.tink.KeysetReader;
import com.google.crypto.tink.PemKeyType;
import com.google.crypto.tink.proto.EcdsaParams;
import com.google.crypto.tink.proto.EcdsaPublicKey;
import com.google.crypto.tink.proto.EcdsaSignatureEncoding;
import com.google.crypto.tink.proto.EllipticCurveType;
import com.google.crypto.tink.proto.EncryptedKeyset;
import com.google.crypto.tink.proto.HashType;
import com.google.crypto.tink.proto.KeyData;
import com.google.crypto.tink.proto.KeyStatusType;
import com.google.crypto.tink.proto.Keyset;
import com.google.crypto.tink.proto.OutputPrefixType;
import com.google.crypto.tink.proto.RsaSsaPkcs1Params;
import com.google.crypto.tink.proto.RsaSsaPkcs1PublicKey;
import com.google.crypto.tink.proto.RsaSsaPssParams;
import com.google.crypto.tink.proto.RsaSsaPssPublicKey;
import com.google.crypto.tink.signature.internal.SigUtil;
import com.google.crypto.tink.subtle.Random;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.security.Key;
import java.security.interfaces.ECPublicKey;
import java.security.interfaces.RSAPublicKey;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;

/**
 * SignaturePemKeysetReader is a {@link KeysetReader} that can read digital signature keys in PEM
 * format (RFC 7468).
 *
 * 

Only supports public keys. * *

Private, unknown or invalid keys are ignored. * *

Usage

* *
{@code
 * import com.google.crypto.tink.PemKeyType;
 *
 * String pem = ...;
 * PemKeyType type = ...;
 * KeysetReader reader = SignaturePemKeysetReader.newBuilder().addPem(pem, type).build();
 * }
*/ public final class SignaturePemKeysetReader implements KeysetReader { private List pemKeys; SignaturePemKeysetReader(List pemKeys) { this.pemKeys = pemKeys; } /** Returns a {@link Builder} for {@link SignaturePemKeysetReader}. */ public static Builder newBuilder() { return new Builder(); } /** Builder for SignaturePemKeysetReader */ public static final class Builder { private List pemKeys = new ArrayList(); Builder() {} public KeysetReader build() { return new SignaturePemKeysetReader(pemKeys); } /** * Adds a PEM. * *

A single PEM can contain multiple keys, but all must have the same {@code keyType}. * Invalid or unparsable keys are ignored. * *

The first key in the first added PEM is the primary key. */ @CanIgnoreReturnValue public Builder addPem(String pem, PemKeyType keyType) { PemKey pemKey = new PemKey(); pemKey.reader = new BufferedReader(new StringReader(pem)); pemKey.type = keyType; pemKeys.add(pemKey); return this; } } private static final class PemKey { BufferedReader reader; PemKeyType type; } @Override public Keyset read() throws IOException { Keyset.Builder keyset = Keyset.newBuilder(); for (PemKey pemKey : pemKeys) { for (Keyset.Key key = readKey(pemKey.reader, pemKey.type); key != null; key = readKey(pemKey.reader, pemKey.type)) { keyset.addKey(key); } } if (keyset.getKeyCount() == 0) { throw new IOException("cannot find any key"); } // Use the first key as the primary key id. keyset.setPrimaryKeyId(keyset.getKey(0).getKeyId()); return keyset.build(); } @Override public EncryptedKeyset readEncrypted() throws IOException { throw new UnsupportedOperationException(); } /** Reads a single PEM key from {@code reader}. Invalid or unparsable PEM would be ignored */ @Nullable private static Keyset.Key readKey(BufferedReader reader, PemKeyType pemKeyType) throws IOException { Key key = pemKeyType.readKey(reader); if (key == null) { return null; } KeyData keyData; if (key instanceof RSAPublicKey) { keyData = convertRsaPublicKey(pemKeyType, (RSAPublicKey) key); } else if (key instanceof ECPublicKey) { keyData = convertEcPublicKey(pemKeyType, (ECPublicKey) key); } else { // Private keys are ignored. return null; } return Keyset.Key.newBuilder() .setKeyData(keyData) .setStatus(KeyStatusType.ENABLED) .setOutputPrefixType(OutputPrefixType.RAW) // PEM keys don't add any prefix to signatures .setKeyId(Random.randInt()) .build(); } private static KeyData convertRsaPublicKey(PemKeyType pemKeyType, RSAPublicKey key) throws IOException { if (pemKeyType.algorithm.equals("RSASSA-PKCS1-v1_5")) { RsaSsaPkcs1Params params = RsaSsaPkcs1Params.newBuilder().setHashType(getHashType(pemKeyType)).build(); RsaSsaPkcs1PublicKey pkcs1PubKey = RsaSsaPkcs1PublicKey.newBuilder() .setVersion(0) .setParams(params) .setE(SigUtil.toUnsignedIntByteString(key.getPublicExponent())) .setN(SigUtil.toUnsignedIntByteString(key.getModulus())) .build(); return KeyData.newBuilder() .setTypeUrl(RsaSsaPkcs1VerifyKeyManager.getKeyType()) .setValue(pkcs1PubKey.toByteString()) .setKeyMaterialType(KeyData.KeyMaterialType.ASYMMETRIC_PUBLIC) .build(); } else if (pemKeyType.algorithm.equals("RSASSA-PSS")) { RsaSsaPssParams params = RsaSsaPssParams.newBuilder() .setSigHash(getHashType(pemKeyType)) .setMgf1Hash(getHashType(pemKeyType)) .setSaltLength(getDigestSizeInBytes(pemKeyType)) .build(); RsaSsaPssPublicKey pssPubKey = RsaSsaPssPublicKey.newBuilder() .setVersion(0) .setParams(params) .setE(SigUtil.toUnsignedIntByteString(key.getPublicExponent())) .setN(SigUtil.toUnsignedIntByteString(key.getModulus())) .build(); return KeyData.newBuilder() .setTypeUrl(RsaSsaPssVerifyKeyManager.getKeyType()) .setValue(pssPubKey.toByteString()) .setKeyMaterialType(KeyData.KeyMaterialType.ASYMMETRIC_PUBLIC) .build(); } throw new IOException("unsupported RSA signature algorithm: " + pemKeyType.algorithm); } private static KeyData convertEcPublicKey(PemKeyType pemKeyType, ECPublicKey key) throws IOException { if (pemKeyType.algorithm.equals("ECDSA")) { EcdsaParams params = EcdsaParams.newBuilder() .setHashType(getHashType(pemKeyType)) .setCurve(getCurveType(pemKeyType)) .setEncoding(EcdsaSignatureEncoding.DER) .build(); EcdsaPublicKey ecdsaPubKey = EcdsaPublicKey.newBuilder() .setVersion(0) .setParams(params) .setX(SigUtil.toUnsignedIntByteString(key.getW().getAffineX())) .setY(SigUtil.toUnsignedIntByteString(key.getW().getAffineY())) .build(); return KeyData.newBuilder() .setTypeUrl(EcdsaVerifyKeyManager.getKeyType()) .setValue(ecdsaPubKey.toByteString()) .setKeyMaterialType(KeyData.KeyMaterialType.ASYMMETRIC_PUBLIC) .build(); } throw new IOException("unsupported EC signature algorithm: " + pemKeyType.algorithm); } private static HashType getHashType(PemKeyType pemKeyType) { switch (pemKeyType.hash) { case SHA256: return HashType.SHA256; case SHA384: return HashType.SHA384; case SHA512: return HashType.SHA512; default: break; } throw new IllegalArgumentException("unsupported hash type: " + pemKeyType.hash.name()); } private static int getDigestSizeInBytes(PemKeyType pemKeyType) { switch (pemKeyType.hash) { case SHA256: return 32; case SHA384: return 48; case SHA512: return 64; default: break; } throw new IllegalArgumentException("unsupported hash type: " + pemKeyType.hash.name()); } private static EllipticCurveType getCurveType(PemKeyType pemKeyType) { switch (pemKeyType.keySizeInBits) { case 256: return EllipticCurveType.NIST_P256; case 384: return EllipticCurveType.NIST_P384; case 521: return EllipticCurveType.NIST_P521; default: break; } throw new IllegalArgumentException( "unsupported curve for key size: " + pemKeyType.keySizeInBits); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy