Replace spongy with libsignal x509 generation for device transfer.

This commit is contained in:
Cody Henthorne
2021-05-19 17:29:48 -04:00
committed by GitHub
parent 6770d21cf7
commit 11df2bc51f
5 changed files with 16 additions and 100 deletions

View File

@@ -3,32 +3,22 @@ package org.signal.devicetransfer;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.spongycastle.asn1.x500.X500Name;
import org.spongycastle.asn1.x500.X500NameBuilder;
import org.spongycastle.asn1.x500.style.BCStyle;
import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
import org.spongycastle.cert.X509CertificateHolder;
import org.spongycastle.cert.X509v3CertificateBuilder;
import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.spongycastle.operator.ContentSigner;
import org.spongycastle.operator.OperatorCreationException;
import org.spongycastle.operator.jcajce.JcaContentSignerBuilder;
import org.signal.libsignal.devicetransfer.DeviceTransferKey;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
@@ -43,24 +33,19 @@ import javax.net.ssl.X509TrustManager;
final class SelfSignedIdentity {
private static final String KEY_GENERATION_ALGORITHM = "RSA";
private static final int KEY_SIZE = 4096;
private static final String SSL_CONTEXT_PROTOCOL = "TLS";
private static final String CERTIFICATE_TYPE = "X509";
private static final String KEYSTORE_TYPE = "BKS";
private static final String SIGNATURE_ALGORITHM = "SHA256WithRSAEncryption";
private SelfSignedIdentity() { }
public static @NonNull SelfSignedKeys create() throws KeyGenerationFailedException {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_GENERATION_ALGORITHM);
keyPairGenerator.initialize(KEY_SIZE);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
X509CertificateHolder x509 = createX509(keyPair);
return new SelfSignedKeys(x509.getEncoded(), keyPair.getPrivate());
} catch (GeneralSecurityException | OperatorCreationException | IOException e) {
DeviceTransferKey key = new DeviceTransferKey();
byte[] x509 = key.generateCertificate("SignalTransfer", 1);
PrivateKey privateKey = KeyFactory.getInstance(KEY_GENERATION_ALGORITHM).generatePrivate(new PKCS8EncodedKeySpec(key.keyMaterial()));
return new SelfSignedKeys(x509, privateKey);
} catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
throw new KeyGenerationFailedException(e);
}
}
@@ -73,7 +58,7 @@ final class SelfSignedIdentity {
KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE);
keyStore.load(null);
keyStore.setKeyEntry("client", keys.getPrivateKey(), null, new Certificate[]{certificate});
keyStore.setKeyEntry("client", keys.getPrivateKey(), null, new Certificate[] { certificate });
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, null);
@@ -88,40 +73,10 @@ final class SelfSignedIdentity {
throws GeneralSecurityException
{
SSLContext sslContext = SSLContext.getInstance(SSL_CONTEXT_PROTOCOL);
sslContext.init(null, new TrustManager[]{trustManager}, new SecureRandom());
sslContext.init(null, new TrustManager[] { trustManager }, new SecureRandom());
return sslContext.getSocketFactory();
}
private static @NonNull X509CertificateHolder createX509(@NonNull KeyPair keyPair) throws OperatorCreationException {
Date startDate = new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000);
Date endDate = new Date(System.currentTimeMillis() + 24 * 60 * 60 * 1000);
X500NameBuilder nameBuilder = new X500NameBuilder(BCStyle.INSTANCE);
nameBuilder.addRDN(BCStyle.C, "United States");
nameBuilder.addRDN(BCStyle.ST, "California");
nameBuilder.addRDN(BCStyle.L, "San Francisco");
nameBuilder.addRDN(BCStyle.O, "Signal Foundation");
nameBuilder.addRDN(BCStyle.CN, "SignalTransfer");
X500Name x500Name = nameBuilder.build();
BigInteger serialNumber = BigInteger.valueOf(new SecureRandom().nextLong()).abs();
SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded());
X509v3CertificateBuilder certificateBuilder = new X509v3CertificateBuilder(x500Name,
serialNumber,
startDate,
endDate,
x500Name,
subjectPublicKeyInfo);
Security.addProvider(new BouncyCastleProvider());
ContentSigner signer = new JcaContentSignerBuilder(SIGNATURE_ALGORITHM).setProvider(BouncyCastleProvider.PROVIDER_NAME)
.build(keyPair.getPrivate());
Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
return certificateBuilder.build(signer);
}
static final class SelfSignedKeys {
private final byte[] x509Encoded;
private final PrivateKey privateKey;