mirror of
https://github.com/google/nomulus.git
synced 2025-05-14 00:17:20 +02:00
Refactor KmsKeyring and KmsUpdater to use a centralized serializer
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=151853998
This commit is contained in:
parent
ff9c72097c
commit
bb70fcb66d
7 changed files with 377 additions and 195 deletions
134
java/google/registry/keyring/api/KeySerializer.java
Normal file
134
java/google/registry/keyring/api/KeySerializer.java
Normal file
|
@ -0,0 +1,134 @@
|
|||
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// 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 google.registry.keyring.api;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import org.bouncycastle.bcpg.ArmoredOutputStream;
|
||||
import org.bouncycastle.bcpg.HashAlgorithmTags;
|
||||
import org.bouncycastle.openpgp.PGPException;
|
||||
import org.bouncycastle.openpgp.PGPKeyPair;
|
||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||
import org.bouncycastle.openpgp.PGPUtil;
|
||||
import org.bouncycastle.openpgp.bc.BcPGPPublicKeyRing;
|
||||
import org.bouncycastle.openpgp.bc.BcPGPSecretKeyRing;
|
||||
import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor;
|
||||
import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyDecryptorBuilder;
|
||||
import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider;
|
||||
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
|
||||
|
||||
/**
|
||||
* Collection of tools to serialize / deserialize PGP types.
|
||||
*
|
||||
* <p>There is no way to serialize / deserialize a PGPPrivateKey on its own, you have to pair it
|
||||
* with the public key.
|
||||
*/
|
||||
public final class KeySerializer {
|
||||
|
||||
|
||||
private KeySerializer() {}
|
||||
|
||||
/**
|
||||
* Serialize a PGPPublicKey
|
||||
*
|
||||
* <p>The reason we're not using {@link PGPPublicKey#getEncoded()} is to use {@link
|
||||
* ArmoredOutputStream}.
|
||||
*/
|
||||
public static byte[] serializePublicKey(PGPPublicKey publicKey) throws IOException {
|
||||
try (ByteArrayOutputStream byteStream = new ByteArrayOutputStream()) {
|
||||
// NOTE: We have to close the ArmoredOutputStream before calling the underlying OutputStream's
|
||||
// "toByteArray". Failing to do so would result in a truncated serialization as we took the
|
||||
// byte array before the ArmoredOutputStream wrote all the data.
|
||||
//
|
||||
// Even "flushing" the ArmoredOutputStream isn't enough - as there are parts that are only
|
||||
// written by the ArmoredOutputStream when it is closed: the "-----END PGP PRIVATE KEY
|
||||
// BLOCK-----" (or similar) footer.
|
||||
try (ArmoredOutputStream out = new ArmoredOutputStream(byteStream)) {
|
||||
publicKey.encode(out);
|
||||
}
|
||||
return byteStream.toByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
/** Deserialize a PGPPublicKey */
|
||||
public static PGPPublicKey deserializePublicKey(byte[] serialized) throws IOException {
|
||||
return
|
||||
new BcPGPPublicKeyRing(
|
||||
PGPUtil.getDecoderStream(
|
||||
new ByteArrayInputStream(serialized))).getPublicKey();
|
||||
}
|
||||
|
||||
/** Serializes a string */
|
||||
public static byte[] serializeString(String key) {
|
||||
return key.getBytes(UTF_8);
|
||||
}
|
||||
|
||||
/** Deserializes a string */
|
||||
public static String deserializeString(byte[] serialized) {
|
||||
return new String(serialized, UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize a PGPKeyPair
|
||||
*
|
||||
* <p>Use this to serialize a PGPPrivateKey as well (pairing it with the corresponding
|
||||
* PGPPublicKey), as private keys can't be serialized on their own.
|
||||
*/
|
||||
public static byte[] serializeKeyPair(PGPKeyPair keyPair) throws IOException, PGPException {
|
||||
try (ByteArrayOutputStream byteStream = new ByteArrayOutputStream()) {
|
||||
// NOTE: We have to close the ArmoredOutputStream before calling the underlying OutputStream's
|
||||
// "toByteArray". Failing to do so would result in a truncated serialization as we took the
|
||||
// byte array before the ArmoredOutputStream wrote all the data.
|
||||
//
|
||||
// Even "flushing" the ArmoredOutputStream isn't enough - as there are parts that are only
|
||||
// written by the ArmoredOutputStream when it is closed: the "-----END PGP PRIVATE KEY
|
||||
// BLOCK-----" (or similar) footer.
|
||||
try (ArmoredOutputStream out = new ArmoredOutputStream(byteStream)) {
|
||||
new PGPSecretKey(
|
||||
keyPair.getPrivateKey(),
|
||||
keyPair.getPublicKey(),
|
||||
new JcaPGPDigestCalculatorProviderBuilder()
|
||||
.setProvider("BC")
|
||||
.build()
|
||||
.get(HashAlgorithmTags.SHA256),
|
||||
true,
|
||||
null).encode(out);
|
||||
}
|
||||
return byteStream.toByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
/** Deserialize a PGPKeyPair */
|
||||
public static PGPKeyPair deserializeKeyPair(byte[] serialized)
|
||||
throws IOException, PGPException {
|
||||
PGPSecretKey secretKey =
|
||||
new BcPGPSecretKeyRing(
|
||||
PGPUtil.getDecoderStream(
|
||||
new ByteArrayInputStream(serialized))).getSecretKey();
|
||||
return new PGPKeyPair(
|
||||
secretKey.getPublicKey(),
|
||||
secretKey.extractPrivateKey(createSecretKeyDecryptor()));
|
||||
}
|
||||
|
||||
private static PBESecretKeyDecryptor createSecretKeyDecryptor() {
|
||||
// There shouldn't be a passphrase on the key
|
||||
return new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider())
|
||||
.build(new char[0]);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue