mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 03:58:21 +00:00
8275252: Migrate cacerts from JKS to password-less PKCS12
Reviewed-by: erikj, ihse, mullan
This commit is contained in:
parent
54a29a4470
commit
bd2b41dd70
@ -75,6 +75,8 @@ TOOL_MAKEJAVASECURITY = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_clas
|
||||
build.tools.makejavasecurity.MakeJavaSecurity
|
||||
|
||||
TOOL_GENERATECACERTS = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
|
||||
-Dkeystore.pkcs12.certProtectionAlgorithm=NONE \
|
||||
-Dkeystore.pkcs12.macAlgorithm=NONE \
|
||||
build.tools.generatecacerts.GenerateCacerts
|
||||
|
||||
TOOL_GENERATEEMOJIDATA = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,21 +25,15 @@
|
||||
|
||||
package build.tools.generatecacerts;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.DigestOutputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -51,33 +45,16 @@ import java.util.stream.Collectors;
|
||||
public class GenerateCacerts {
|
||||
public static void main(String[] args) throws Exception {
|
||||
try (FileOutputStream fos = new FileOutputStream(args[1])) {
|
||||
store(args[0], fos, "changeit".toCharArray());
|
||||
store(args[0], fos);
|
||||
}
|
||||
}
|
||||
|
||||
// The following code are copied from JavaKeyStore.java.
|
||||
public static void store(String dir, OutputStream stream) throws Exception {
|
||||
|
||||
private static final int MAGIC = 0xfeedfeed;
|
||||
private static final int VERSION_2 = 0x02;
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
|
||||
// This method is a simplified version of JavaKeyStore::engineStore.
|
||||
// A new "dir" argument is added. All cert names in "dir" is collected into
|
||||
// a sorted array. Each cert is stored with a creation date set to its
|
||||
// notBefore value. Thus the output is determined as long as the certs
|
||||
// are the same.
|
||||
public static void store(String dir, OutputStream stream, char[] password)
|
||||
throws IOException, NoSuchAlgorithmException, CertificateException
|
||||
{
|
||||
byte[] encoded; // the certificate encoding
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X509");
|
||||
|
||||
MessageDigest md = getPreKeyedHash(password);
|
||||
DataOutputStream dos
|
||||
= new DataOutputStream(new DigestOutputStream(stream, md));
|
||||
|
||||
dos.writeInt(MAGIC);
|
||||
// always write the latest version
|
||||
dos.writeInt(VERSION_2);
|
||||
KeyStore ks = KeyStore.getInstance("pkcs12");
|
||||
ks.load(null, null);
|
||||
|
||||
// All file names in dir sorted.
|
||||
// README is excluded. Name starting with "." excluded.
|
||||
@ -88,61 +65,15 @@ public class GenerateCacerts {
|
||||
|
||||
entries.sort(String::compareTo);
|
||||
|
||||
dos.writeInt(entries.size());
|
||||
|
||||
for (String entry : entries) {
|
||||
|
||||
String alias = entry + " [jdk]";
|
||||
X509Certificate cert;
|
||||
try (InputStream fis = Files.newInputStream(Path.of(dir, entry))) {
|
||||
cert = (X509Certificate) cf.generateCertificate(fis);
|
||||
}
|
||||
|
||||
dos.writeInt(2);
|
||||
|
||||
// Write the alias
|
||||
dos.writeUTF(alias);
|
||||
|
||||
// Write the (entry creation) date, which is notBefore of the cert
|
||||
dos.writeLong(cert.getNotBefore().getTime());
|
||||
|
||||
// Write the trusted certificate
|
||||
encoded = cert.getEncoded();
|
||||
dos.writeUTF(cert.getType());
|
||||
dos.writeInt(encoded.length);
|
||||
dos.write(encoded);
|
||||
ks.setCertificateEntry(alias, cert);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the keyed hash which is used to detect tampering with
|
||||
* the keystore (such as deleting or modifying key or
|
||||
* certificate entries).
|
||||
*/
|
||||
byte[] digest = md.digest();
|
||||
|
||||
dos.write(digest);
|
||||
dos.flush();
|
||||
}
|
||||
|
||||
private static MessageDigest getPreKeyedHash(char[] password)
|
||||
throws NoSuchAlgorithmException, UnsupportedEncodingException
|
||||
{
|
||||
|
||||
MessageDigest md = MessageDigest.getInstance("SHA");
|
||||
byte[] passwdBytes = convertToBytes(password);
|
||||
md.update(passwdBytes);
|
||||
Arrays.fill(passwdBytes, (byte) 0x00);
|
||||
md.update("Mighty Aphrodite".getBytes("UTF8"));
|
||||
return md;
|
||||
}
|
||||
|
||||
private static byte[] convertToBytes(char[] password) {
|
||||
int i, j;
|
||||
byte[] passwdBytes = new byte[password.length * 2];
|
||||
for (i=0, j=0; i<password.length; i++) {
|
||||
passwdBytes[j++] = (byte)(password[i] >> 8);
|
||||
passwdBytes[j++] = (byte)password[i];
|
||||
}
|
||||
return passwdBytes;
|
||||
ks.store(stream, null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ public class VerifyCACerts {
|
||||
// SHA-256 of cacerts, can be generated with
|
||||
// shasum -a 256 cacerts | sed -e 's/../&:/g' | tr '[:lower:]' '[:upper:]' | cut -c1-95
|
||||
private static final String CHECKSUM
|
||||
= "CC:AD:BB:49:70:97:3F:42:AD:73:91:A0:A2:C4:B8:AA:D1:95:59:F3:B3:22:09:2A:1F:2C:AB:04:47:08:EF:AA";
|
||||
= "0D:9C:40:8F:CE:B1:C7:27:89:54:FD:80:DA:B6:91:F4:C9:94:15:C4:8D:25:62:34:D4:70:32:60:1A:6F:13:27";
|
||||
|
||||
// Hex formatter to upper case with ":" delimiter
|
||||
private static final HexFormat HEX = HexFormat.ofDelimiter(":").withUpperCase();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user