8242068: Signed JAR support for RSASSA-PSS and EdDSA
Reviewed-by: valeriep
This commit is contained in:
parent
e559bd2c8b
commit
839f01ddf5
@ -196,8 +196,8 @@ public class ContentInfo {
|
||||
if (content == null)
|
||||
return null;
|
||||
|
||||
DerInputStream dis = new DerInputStream(content.toByteArray());
|
||||
return dis.getOctetString();
|
||||
DerValue v = new DerValue(content.toByteArray());
|
||||
return v.getOctetString();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
@ -28,6 +28,9 @@ package sun.security.pkcs;
|
||||
import java.io.*;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URI;
|
||||
import java.security.interfaces.EdECPrivateKey;
|
||||
import java.security.spec.InvalidParameterSpecException;
|
||||
import java.security.spec.PSSParameterSpec;
|
||||
import java.util.*;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
@ -35,14 +38,12 @@ import java.security.cert.X509CRL;
|
||||
import java.security.cert.CRLException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
import sun.security.provider.SHAKE256;
|
||||
import sun.security.timestamp.*;
|
||||
import sun.security.util.*;
|
||||
import sun.security.x509.AlgorithmId;
|
||||
import sun.security.x509.X509CertImpl;
|
||||
import sun.security.x509.X509CertInfo;
|
||||
import sun.security.x509.X509CRLImpl;
|
||||
import sun.security.x509.X500Name;
|
||||
import sun.security.x509.*;
|
||||
|
||||
/**
|
||||
* PKCS7 as defined in RSA Laboratories PKCS7 Technical Note. Profile
|
||||
@ -86,16 +87,6 @@ public class PKCS7 {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Object identifier for the timestamping key purpose.
|
||||
*/
|
||||
private static final String KP_TIMESTAMPING_OID = "1.3.6.1.5.5.7.3.8";
|
||||
|
||||
/*
|
||||
* Object identifier for extendedKeyUsage extension
|
||||
*/
|
||||
private static final String EXTENDED_KEY_USAGE_OID = "2.5.29.37";
|
||||
|
||||
/**
|
||||
* Unmarshals a PKCS7 block from its encoded form, parsing the
|
||||
* encoded bytes from the InputStream.
|
||||
@ -178,9 +169,9 @@ public class PKCS7 {
|
||||
private void parse(DerInputStream derin, boolean oldStyle)
|
||||
throws IOException
|
||||
{
|
||||
contentInfo = new ContentInfo(derin, oldStyle);
|
||||
contentType = contentInfo.contentType;
|
||||
DerValue content = contentInfo.getContent();
|
||||
ContentInfo block = new ContentInfo(derin, oldStyle);
|
||||
contentType = block.contentType;
|
||||
DerValue content = block.getContent();
|
||||
|
||||
if (contentType.equals(ContentInfo.SIGNED_DATA_OID)) {
|
||||
parseSignedData(content);
|
||||
@ -189,6 +180,7 @@ public class PKCS7 {
|
||||
parseOldSignedData(content);
|
||||
} else if (contentType.equals(ContentInfo.NETSCAPE_CERT_SEQUENCE_OID)){
|
||||
parseNetscapeCertChain(content);
|
||||
contentInfo = block; // Maybe useless, just do not let it be null
|
||||
} else {
|
||||
throw new ParsingException("content type " + contentType +
|
||||
" not supported.");
|
||||
@ -773,6 +765,128 @@ public class PKCS7 {
|
||||
return this.oldStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a PKCS7 data block.
|
||||
*
|
||||
* @param sigalg signature algorithm to be used
|
||||
* @param sigProvider (optional) provider
|
||||
* @param privateKey signer's private ky
|
||||
* @param signerChain signer's certificate chain
|
||||
* @param content the content to sign
|
||||
* @param internalsf whether the content should be include in output
|
||||
* @param directsign if the content is signed directly or thru authattrs
|
||||
* @param ts (optional) timestamper
|
||||
* @return the pkcs7 output in an array
|
||||
* @throws SignatureException if signing failed
|
||||
* @throws InvalidKeyException if key cannot be used
|
||||
* @throws IOException should not happen here, all byte array
|
||||
* @throws NoSuchAlgorithmException if siglag is bad
|
||||
*/
|
||||
public static byte[] generateNewSignedData(
|
||||
String sigalg, Provider sigProvider,
|
||||
PrivateKey privateKey, X509Certificate[] signerChain,
|
||||
byte[] content, boolean internalsf, boolean directsign,
|
||||
Function<byte[], PKCS9Attributes> ts)
|
||||
throws SignatureException, InvalidKeyException, IOException,
|
||||
NoSuchAlgorithmException {
|
||||
|
||||
Signature signer = SignatureUtil.fromKey(sigalg, privateKey, sigProvider);
|
||||
|
||||
AlgorithmId digAlgID = SignatureUtil.getDigestAlgInPkcs7SignerInfo(
|
||||
signer, sigalg, privateKey, directsign);
|
||||
AlgorithmId sigAlgID = SignatureUtil.fromSignature(signer, privateKey);
|
||||
|
||||
PKCS9Attributes authAttrs = null;
|
||||
if (!directsign) {
|
||||
// MessageDigest
|
||||
byte[] md;
|
||||
String digAlgName = digAlgID.getName();
|
||||
if (digAlgName.equals("SHAKE256") || digAlgName.equals("SHAKE256-LEN")) {
|
||||
// No MessageDigest impl for SHAKE256 yet
|
||||
var shaker = new SHAKE256(64);
|
||||
shaker.update(content, 0, content.length);
|
||||
md = shaker.digest();
|
||||
} else {
|
||||
md = MessageDigest.getInstance(digAlgName)
|
||||
.digest(content);
|
||||
}
|
||||
// CMSAlgorithmProtection (RFC6211)
|
||||
DerOutputStream derAp = new DerOutputStream();
|
||||
DerOutputStream derAlgs = new DerOutputStream();
|
||||
digAlgID.derEncode(derAlgs);
|
||||
DerOutputStream derSigAlg = new DerOutputStream();
|
||||
sigAlgID.derEncode(derSigAlg);
|
||||
derAlgs.writeImplicit((byte)0xA1, derSigAlg);
|
||||
derAp.write(DerValue.tag_Sequence, derAlgs);
|
||||
authAttrs = new PKCS9Attributes(new PKCS9Attribute[]{
|
||||
new PKCS9Attribute(PKCS9Attribute.CONTENT_TYPE_OID,
|
||||
ContentInfo.DATA_OID),
|
||||
new PKCS9Attribute(PKCS9Attribute.SIGNING_TIME_OID,
|
||||
new Date()),
|
||||
new PKCS9Attribute(PKCS9Attribute.CMS_ALGORITHM_PROTECTION_OID,
|
||||
derAp.toByteArray()),
|
||||
new PKCS9Attribute(PKCS9Attribute.MESSAGE_DIGEST_OID,
|
||||
md)
|
||||
});
|
||||
signer.update(authAttrs.getDerEncoding());
|
||||
} else {
|
||||
signer.update(content);
|
||||
}
|
||||
|
||||
byte[] signature = signer.sign();
|
||||
|
||||
return constructToken(signature, signerChain,
|
||||
internalsf ? content : null,
|
||||
authAttrs,
|
||||
ts == null ? null : ts.apply(signature),
|
||||
digAlgID,
|
||||
sigAlgID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assemble a PKCS7 token from its components
|
||||
* @param signature the signature
|
||||
* @param signerChain the signer's certificate chain
|
||||
* @param content (optional) encapsulated content
|
||||
* @param authAttrs (optional) authenticated attributes
|
||||
* @param unauthAttrs (optional) unauthenticated attributes
|
||||
* @param digAlgID digest algorithm identifier
|
||||
* @param encAlgID encryption algorithm identifier
|
||||
* @return the token in a byte array
|
||||
* @throws IOException should not happen here, all byte array
|
||||
*/
|
||||
private static byte[] constructToken(byte[] signature,
|
||||
X509Certificate[] signerChain,
|
||||
byte[] content,
|
||||
PKCS9Attributes authAttrs,
|
||||
PKCS9Attributes unauthAttrs,
|
||||
AlgorithmId digAlgID,
|
||||
AlgorithmId encAlgID)
|
||||
throws IOException {
|
||||
// Create the SignerInfo
|
||||
X500Name issuerName =
|
||||
X500Name.asX500Name(signerChain[0].getIssuerX500Principal());
|
||||
BigInteger serialNumber = signerChain[0].getSerialNumber();
|
||||
SignerInfo signerInfo = new SignerInfo(issuerName, serialNumber,
|
||||
digAlgID, authAttrs,
|
||||
encAlgID,
|
||||
signature, unauthAttrs);
|
||||
|
||||
// Create the PKCS #7 signed data message
|
||||
SignerInfo[] signerInfos = {signerInfo};
|
||||
AlgorithmId[] algorithms = {signerInfo.getDigestAlgorithmId()};
|
||||
// Include or exclude content
|
||||
ContentInfo contentInfo = (content == null)
|
||||
? new ContentInfo(ContentInfo.DATA_OID, null)
|
||||
: new ContentInfo(content);
|
||||
PKCS7 pkcs7 = new PKCS7(algorithms, contentInfo,
|
||||
signerChain, signerInfos);
|
||||
ByteArrayOutputStream p7out = new ByteArrayOutputStream();
|
||||
pkcs7.encodeSignedData(p7out);
|
||||
|
||||
return p7out.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assembles a PKCS #7 signed data message that optionally includes a
|
||||
* signature timestamp.
|
||||
@ -797,6 +911,7 @@ public class PKCS7 {
|
||||
* generating the signature timestamp or while generating the signed
|
||||
* data message.
|
||||
*/
|
||||
@Deprecated(since="16", forRemoval=true)
|
||||
public static byte[] generateSignedData(byte[] signature,
|
||||
X509Certificate[] signerChain,
|
||||
byte[] content,
|
||||
@ -824,34 +939,59 @@ public class PKCS7 {
|
||||
tsToken)});
|
||||
}
|
||||
|
||||
// Create the SignerInfo
|
||||
X500Name issuerName =
|
||||
X500Name.asX500Name(signerChain[0].getIssuerX500Principal());
|
||||
BigInteger serialNumber = signerChain[0].getSerialNumber();
|
||||
String encAlg = AlgorithmId.getEncAlgFromSigAlg(signatureAlgorithm);
|
||||
String digAlg = AlgorithmId.getDigAlgFromSigAlg(signatureAlgorithm);
|
||||
if (digAlg == null) {
|
||||
throw new UnsupportedOperationException("Unable to determine " +
|
||||
"the digest algorithm from the signature algorithm.");
|
||||
return constructToken(signature, signerChain, content,
|
||||
null,
|
||||
unauthAttrs,
|
||||
AlgorithmId.get(SignatureUtil.extractDigestAlgFromDwithE(signatureAlgorithm)),
|
||||
AlgorithmId.get(signatureAlgorithm));
|
||||
}
|
||||
|
||||
/**
|
||||
* Examine the certificate for a Subject Information Access extension
|
||||
* (<a href="http://tools.ietf.org/html/rfc5280">RFC 5280</a>).
|
||||
* The extension's {@code accessMethod} field should contain the object
|
||||
* identifier defined for timestamping: 1.3.6.1.5.5.7.48.3 and its
|
||||
* {@code accessLocation} field should contain an HTTP or HTTPS URL.
|
||||
*
|
||||
* @param tsaCertificate (optional) X.509 certificate for the TSA.
|
||||
* @return An HTTP or HTTPS URI or null if none was found.
|
||||
*/
|
||||
public static URI getTimestampingURI(X509Certificate tsaCertificate) {
|
||||
|
||||
if (tsaCertificate == null) {
|
||||
return null;
|
||||
}
|
||||
SignerInfo signerInfo = new SignerInfo(issuerName, serialNumber,
|
||||
AlgorithmId.get(digAlg), null,
|
||||
AlgorithmId.get(encAlg),
|
||||
signature, unauthAttrs);
|
||||
|
||||
// Create the PKCS #7 signed data message
|
||||
SignerInfo[] signerInfos = {signerInfo};
|
||||
AlgorithmId[] algorithms = {signerInfo.getDigestAlgorithmId()};
|
||||
// Include or exclude content
|
||||
ContentInfo contentInfo = (content == null)
|
||||
? new ContentInfo(ContentInfo.DATA_OID, null)
|
||||
: new ContentInfo(content);
|
||||
PKCS7 pkcs7 = new PKCS7(algorithms, contentInfo,
|
||||
signerChain, signerInfos);
|
||||
ByteArrayOutputStream p7out = new ByteArrayOutputStream();
|
||||
pkcs7.encodeSignedData(p7out);
|
||||
|
||||
return p7out.toByteArray();
|
||||
// Parse the extensions
|
||||
try {
|
||||
byte[] extensionValue = tsaCertificate.getExtensionValue
|
||||
(KnownOIDs.SubjectInfoAccess.value());
|
||||
if (extensionValue == null) {
|
||||
return null;
|
||||
}
|
||||
DerInputStream der = new DerInputStream(extensionValue);
|
||||
der = new DerInputStream(der.getOctetString());
|
||||
DerValue[] derValue = der.getSequence(5);
|
||||
AccessDescription description;
|
||||
GeneralName location;
|
||||
URIName uri;
|
||||
for (int i = 0; i < derValue.length; i++) {
|
||||
description = new AccessDescription(derValue[i]);
|
||||
if (description.getAccessMethod()
|
||||
.equals(ObjectIdentifier.of(KnownOIDs.AD_TimeStamping))) {
|
||||
location = description.getAccessLocation();
|
||||
if (location.getType() == GeneralNameInterface.NAME_URI) {
|
||||
uri = (URIName) location.getName();
|
||||
if (uri.getScheme().equalsIgnoreCase("http") ||
|
||||
uri.getScheme().equalsIgnoreCase("https")) {
|
||||
return uri.getURI();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
// ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -873,7 +1013,7 @@ public class PKCS7 {
|
||||
* @throws CertificateException The exception is thrown if the TSA's
|
||||
* certificate is not permitted for timestamping.
|
||||
*/
|
||||
private static byte[] generateTimestampToken(Timestamper tsa,
|
||||
public static byte[] generateTimestampToken(Timestamper tsa,
|
||||
String tSAPolicyID,
|
||||
String tSADigestAlg,
|
||||
byte[] toBeTimestamped)
|
||||
@ -944,13 +1084,13 @@ public class PKCS7 {
|
||||
"Certificate not included in timestamp token");
|
||||
} else {
|
||||
if (!cert.getCriticalExtensionOIDs().contains(
|
||||
EXTENDED_KEY_USAGE_OID)) {
|
||||
KnownOIDs.extendedKeyUsage.value())) {
|
||||
throw new CertificateException(
|
||||
"Certificate is not valid for timestamping");
|
||||
}
|
||||
List<String> keyPurposes = cert.getExtendedKeyUsage();
|
||||
if (keyPurposes == null ||
|
||||
!keyPurposes.contains(KP_TIMESTAMPING_OID)) {
|
||||
!keyPurposes.contains(KnownOIDs.KP_TimeStamping.value())) {
|
||||
throw new CertificateException(
|
||||
"Certificate is not valid for timestamping");
|
||||
}
|
||||
|
@ -164,6 +164,13 @@ import sun.security.util.*;
|
||||
* <TD>byte[]</TD>
|
||||
* </TR>
|
||||
*
|
||||
* <TR>
|
||||
* <TD>1.2.840.113549.1.9.16.2.52</TD>
|
||||
* <TD>CMSAlgorithmProtection</TD>
|
||||
* <TD>Single-valued</TD>
|
||||
* <TD>byte[]</TD>
|
||||
* </TR>
|
||||
*
|
||||
* </TABLE>
|
||||
*
|
||||
* @author Douglas Hoover
|
||||
@ -176,7 +183,7 @@ public class PKCS9Attribute implements DerEncoder {
|
||||
/**
|
||||
* Array of attribute OIDs defined in PKCS9, by number.
|
||||
*/
|
||||
static final ObjectIdentifier[] PKCS9_OIDS = new ObjectIdentifier[18];
|
||||
static final ObjectIdentifier[] PKCS9_OIDS = new ObjectIdentifier[19];
|
||||
|
||||
private static final Class<?> BYTE_ARRAY_CLASS;
|
||||
|
||||
@ -223,6 +230,9 @@ public class PKCS9Attribute implements DerEncoder {
|
||||
public static final ObjectIdentifier SIGNATURE_TIMESTAMP_TOKEN_OID =
|
||||
PKCS9_OIDS[17] =
|
||||
ObjectIdentifier.of(KnownOIDs.SignatureTimestampToken);
|
||||
public static final ObjectIdentifier CMS_ALGORITHM_PROTECTION_OID =
|
||||
PKCS9_OIDS[18] =
|
||||
ObjectIdentifier.of(KnownOIDs.CMSAlgorithmProtection);
|
||||
|
||||
/**
|
||||
* Acceptable ASN.1 tags for DER encodings of values of PKCS9
|
||||
@ -261,10 +271,11 @@ public class PKCS9Attribute implements DerEncoder {
|
||||
{DerValue.tag_Sequence}, // extensionRequest
|
||||
{DerValue.tag_Sequence}, // SMIMECapability
|
||||
{DerValue.tag_Sequence}, // SigningCertificate
|
||||
{DerValue.tag_Sequence} // SignatureTimestampToken
|
||||
{DerValue.tag_Sequence}, // SignatureTimestampToken
|
||||
{DerValue.tag_Sequence} // CMSAlgorithmProtection
|
||||
};
|
||||
|
||||
private static final Class<?>[] VALUE_CLASSES = new Class<?>[18];
|
||||
private static final Class<?>[] VALUE_CLASSES = new Class<?>[19];
|
||||
|
||||
static {
|
||||
try {
|
||||
@ -292,6 +303,7 @@ public class PKCS9Attribute implements DerEncoder {
|
||||
VALUE_CLASSES[15] = null; // not supported yet
|
||||
VALUE_CLASSES[16] = null; // not supported yet
|
||||
VALUE_CLASSES[17] = BYTE_ARRAY_CLASS; // SignatureTimestampToken
|
||||
VALUE_CLASSES[18] = BYTE_ARRAY_CLASS; // CMSAlgorithmProtection
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new ExceptionInInitializerError(e.toString());
|
||||
}
|
||||
@ -319,7 +331,8 @@ public class PKCS9Attribute implements DerEncoder {
|
||||
true, // ExtensionRequest
|
||||
true, // SMIMECapability - not supported yet
|
||||
true, // SigningCertificate
|
||||
true // SignatureTimestampToken
|
||||
true, // SignatureTimestampToken
|
||||
true, // CMSAlgorithmProtection
|
||||
};
|
||||
|
||||
/**
|
||||
@ -496,6 +509,11 @@ public class PKCS9Attribute implements DerEncoder {
|
||||
case 17: // SignatureTimestampToken attribute
|
||||
value = elems[0].toByteArray();
|
||||
break;
|
||||
|
||||
case 18: // CMSAlgorithmProtection
|
||||
value = elems[0].toByteArray();
|
||||
break;
|
||||
|
||||
default: // can't happen
|
||||
}
|
||||
}
|
||||
@ -623,6 +641,10 @@ public class PKCS9Attribute implements DerEncoder {
|
||||
temp.write(DerValue.tag_Set, (byte[])value);
|
||||
break;
|
||||
|
||||
case 18: // CMSAlgorithmProtection
|
||||
temp.write(DerValue.tag_Set, (byte[])value);
|
||||
break;
|
||||
|
||||
default: // can't happen
|
||||
}
|
||||
|
||||
|
@ -34,27 +34,19 @@ import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.CertPath;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.*;
|
||||
import java.security.spec.PSSParameterSpec;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
|
||||
import sun.security.provider.SHAKE256;
|
||||
import sun.security.timestamp.TimestampToken;
|
||||
import sun.security.util.ConstraintsParameters;
|
||||
import sun.security.util.Debug;
|
||||
import sun.security.util.DerEncoder;
|
||||
import sun.security.util.DerInputStream;
|
||||
import sun.security.util.DerOutputStream;
|
||||
import sun.security.util.DerValue;
|
||||
import sun.security.util.DisabledAlgorithmConstraints;
|
||||
import sun.security.util.HexDumpEncoder;
|
||||
import sun.security.util.KeyUtil;
|
||||
import sun.security.util.ObjectIdentifier;
|
||||
import sun.security.util.*;
|
||||
import sun.security.x509.AlgorithmId;
|
||||
import sun.security.x509.X500Name;
|
||||
import sun.security.x509.KeyUsageExtension;
|
||||
import sun.security.util.SignatureUtil;
|
||||
|
||||
/**
|
||||
* A SignerInfo, as defined in PKCS#7's signedData type.
|
||||
@ -92,12 +84,8 @@ public class SignerInfo implements DerEncoder {
|
||||
AlgorithmId digestAlgorithmId,
|
||||
AlgorithmId digestEncryptionAlgorithmId,
|
||||
byte[] encryptedDigest) {
|
||||
this.version = BigInteger.ONE;
|
||||
this.issuerName = issuerName;
|
||||
this.certificateSerialNumber = serial;
|
||||
this.digestAlgorithmId = digestAlgorithmId;
|
||||
this.digestEncryptionAlgorithmId = digestEncryptionAlgorithmId;
|
||||
this.encryptedDigest = encryptedDigest;
|
||||
this(issuerName, serial, digestAlgorithmId, null,
|
||||
digestEncryptionAlgorithmId, encryptedDigest, null);
|
||||
}
|
||||
|
||||
public SignerInfo(X500Name issuerName,
|
||||
@ -198,6 +186,36 @@ public class SignerInfo implements DerEncoder {
|
||||
if (derin.available() != 0) {
|
||||
throw new ParsingException("extra data at the end");
|
||||
}
|
||||
|
||||
// verify CMSAlgorithmProtection
|
||||
checkCMSAlgorithmProtection();
|
||||
}
|
||||
|
||||
// CMSAlgorithmProtection verification as described in RFC 6211
|
||||
private void checkCMSAlgorithmProtection() throws IOException {
|
||||
if (authenticatedAttributes == null) {
|
||||
return;
|
||||
}
|
||||
PKCS9Attribute ap = authenticatedAttributes.getAttribute(
|
||||
PKCS9Attribute.CMS_ALGORITHM_PROTECTION_OID);
|
||||
if (ap == null) {
|
||||
return;
|
||||
}
|
||||
DerValue dv = new DerValue((byte[])ap.getValue());
|
||||
DerInputStream data = dv.data();
|
||||
AlgorithmId d = AlgorithmId.parse(data.getDerValue());
|
||||
DerValue ds = data.getDerValue();
|
||||
if (data.available() > 0) {
|
||||
throw new IOException("Unknown field in CMSAlgorithmProtection");
|
||||
}
|
||||
if (!ds.isContextSpecific((byte)1)) {
|
||||
throw new IOException("No signature algorithm in CMSAlgorithmProtection");
|
||||
}
|
||||
AlgorithmId s = AlgorithmId.parse(ds.withTag(DerValue.tag_Sequence));
|
||||
if (!s.equals(digestEncryptionAlgorithmId)
|
||||
|| !d.equals(digestAlgorithmId)) {
|
||||
throw new IOException("CMSAlgorithmProtection check failed");
|
||||
}
|
||||
}
|
||||
|
||||
public void encode(DerOutputStream out) throws IOException {
|
||||
@ -327,7 +345,6 @@ public class SignerInfo implements DerEncoder {
|
||||
|
||||
ConstraintsParameters cparams =
|
||||
new ConstraintsParameters(timestamp);
|
||||
String digestAlgname = getDigestAlgorithmId().getName();
|
||||
|
||||
byte[] dataSigned;
|
||||
|
||||
@ -353,6 +370,8 @@ public class SignerInfo implements DerEncoder {
|
||||
if (messageDigest == null) // fail if there is no message digest
|
||||
return null;
|
||||
|
||||
String digestAlgname = digestAlgorithmId.getName();
|
||||
|
||||
// check that digest algorithm is not restricted
|
||||
try {
|
||||
JAR_DISABLED_CHECK.permits(digestAlgname, cparams);
|
||||
@ -360,8 +379,24 @@ public class SignerInfo implements DerEncoder {
|
||||
throw new SignatureException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
MessageDigest md = MessageDigest.getInstance(digestAlgname);
|
||||
byte[] computedMessageDigest = md.digest(data);
|
||||
byte[] computedMessageDigest;
|
||||
if (digestAlgname.equals("SHAKE256")
|
||||
|| digestAlgname.equals("SHAKE256-LEN")) {
|
||||
if (digestAlgname.equals("SHAKE256-LEN")) {
|
||||
int v = new DerValue(digestAlgorithmId
|
||||
.getEncodedParams()).getInteger();
|
||||
if (v != 512) {
|
||||
throw new SignatureException(
|
||||
"Unsupported id-shake256-" + v);
|
||||
}
|
||||
}
|
||||
var md = new SHAKE256(64);
|
||||
md.update(data, 0, data.length);
|
||||
computedMessageDigest = md.digest();
|
||||
} else {
|
||||
MessageDigest md = MessageDigest.getInstance(digestAlgname);
|
||||
computedMessageDigest = md.digest(data);
|
||||
}
|
||||
|
||||
if (messageDigest.length != computedMessageDigest.length)
|
||||
return null;
|
||||
@ -380,16 +415,11 @@ public class SignerInfo implements DerEncoder {
|
||||
}
|
||||
|
||||
// put together digest algorithm and encryption algorithm
|
||||
// to form signing algorithm
|
||||
String encryptionAlgname =
|
||||
getDigestEncryptionAlgorithmId().getName();
|
||||
|
||||
// Workaround: sometimes the encryptionAlgname is actually
|
||||
// a signature name
|
||||
String tmp = AlgorithmId.getEncAlgFromSigAlg(encryptionAlgname);
|
||||
if (tmp != null) encryptionAlgname = tmp;
|
||||
String algname = AlgorithmId.makeSigAlg(
|
||||
digestAlgname, encryptionAlgname);
|
||||
// to form signing algorithm. See makeSigAlg for details.
|
||||
String algname = makeSigAlg(
|
||||
digestAlgorithmId,
|
||||
digestEncryptionAlgorithmId,
|
||||
authenticatedAttributes == null);
|
||||
|
||||
// check that jar signature algorithm is not restricted
|
||||
try {
|
||||
@ -435,11 +465,11 @@ public class SignerInfo implements DerEncoder {
|
||||
+ "extension");
|
||||
}
|
||||
|
||||
boolean digSigAllowed = keyUsage.get(
|
||||
KeyUsageExtension.DIGITAL_SIGNATURE).booleanValue();
|
||||
boolean digSigAllowed
|
||||
= keyUsage.get(KeyUsageExtension.DIGITAL_SIGNATURE);
|
||||
|
||||
boolean nonRepuAllowed = keyUsage.get(
|
||||
KeyUsageExtension.NON_REPUDIATION).booleanValue();
|
||||
boolean nonRepuAllowed
|
||||
= keyUsage.get(KeyUsageExtension.NON_REPUDIATION);
|
||||
|
||||
if (!digSigAllowed && !nonRepuAllowed) {
|
||||
throw new SignatureException("Key usage restricted: "
|
||||
@ -471,6 +501,60 @@ public class SignerInfo implements DerEncoder {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives the signature algorithm name from the digest algorithm
|
||||
* name and the encryption algorithm name inside a PKCS7 SignerInfo.
|
||||
*
|
||||
* For old style PKCS7 files where we use RSA, DSA, EC as encAlgId
|
||||
* a DIGESTwithENC algorithm is returned. For new style RSASSA-PSS
|
||||
* and EdDSA encryption, this method ensures digAlgId is compatible
|
||||
* with the algorithm.
|
||||
*
|
||||
* @param digAlgId the digest algorithm
|
||||
* @param encAlgId the encryption or signature algorithm
|
||||
* @param directSign whether the signature is calculated on the content
|
||||
* directly. This makes difference for Ed448.
|
||||
*/
|
||||
public static String makeSigAlg(AlgorithmId digAlgId, AlgorithmId encAlgId,
|
||||
boolean directSign) throws NoSuchAlgorithmException {
|
||||
String encAlg = encAlgId.getName();
|
||||
if (encAlg.contains("with")) {
|
||||
return encAlg;
|
||||
}
|
||||
switch (encAlg) {
|
||||
case "RSASSA-PSS":
|
||||
PSSParameterSpec spec = (PSSParameterSpec)
|
||||
SignatureUtil.getParamSpec(encAlg, encAlgId.getParameters());
|
||||
if (!AlgorithmId.get(spec.getDigestAlgorithm()).equals(digAlgId)) {
|
||||
throw new NoSuchAlgorithmException("Incompatible digest algorithm");
|
||||
}
|
||||
return encAlg;
|
||||
case "Ed25519":
|
||||
if (!digAlgId.equals(SignatureUtil.EdDSADigestAlgHolder.sha512)) {
|
||||
throw new NoSuchAlgorithmException("Incompatible digest algorithm");
|
||||
}
|
||||
return encAlg;
|
||||
case "Ed448":
|
||||
if (directSign) {
|
||||
if (!digAlgId.equals(SignatureUtil.EdDSADigestAlgHolder.shake256)) {
|
||||
throw new NoSuchAlgorithmException("Incompatible digest algorithm");
|
||||
}
|
||||
} else {
|
||||
if (!digAlgId.equals(SignatureUtil.EdDSADigestAlgHolder.shake256$512)) {
|
||||
throw new NoSuchAlgorithmException("Incompatible digest algorithm");
|
||||
}
|
||||
}
|
||||
return encAlg;
|
||||
default:
|
||||
String digAlg = digAlgId.getName();
|
||||
if (digAlg.startsWith("SHA-")) {
|
||||
digAlg = "SHA" + digAlg.substring(4);
|
||||
}
|
||||
if (encAlg.equals("EC")) encAlg = "ECDSA";
|
||||
return digAlg + "with" + encAlg;
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify the content of the pkcs7 block. */
|
||||
SignerInfo verify(PKCS7 block)
|
||||
throws NoSuchAlgorithmException, SignatureException {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2020, 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
|
||||
@ -30,7 +30,6 @@ import java.io.PrintStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.*;
|
||||
|
||||
import java.util.Base64;
|
||||
@ -189,19 +188,27 @@ public class PKCS10 {
|
||||
* retrieved in either string or binary format.
|
||||
*
|
||||
* @param subject identifies the signer (by X.500 name).
|
||||
* @param signature private key and signing algorithm to use.
|
||||
* @param key private key to use.
|
||||
* @param algorithm signing algorithm to use.
|
||||
* @exception IOException on errors.
|
||||
* @exception CertificateException on certificate handling errors.
|
||||
* @exception SignatureException on signature handling errors.
|
||||
* @exception NoSuchAlgorithmException algorithm is not recognized
|
||||
* @exception InvalidKeyException key has a problem
|
||||
*/
|
||||
public void encodeAndSign(X500Name subject, Signature signature)
|
||||
throws CertificateException, IOException, SignatureException {
|
||||
public void encodeAndSign(X500Name subject, PrivateKey key, String algorithm)
|
||||
throws IOException, SignatureException,
|
||||
NoSuchAlgorithmException, InvalidKeyException {
|
||||
|
||||
DerOutputStream out, scratch;
|
||||
byte[] certificateRequestInfo;
|
||||
byte[] sig;
|
||||
|
||||
if (encoded != null)
|
||||
if (encoded != null) {
|
||||
throw new SignatureException("request is already signed");
|
||||
}
|
||||
|
||||
Signature signature = SignatureUtil.fromKey(
|
||||
algorithm, key, (Provider)null);
|
||||
|
||||
this.subject = subject;
|
||||
|
||||
@ -230,15 +237,7 @@ public class PKCS10 {
|
||||
/*
|
||||
* Build guts of SIGNED macro
|
||||
*/
|
||||
AlgorithmId algId = null;
|
||||
try {
|
||||
AlgorithmParameters params = signature.getParameters();
|
||||
algId = params == null
|
||||
? AlgorithmId.get(signature.getAlgorithm())
|
||||
: AlgorithmId.get(params);
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
throw new SignatureException(nsae);
|
||||
}
|
||||
AlgorithmId algId = SignatureUtil.fromSignature(signature, key);
|
||||
|
||||
algId.encode(scratch); // sig algorithm
|
||||
scratch.putBitString(sig); // sig
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2020, 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
|
||||
@ -30,12 +30,12 @@ import java.security.cert.X509Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.*;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.security.spec.ECGenParameterSpec;
|
||||
import java.security.spec.NamedParameterSpec;
|
||||
import java.util.Date;
|
||||
|
||||
import sun.security.pkcs10.PKCS10;
|
||||
import sun.security.util.SignatureUtil;
|
||||
import sun.security.x509.*;
|
||||
|
||||
/**
|
||||
@ -187,7 +187,7 @@ public final class CertAndKeyGen {
|
||||
}
|
||||
|
||||
if (sigAlg == null) {
|
||||
sigAlg = AlgorithmId.getDefaultSigAlgForKey(privateKey);
|
||||
sigAlg = SignatureUtil.getDefaultSigAlgForKey(privateKey);
|
||||
if (sigAlg == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Cannot derive signature algorithm from "
|
||||
@ -282,8 +282,6 @@ public final class CertAndKeyGen {
|
||||
new CertificateValidity(firstDate,lastDate);
|
||||
|
||||
X509CertInfo info = new X509CertInfo();
|
||||
AlgorithmParameterSpec params = AlgorithmId
|
||||
.getDefaultAlgorithmParameterSpec(sigAlg, privateKey);
|
||||
// Add all mandatory attributes
|
||||
info.set(X509CertInfo.VERSION,
|
||||
new CertificateVersion(CertificateVersion.V3));
|
||||
@ -292,9 +290,6 @@ public final class CertAndKeyGen {
|
||||
}
|
||||
info.set(X509CertInfo.SERIAL_NUMBER,
|
||||
CertificateSerialNumber.newRandom64bit(prng));
|
||||
AlgorithmId algID = AlgorithmId.getWithParameterSpec(sigAlg, params);
|
||||
info.set(X509CertInfo.ALGORITHM_ID,
|
||||
new CertificateAlgorithmId(algID));
|
||||
info.set(X509CertInfo.SUBJECT, myname);
|
||||
info.set(X509CertInfo.KEY, new CertificateX509Key(publicKey));
|
||||
info.set(X509CertInfo.VALIDITY, interval);
|
||||
@ -302,19 +297,13 @@ public final class CertAndKeyGen {
|
||||
if (ext != null) info.set(X509CertInfo.EXTENSIONS, ext);
|
||||
|
||||
cert = new X509CertImpl(info);
|
||||
cert.sign(privateKey,
|
||||
params,
|
||||
sigAlg,
|
||||
null);
|
||||
cert.sign(privateKey, sigAlg);
|
||||
|
||||
return (X509Certificate)cert;
|
||||
return cert;
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new CertificateEncodingException("getSelfCert: " +
|
||||
e.getMessage());
|
||||
} catch (InvalidAlgorithmParameterException e2) {
|
||||
throw new SignatureException(
|
||||
"Unsupported PSSParameterSpec: " + e2.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ -326,44 +315,6 @@ public final class CertAndKeyGen {
|
||||
return getSelfCertificate(myname, new Date(), validity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a PKCS #10 certificate request. The caller uses either
|
||||
* <code>PKCS10.print</code> or <code>PKCS10.toByteArray</code>
|
||||
* operations on the result, to get the request in an appropriate
|
||||
* transmission format.
|
||||
*
|
||||
* <P>PKCS #10 certificate requests are sent, along with some proof
|
||||
* of identity, to Certificate Authorities (CAs) which then issue
|
||||
* X.509 public key certificates.
|
||||
*
|
||||
* @param myname X.500 name of the subject
|
||||
* @exception InvalidKeyException on key handling errors.
|
||||
* @exception SignatureException on signature handling errors.
|
||||
*/
|
||||
// This method is not used inside JDK. Will not update it.
|
||||
public PKCS10 getCertRequest (X500Name myname)
|
||||
throws InvalidKeyException, SignatureException
|
||||
{
|
||||
PKCS10 req = new PKCS10 (publicKey);
|
||||
|
||||
try {
|
||||
Signature signature = Signature.getInstance(sigAlg);
|
||||
signature.initSign (privateKey);
|
||||
req.encodeAndSign(myname, signature);
|
||||
|
||||
} catch (CertificateException e) {
|
||||
throw new SignatureException (sigAlg + " CertificateException");
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new SignatureException (sigAlg + " IOException");
|
||||
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// "can't happen"
|
||||
throw new SignatureException (sigAlg + " unavailable?");
|
||||
}
|
||||
return req;
|
||||
}
|
||||
|
||||
private SecureRandom prng;
|
||||
private String keyType;
|
||||
private String sigAlg;
|
||||
|
@ -28,21 +28,7 @@ package sun.security.tools.keytool;
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.AlgorithmParameters;
|
||||
import java.security.CodeSigner;
|
||||
import java.security.CryptoPrimitive;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.Key;
|
||||
import java.security.PublicKey;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.Signature;
|
||||
import java.security.Timestamp;
|
||||
import java.security.UnrecoverableEntryException;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.Principal;
|
||||
import java.security.*;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.CertStoreException;
|
||||
@ -53,6 +39,7 @@ import java.security.cert.URICertStoreParameters;
|
||||
|
||||
|
||||
import java.security.interfaces.ECKey;
|
||||
import java.security.interfaces.EdECKey;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.security.spec.ECParameterSpec;
|
||||
import java.text.Collator;
|
||||
@ -100,7 +87,6 @@ import sun.security.util.Pem;
|
||||
import sun.security.x509.*;
|
||||
|
||||
import static java.security.KeyStore.*;
|
||||
import java.security.Security;
|
||||
import static sun.security.tools.keytool.Main.Command.*;
|
||||
import static sun.security.tools.keytool.Main.Option.*;
|
||||
import sun.security.util.DisabledAlgorithmConstraints;
|
||||
@ -1449,21 +1435,12 @@ public final class Main {
|
||||
if (sigAlgName == null) {
|
||||
sigAlgName = getCompatibleSigAlgName(privateKey);
|
||||
}
|
||||
Signature signature = Signature.getInstance(sigAlgName);
|
||||
AlgorithmParameterSpec params = AlgorithmId
|
||||
.getDefaultAlgorithmParameterSpec(sigAlgName, privateKey);
|
||||
|
||||
SignatureUtil.initSignWithParam(signature, privateKey, params, null);
|
||||
|
||||
X509CertInfo info = new X509CertInfo();
|
||||
AlgorithmId algID = AlgorithmId.getWithParameterSpec(sigAlgName, params);
|
||||
info.set(X509CertInfo.VALIDITY, interval);
|
||||
info.set(X509CertInfo.SERIAL_NUMBER,
|
||||
CertificateSerialNumber.newRandom64bit(new SecureRandom()));
|
||||
info.set(X509CertInfo.VERSION,
|
||||
new CertificateVersion(CertificateVersion.V3));
|
||||
info.set(X509CertInfo.ALGORITHM_ID,
|
||||
new CertificateAlgorithmId(algID));
|
||||
info.set(X509CertInfo.ISSUER, issuer);
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
|
||||
@ -1507,7 +1484,7 @@ public final class Main {
|
||||
signerCert.getPublicKey());
|
||||
info.set(X509CertInfo.EXTENSIONS, ext);
|
||||
X509CertImpl cert = new X509CertImpl(info);
|
||||
cert.sign(privateKey, params, sigAlgName, null);
|
||||
cert.sign(privateKey, sigAlgName);
|
||||
dumpCert(cert, out);
|
||||
for (Certificate ca: keyStore.getCertificateChain(alias)) {
|
||||
if (ca instanceof X509Certificate) {
|
||||
@ -1608,17 +1585,12 @@ public final class Main {
|
||||
sigAlgName = getCompatibleSigAlgName(privKey);
|
||||
}
|
||||
|
||||
Signature signature = Signature.getInstance(sigAlgName);
|
||||
AlgorithmParameterSpec params = AlgorithmId
|
||||
.getDefaultAlgorithmParameterSpec(sigAlgName, privKey);
|
||||
SignatureUtil.initSignWithParam(signature, privKey, params, null);
|
||||
|
||||
X500Name subject = dname == null?
|
||||
new X500Name(((X509Certificate)cert).getSubjectX500Principal().getEncoded()):
|
||||
new X500Name(dname);
|
||||
|
||||
// Sign the request and base-64 encode it
|
||||
request.encodeAndSign(subject, signature);
|
||||
request.encodeAndSign(subject, privKey, sigAlgName);
|
||||
request.print(out);
|
||||
|
||||
checkWeak(rb.getString("the.generated.certificate.request"), request);
|
||||
@ -1847,7 +1819,7 @@ public final class Main {
|
||||
*/
|
||||
private static String getCompatibleSigAlgName(PrivateKey key)
|
||||
throws Exception {
|
||||
String result = AlgorithmId.getDefaultSigAlgForKey(key);
|
||||
String result = SignatureUtil.getDefaultSigAlgForKey(key);
|
||||
if (result != null) {
|
||||
return result;
|
||||
} else {
|
||||
@ -2537,7 +2509,7 @@ public final class Main {
|
||||
|
||||
private static String verifyCRL(KeyStore ks, CRL crl)
|
||||
throws Exception {
|
||||
X509CRLImpl xcrl = (X509CRLImpl)crl;
|
||||
X509CRL xcrl = (X509CRL)crl;
|
||||
X500Principal issuer = xcrl.getIssuerX500Principal();
|
||||
for (String s: Collections.list(ks.aliases())) {
|
||||
Certificate cert = ks.getCertificate(s);
|
||||
@ -2545,7 +2517,7 @@ public final class Main {
|
||||
X509Certificate xcert = (X509Certificate)cert;
|
||||
if (xcert.getSubjectX500Principal().equals(issuer)) {
|
||||
try {
|
||||
((X509CRLImpl)crl).verify(cert.getPublicKey());
|
||||
((X509CRL)crl).verify(cert.getPublicKey());
|
||||
return s;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
@ -2983,18 +2955,6 @@ public final class Main {
|
||||
certInfo.set(X509CertInfo.ISSUER + "." +
|
||||
X509CertInfo.DN_NAME, owner);
|
||||
|
||||
// The inner and outer signature algorithms have to match.
|
||||
// The way we achieve that is really ugly, but there seems to be no
|
||||
// other solution: We first sign the cert, then retrieve the
|
||||
// outer sigalg and use it to set the inner sigalg
|
||||
X509CertImpl newCert = new X509CertImpl(certInfo);
|
||||
AlgorithmParameterSpec params = AlgorithmId
|
||||
.getDefaultAlgorithmParameterSpec(sigAlgName, privKey);
|
||||
newCert.sign(privKey, params, sigAlgName, null);
|
||||
AlgorithmId sigAlgid = (AlgorithmId)newCert.get(X509CertImpl.SIG_ALG);
|
||||
certInfo.set(CertificateAlgorithmId.NAME + "." +
|
||||
CertificateAlgorithmId.ALGORITHM, sigAlgid);
|
||||
|
||||
certInfo.set(X509CertInfo.VERSION,
|
||||
new CertificateVersion(CertificateVersion.V3));
|
||||
|
||||
@ -3006,8 +2966,8 @@ public final class Main {
|
||||
null);
|
||||
certInfo.set(X509CertInfo.EXTENSIONS, ext);
|
||||
// Sign the new certificate
|
||||
newCert = new X509CertImpl(certInfo);
|
||||
newCert.sign(privKey, params, sigAlgName, null);
|
||||
X509CertImpl newCert = new X509CertImpl(certInfo);
|
||||
newCert.sign(privKey, sigAlgName);
|
||||
|
||||
// Store the new certificate as a single-element certificate chain
|
||||
keyStore.setKeyEntry(alias, privKey,
|
||||
@ -3334,8 +3294,11 @@ public final class Main {
|
||||
if (key instanceof ECKey) {
|
||||
ECParameterSpec paramSpec = ((ECKey) key).getParams();
|
||||
if (paramSpec instanceof NamedCurve) {
|
||||
result += " (" + paramSpec.toString().split(" ")[0] + ")";
|
||||
NamedCurve nc = (NamedCurve)paramSpec;
|
||||
result += " (" + nc.getNameAndAliases()[0] + ")";
|
||||
}
|
||||
} else if (key instanceof EdECKey) {
|
||||
result = ((EdECKey) key).getParams().getName();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -148,6 +148,8 @@ public enum KnownOIDs {
|
||||
HmacSHA3_256("2.16.840.1.101.3.4.2.14", "HmacSHA3-256"),
|
||||
HmacSHA3_384("2.16.840.1.101.3.4.2.15", "HmacSHA3-384"),
|
||||
HmacSHA3_512("2.16.840.1.101.3.4.2.16", "HmacSHA3-512"),
|
||||
SHAKE128_LEN("2.16.840.1.101.3.4.2.17", "SHAKE128-LEN"),
|
||||
SHAKE256_LEN("2.16.840.1.101.3.4.2.18", "SHAKE256-LEN"),
|
||||
|
||||
// sigAlgs 2.16.840.1.101.3.4.3.*
|
||||
SHA224withDSA("2.16.840.1.101.3.4.3.1"),
|
||||
@ -181,7 +183,7 @@ public enum KnownOIDs {
|
||||
OAEP("1.2.840.113549.1.1.7"),
|
||||
MGF1("1.2.840.113549.1.1.8"),
|
||||
PSpecified("1.2.840.113549.1.1.9"),
|
||||
RSASSA_PSS("1.2.840.113549.1.1.10", "RSASSA-PSS"),
|
||||
RSASSA_PSS("1.2.840.113549.1.1.10", "RSASSA-PSS", "PSS"),
|
||||
SHA256withRSA("1.2.840.113549.1.1.11"),
|
||||
SHA384withRSA("1.2.840.113549.1.1.12"),
|
||||
SHA512withRSA("1.2.840.113549.1.1.13"),
|
||||
@ -231,6 +233,7 @@ public enum KnownOIDs {
|
||||
FriendlyName("1.2.840.113549.1.9.20"),
|
||||
LocalKeyID("1.2.840.113549.1.9.21"),
|
||||
CertTypeX509("1.2.840.113549.1.9.22.1"),
|
||||
CMSAlgorithmProtection("1.2.840.113549.1.9.52"),
|
||||
|
||||
// PKCS12 1.2.840.113549.1.12.*
|
||||
PBEWithSHA1AndRC4_128("1.2.840.113549.1.12.1.1"),
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2020, 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
|
||||
@ -31,6 +31,7 @@ import java.security.CodeSigner;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.SignatureException;
|
||||
import java.security.Timestamp;
|
||||
import java.security.cert.CertPath;
|
||||
@ -173,6 +174,7 @@ public class SignatureFileVerifier {
|
||||
* @param s file name
|
||||
* @return true if the input file name is a supported
|
||||
* Signature File or PKCS7 block file name
|
||||
* @see #getBlockExtension(PrivateKey)
|
||||
*/
|
||||
public static boolean isBlockOrSF(String s) {
|
||||
// Note: keep this in sync with j.u.z.ZipFile.Source#isSignatureRelated
|
||||
@ -183,6 +185,26 @@ public class SignatureFileVerifier {
|
||||
|| s.endsWith(".EC");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the signed JAR block file extension for a key.
|
||||
*
|
||||
* @param key the key used to sign the JAR file
|
||||
* @return the extension
|
||||
* @see #isBlockOrSF(String)
|
||||
*/
|
||||
public static String getBlockExtension(PrivateKey key) {
|
||||
String keyAlgorithm = key.getAlgorithm().toUpperCase(Locale.ENGLISH);
|
||||
if (keyAlgorithm.equals("RSASSA-PSS")) {
|
||||
return "RSA";
|
||||
} else if (keyAlgorithm.equals("EDDSA")
|
||||
|| keyAlgorithm.equals("ED25519")
|
||||
|| keyAlgorithm.equals("ED448")) {
|
||||
return "EC";
|
||||
} else {
|
||||
return keyAlgorithm;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Yet another utility method used by JarVerifier and JarSigner
|
||||
* to determine what files are signature related, which includes
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2020, 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
|
||||
@ -27,10 +27,15 @@ package sun.security.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.*;
|
||||
import java.security.interfaces.EdECKey;
|
||||
import java.security.interfaces.EdECPrivateKey;
|
||||
import java.security.interfaces.RSAKey;
|
||||
import java.security.spec.*;
|
||||
import java.util.Locale;
|
||||
|
||||
import sun.security.rsa.RSAUtil;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import sun.security.x509.AlgorithmId;
|
||||
|
||||
/**
|
||||
* Utility class for Signature related operations. Currently used by various
|
||||
@ -41,15 +46,23 @@ import jdk.internal.access.SharedSecrets;
|
||||
*/
|
||||
public class SignatureUtil {
|
||||
|
||||
private static String checkName(String algName) throws ProviderException {
|
||||
/**
|
||||
* Convert OID.1.2.3.4 or 1.2.3.4 to its matching stdName.
|
||||
*
|
||||
* @param algName input, could be in any form
|
||||
* @return the matching stdName, or {@code algName} if it is not in the
|
||||
* form of an OID, or the OID value if no match is found.
|
||||
*/
|
||||
private static String checkName(String algName) {
|
||||
if (algName.indexOf(".") == -1) {
|
||||
return algName;
|
||||
}
|
||||
// convert oid to String
|
||||
try {
|
||||
return Signature.getInstance(algName).getAlgorithm();
|
||||
} catch (Exception e) {
|
||||
throw new ProviderException("Error mapping algorithm name", e);
|
||||
} else {
|
||||
// convert oid to String
|
||||
if (algName.startsWith("OID.")) {
|
||||
algName = algName.substring(4);
|
||||
}
|
||||
KnownOIDs ko = KnownOIDs.findMatch(algName);
|
||||
return ko != null ? ko.stdName() : algName;
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,15 +82,21 @@ public class SignatureUtil {
|
||||
}
|
||||
}
|
||||
|
||||
// Utility method for converting the specified AlgorithmParameters object
|
||||
// into an AlgorithmParameterSpec object.
|
||||
/**
|
||||
* Utility method for converting the specified AlgorithmParameters object
|
||||
* into an AlgorithmParameterSpec object.
|
||||
*
|
||||
* @param sigName signature algorithm
|
||||
* @param params (optional) parameters
|
||||
* @return an AlgorithmParameterSpec, null if {@code params} is null
|
||||
*/
|
||||
public static AlgorithmParameterSpec getParamSpec(String sigName,
|
||||
AlgorithmParameters params)
|
||||
throws ProviderException {
|
||||
|
||||
sigName = checkName(sigName).toUpperCase(Locale.ENGLISH);
|
||||
AlgorithmParameterSpec paramSpec = null;
|
||||
if (params != null) {
|
||||
sigName = checkName(sigName).toUpperCase(Locale.ENGLISH);
|
||||
// AlgorithmParameters.getAlgorithm() may returns oid if it's
|
||||
// created during DER decoding. Convert to use the standard name
|
||||
// before passing it to RSAUtil
|
||||
@ -107,15 +126,21 @@ public class SignatureUtil {
|
||||
return paramSpec;
|
||||
}
|
||||
|
||||
// Utility method for converting the specified parameter bytes into an
|
||||
// AlgorithmParameterSpec object.
|
||||
/**
|
||||
* Utility method for converting the specified parameter bytes
|
||||
* into an AlgorithmParameterSpec object.
|
||||
*
|
||||
* @param sigName signature algorithm
|
||||
* @param paramBytes (optional) parameter bytes
|
||||
* @return an AlgorithmParameterSpec, null if {@code paramBytes} is null
|
||||
*/
|
||||
public static AlgorithmParameterSpec getParamSpec(String sigName,
|
||||
byte[] paramBytes)
|
||||
throws ProviderException {
|
||||
sigName = checkName(sigName).toUpperCase(Locale.ENGLISH);
|
||||
AlgorithmParameterSpec paramSpec = null;
|
||||
|
||||
if (paramBytes != null) {
|
||||
sigName = checkName(sigName).toUpperCase(Locale.ENGLISH);
|
||||
if (sigName.indexOf("RSA") != -1) {
|
||||
AlgorithmParameters params =
|
||||
createAlgorithmParameters(sigName, paramBytes);
|
||||
@ -168,4 +193,342 @@ public class SignatureUtil {
|
||||
InvalidKeyException {
|
||||
SharedSecrets.getJavaSecuritySignatureAccess().initSign(s, key, params, sr);
|
||||
}
|
||||
|
||||
public static class EdDSADigestAlgHolder {
|
||||
public final static AlgorithmId sha512;
|
||||
public final static AlgorithmId shake256;
|
||||
public final static AlgorithmId shake256$512;
|
||||
|
||||
static {
|
||||
try {
|
||||
sha512 = new AlgorithmId(ObjectIdentifier.of(KnownOIDs.SHA_512));
|
||||
shake256 = new AlgorithmId(ObjectIdentifier.of(KnownOIDs.SHAKE256));
|
||||
shake256$512 = new AlgorithmId(
|
||||
ObjectIdentifier.of(KnownOIDs.SHAKE256_LEN),
|
||||
new DerValue((byte) 2, new byte[]{2, 0})); // int 512
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError("Should not happen", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Determines the digestEncryptionAlgorithmId in PKCS7 SignerInfo.
|
||||
*
|
||||
* @param signer Signature object that tells you RSASSA-PSS params
|
||||
* @param sigalg Signature algorithm
|
||||
* @param privateKey key tells you EdDSA params
|
||||
* @param directsign Ed448 uses different digest algs depending on this
|
||||
* @return the digest algId
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
public static AlgorithmId getDigestAlgInPkcs7SignerInfo(
|
||||
Signature signer, String sigalg, PrivateKey privateKey, boolean directsign)
|
||||
throws NoSuchAlgorithmException {
|
||||
AlgorithmId digAlgID;
|
||||
String kAlg = privateKey.getAlgorithm();
|
||||
if (privateKey instanceof EdECPrivateKey
|
||||
|| kAlg.equalsIgnoreCase("Ed25519")
|
||||
|| kAlg.equalsIgnoreCase("Ed448")) {
|
||||
if (privateKey instanceof EdECPrivateKey) {
|
||||
// Note: SunEC's kAlg is EdDSA, find out the real one
|
||||
kAlg = ((EdECPrivateKey) privateKey).getParams().getName();
|
||||
}
|
||||
// https://www.rfc-editor.org/rfc/rfc8419.html#section-3
|
||||
switch (kAlg.toUpperCase(Locale.ENGLISH)) {
|
||||
case "ED25519":
|
||||
digAlgID = EdDSADigestAlgHolder.sha512;
|
||||
break;
|
||||
case "ED448":
|
||||
if (directsign) {
|
||||
digAlgID = EdDSADigestAlgHolder.shake256;
|
||||
} else {
|
||||
digAlgID = EdDSADigestAlgHolder.shake256$512;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Unknown curve name: " + kAlg);
|
||||
}
|
||||
} else {
|
||||
if (sigalg.equalsIgnoreCase("RSASSA-PSS")) {
|
||||
try {
|
||||
digAlgID = AlgorithmId.get(signer.getParameters()
|
||||
.getParameterSpec(PSSParameterSpec.class)
|
||||
.getDigestAlgorithm());
|
||||
} catch (InvalidParameterSpecException e) {
|
||||
throw new AssertionError("Should not happen", e);
|
||||
}
|
||||
} else {
|
||||
digAlgID = AlgorithmId.get(extractDigestAlgFromDwithE(sigalg));
|
||||
}
|
||||
}
|
||||
return digAlgID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the digest algorithm name from a signature
|
||||
* algorithm name in either the "DIGESTwithENCRYPTION" or the
|
||||
* "DIGESTwithENCRYPTIONandWHATEVER" format.
|
||||
*
|
||||
* It's OK to return "SHA1" instead of "SHA-1".
|
||||
*/
|
||||
public static String extractDigestAlgFromDwithE(String signatureAlgorithm) {
|
||||
signatureAlgorithm = signatureAlgorithm.toUpperCase(Locale.ENGLISH);
|
||||
int with = signatureAlgorithm.indexOf("WITH");
|
||||
if (with > 0) {
|
||||
return signatureAlgorithm.substring(0, with);
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"Unknown algorithm: " + signatureAlgorithm);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns default AlgorithmParameterSpec for a key used in a signature.
|
||||
* This is only useful for RSASSA-PSS now, which is the only algorithm
|
||||
* that must be initialized with a AlgorithmParameterSpec now.
|
||||
*/
|
||||
public static AlgorithmParameterSpec getDefaultParamSpec(
|
||||
String sigAlg, Key k) {
|
||||
sigAlg = checkName(sigAlg);
|
||||
if (sigAlg.equalsIgnoreCase("RSASSA-PSS")) {
|
||||
if (k instanceof RSAKey) {
|
||||
AlgorithmParameterSpec spec = ((RSAKey) k).getParams();
|
||||
if (spec instanceof PSSParameterSpec) {
|
||||
return spec;
|
||||
}
|
||||
}
|
||||
switch (ifcFfcStrength(KeyUtil.getKeySize(k))) {
|
||||
case "SHA256":
|
||||
return PSSParamsHolder.PSS_256_SPEC;
|
||||
case "SHA384":
|
||||
return PSSParamsHolder.PSS_384_SPEC;
|
||||
case "SHA512":
|
||||
return PSSParamsHolder.PSS_512_SPEC;
|
||||
default:
|
||||
throw new AssertionError("Should not happen");
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Signature that has been initialized with proper key and params.
|
||||
*
|
||||
* @param sigAlg signature algorithms
|
||||
* @param key public or private key
|
||||
* @param provider (optional) provider
|
||||
*/
|
||||
public static Signature fromKey(String sigAlg, Key key, String provider)
|
||||
throws NoSuchAlgorithmException, NoSuchProviderException,
|
||||
InvalidKeyException{
|
||||
Signature sigEngine = (provider == null || provider.isEmpty())
|
||||
? Signature.getInstance(sigAlg)
|
||||
: Signature.getInstance(sigAlg, provider);
|
||||
return autoInitInternal(sigAlg, key, sigEngine);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Signature that has been initialized with proper key and params.
|
||||
*
|
||||
* @param sigAlg signature algorithms
|
||||
* @param key public or private key
|
||||
* @param provider (optional) provider
|
||||
*/
|
||||
public static Signature fromKey(String sigAlg, Key key, Provider provider)
|
||||
throws NoSuchAlgorithmException, InvalidKeyException{
|
||||
Signature sigEngine = (provider == null)
|
||||
? Signature.getInstance(sigAlg)
|
||||
: Signature.getInstance(sigAlg, provider);
|
||||
return autoInitInternal(sigAlg, key, sigEngine);
|
||||
}
|
||||
|
||||
private static Signature autoInitInternal(String alg, Key key, Signature s)
|
||||
throws InvalidKeyException {
|
||||
AlgorithmParameterSpec params = SignatureUtil
|
||||
.getDefaultParamSpec(alg, key);
|
||||
try {
|
||||
if (key instanceof PrivateKey) {
|
||||
SignatureUtil.initSignWithParam(s, (PrivateKey) key, params,
|
||||
null);
|
||||
} else {
|
||||
SignatureUtil.initVerifyWithParam(s, (PublicKey) key, params);
|
||||
}
|
||||
} catch (InvalidAlgorithmParameterException e) {
|
||||
throw new AssertionError("Should not happen", e);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives AlgorithmId from a signature object and a key.
|
||||
* @param sigEngine the signature object
|
||||
* @param key the private key
|
||||
* @return the AlgorithmId, not null
|
||||
* @throws SignatureException if cannot find one
|
||||
*/
|
||||
public static AlgorithmId fromSignature(Signature sigEngine, PrivateKey key)
|
||||
throws SignatureException {
|
||||
try {
|
||||
if (key instanceof EdECKey) {
|
||||
return AlgorithmId.get(((EdECKey) key).getParams().getName());
|
||||
}
|
||||
|
||||
AlgorithmParameters params = null;
|
||||
try {
|
||||
params = sigEngine.getParameters();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// some provider does not support it
|
||||
}
|
||||
if (params != null) {
|
||||
return AlgorithmId.get(sigEngine.getParameters());
|
||||
} else {
|
||||
String sigAlg = sigEngine.getAlgorithm();
|
||||
if (sigAlg.equalsIgnoreCase("EdDSA")) {
|
||||
// Hopefully key knows if it's Ed25519 or Ed448
|
||||
sigAlg = key.getAlgorithm();
|
||||
}
|
||||
return AlgorithmId.get(sigAlg);
|
||||
}
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// This could happen if both sig alg and key alg is EdDSA,
|
||||
// we don't know which provider does this.
|
||||
throw new SignatureException("Cannot derive AlgorithmIdentifier", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a signature algorithm matches a key, i.e. if this
|
||||
* signature can be initialized with this key. Currently used
|
||||
* in {@link jdk.security.jarsigner.JarSigner} to fail early.
|
||||
*
|
||||
* Note: Unknown signature algorithms are allowed.
|
||||
*
|
||||
* @param key must not be null
|
||||
* @param sAlg must not be null
|
||||
* @throws IllegalArgumentException if they are known to not match
|
||||
*/
|
||||
public static void checkKeyAndSigAlgMatch(PrivateKey key, String sAlg) {
|
||||
String kAlg = key.getAlgorithm().toUpperCase(Locale.ENGLISH);
|
||||
sAlg = checkName(sAlg).toUpperCase(Locale.ENGLISH);
|
||||
switch (sAlg) {
|
||||
case "RSASSA-PSS" -> {
|
||||
if (!kAlg.equals("RSASSA-PSS")
|
||||
&& !kAlg.equals("RSA")) {
|
||||
throw new IllegalArgumentException(
|
||||
"key algorithm not compatible with signature algorithm");
|
||||
}
|
||||
}
|
||||
case "EDDSA" -> {
|
||||
// General EdDSA, any EDDSA name variance is OK
|
||||
if (!kAlg.equals("EDDSA") && !kAlg.equals("ED448")
|
||||
&& !kAlg.equals("ED25519")) {
|
||||
throw new IllegalArgumentException(
|
||||
"key algorithm not compatible with signature algorithm");
|
||||
}
|
||||
}
|
||||
case "ED25519", "ED448" -> {
|
||||
// fix-size EdDSA
|
||||
if (key instanceof EdECKey) {
|
||||
// SunEC's key alg is fix-size. Must match.
|
||||
String groupName = ((EdECKey) key).getParams()
|
||||
.getName().toUpperCase(Locale.US);
|
||||
if (!sAlg.equals(groupName)) {
|
||||
throw new IllegalArgumentException(
|
||||
"key algorithm not compatible with signature algorithm");
|
||||
}
|
||||
} else {
|
||||
// Other vendor might be generalized or fix-size
|
||||
if (!kAlg.equals("EDDSA") && !kAlg.equals(sAlg)) {
|
||||
throw new IllegalArgumentException(
|
||||
"key algorithm not compatible with signature algorithm");
|
||||
}
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
if (sAlg.contains("WITH")) {
|
||||
if ((sAlg.endsWith("WITHRSA") && !kAlg.equals("RSA")) ||
|
||||
(sAlg.endsWith("WITHECDSA") && !kAlg.equals("EC")) ||
|
||||
(sAlg.endsWith("WITHDSA") && !kAlg.equals("DSA"))) {
|
||||
throw new IllegalArgumentException(
|
||||
"key algorithm not compatible with signature algorithm");
|
||||
}
|
||||
}
|
||||
// Do not fail now. Maybe new algorithm we don't know.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default signature algorithm for a private key.
|
||||
*
|
||||
* @param k cannot be null
|
||||
* @return the default alg, might be null if unsupported
|
||||
*/
|
||||
public static String getDefaultSigAlgForKey(PrivateKey k) {
|
||||
String kAlg = k.getAlgorithm();
|
||||
return switch (kAlg.toUpperCase(Locale.ENGLISH)) {
|
||||
case "DSA", "RSA" -> ifcFfcStrength(KeyUtil.getKeySize(k))
|
||||
+ "with" + kAlg;
|
||||
case "EC" -> ecStrength(KeyUtil.getKeySize(k))
|
||||
+ "withECDSA";
|
||||
case "EDDSA" -> k instanceof EdECPrivateKey
|
||||
? ((EdECPrivateKey) k).getParams().getName()
|
||||
: kAlg;
|
||||
case "RSASSA-PSS", "ED25519", "ED448" -> kAlg;
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
// Useful PSSParameterSpec objects
|
||||
private static class PSSParamsHolder {
|
||||
final static PSSParameterSpec PSS_256_SPEC = new PSSParameterSpec(
|
||||
"SHA-256", "MGF1",
|
||||
new MGF1ParameterSpec("SHA-256"),
|
||||
32, PSSParameterSpec.TRAILER_FIELD_BC);
|
||||
final static PSSParameterSpec PSS_384_SPEC = new PSSParameterSpec(
|
||||
"SHA-384", "MGF1",
|
||||
new MGF1ParameterSpec("SHA-384"),
|
||||
48, PSSParameterSpec.TRAILER_FIELD_BC);
|
||||
final static PSSParameterSpec PSS_512_SPEC = new PSSParameterSpec(
|
||||
"SHA-512", "MGF1",
|
||||
new MGF1ParameterSpec("SHA-512"),
|
||||
64, PSSParameterSpec.TRAILER_FIELD_BC);
|
||||
}
|
||||
|
||||
// The following values are from SP800-57 part 1 rev 4 tables 2 and 3
|
||||
|
||||
/**
|
||||
* Return the default message digest algorithm with the same security
|
||||
* strength as the specified EC key size.
|
||||
*
|
||||
* Attention: sync with the @implNote inside
|
||||
* {@link jdk.security.jarsigner.JarSigner.Builder#getDefaultSignatureAlgorithm}.
|
||||
*/
|
||||
private static String ecStrength (int bitLength) {
|
||||
if (bitLength >= 512) { // 256 bits of strength
|
||||
return "SHA512";
|
||||
} else if (bitLength >= 384) { // 192 bits of strength
|
||||
return "SHA384";
|
||||
} else { // 128 bits of strength and less
|
||||
return "SHA256";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default message digest algorithm with the same security
|
||||
* strength as the specified IFC/FFC key size.
|
||||
*
|
||||
* Attention: sync with the @implNote inside
|
||||
* {@link jdk.security.jarsigner.JarSigner.Builder#getDefaultSignatureAlgorithm}.
|
||||
*/
|
||||
private static String ifcFfcStrength (int bitLength) {
|
||||
if (bitLength > 7680) { // 256 bits
|
||||
return "SHA512";
|
||||
} else if (bitLength > 3072) { // 192 bits
|
||||
return "SHA384";
|
||||
} else { // 128 bits and less
|
||||
return "SHA256";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,18 +26,10 @@
|
||||
package sun.security.x509;
|
||||
|
||||
import java.io.*;
|
||||
import java.security.interfaces.RSAKey;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.security.spec.EdDSAParameterSpec;
|
||||
import java.security.spec.InvalidParameterSpecException;
|
||||
import java.security.spec.MGF1ParameterSpec;
|
||||
import java.security.spec.PSSParameterSpec;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.security.*;
|
||||
import java.security.interfaces.*;
|
||||
|
||||
import sun.security.rsa.PSSParameters;
|
||||
import sun.security.util.*;
|
||||
|
||||
|
||||
@ -110,7 +102,7 @@ public class AlgorithmId implements Serializable, DerEncoder {
|
||||
* Constructs an algorithm ID with algorithm parameters.
|
||||
*
|
||||
* @param oid the identifier for the algorithm.
|
||||
* @param algparams the associated algorithm parameters.
|
||||
* @param algparams the associated algorithm parameters, can be null.
|
||||
*/
|
||||
public AlgorithmId(ObjectIdentifier oid, AlgorithmParameters algparams) {
|
||||
algid = oid;
|
||||
@ -118,7 +110,13 @@ public class AlgorithmId implements Serializable, DerEncoder {
|
||||
constructedFromDer = false;
|
||||
}
|
||||
|
||||
private AlgorithmId(ObjectIdentifier oid, DerValue params)
|
||||
/**
|
||||
* Constructs an algorithm ID with algorithm parameters as a DerValue.
|
||||
*
|
||||
* @param oid the identifier for the algorithm.
|
||||
* @param params the associated algorithm parameters, can be null.
|
||||
*/
|
||||
public AlgorithmId(ObjectIdentifier oid, DerValue params)
|
||||
throws IOException {
|
||||
this.algid = oid;
|
||||
this.params = params;
|
||||
@ -270,10 +268,10 @@ public class AlgorithmId implements Serializable, DerEncoder {
|
||||
if (o == KnownOIDs.SpecifiedSHA2withECDSA) {
|
||||
if (params != null) {
|
||||
try {
|
||||
AlgorithmId paramsId =
|
||||
AlgorithmId digestParams =
|
||||
AlgorithmId.parse(new DerValue(params.toByteArray()));
|
||||
String paramsName = paramsId.getName();
|
||||
return makeSigAlg(paramsName, "EC");
|
||||
String digestAlg = digestParams.getName();
|
||||
return digestAlg.replace("-", "") + "withECDSA";
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
@ -668,210 +666,4 @@ public class AlgorithmId implements Serializable, DerEncoder {
|
||||
ObjectIdentifier.of(KnownOIDs.SHA384withECDSA);
|
||||
public static final ObjectIdentifier SHA512withECDSA_oid =
|
||||
ObjectIdentifier.of(KnownOIDs.SHA512withECDSA);
|
||||
|
||||
/**
|
||||
* Creates a signature algorithm name from a digest algorithm
|
||||
* name and a encryption algorithm name.
|
||||
*/
|
||||
public static String makeSigAlg(String digAlg, String encAlg) {
|
||||
digAlg = digAlg.replace("-", "");
|
||||
if (encAlg.equalsIgnoreCase("EC")) encAlg = "ECDSA";
|
||||
|
||||
return digAlg + "with" + encAlg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the encryption algorithm name from a signature
|
||||
* algorithm name.
|
||||
*/
|
||||
public static String getEncAlgFromSigAlg(String signatureAlgorithm) {
|
||||
signatureAlgorithm = signatureAlgorithm.toUpperCase(Locale.ENGLISH);
|
||||
int with = signatureAlgorithm.indexOf("WITH");
|
||||
String keyAlgorithm = null;
|
||||
if (with > 0) {
|
||||
int and = signatureAlgorithm.indexOf("AND", with + 4);
|
||||
if (and > 0) {
|
||||
keyAlgorithm = signatureAlgorithm.substring(with + 4, and);
|
||||
} else {
|
||||
keyAlgorithm = signatureAlgorithm.substring(with + 4);
|
||||
}
|
||||
if (keyAlgorithm.equalsIgnoreCase("ECDSA")) {
|
||||
keyAlgorithm = "EC";
|
||||
}
|
||||
}
|
||||
return keyAlgorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the digest algorithm name from a signature
|
||||
* algorithm name.
|
||||
*/
|
||||
public static String getDigAlgFromSigAlg(String signatureAlgorithm) {
|
||||
signatureAlgorithm = signatureAlgorithm.toUpperCase(Locale.ENGLISH);
|
||||
int with = signatureAlgorithm.indexOf("WITH");
|
||||
if (with > 0) {
|
||||
return signatureAlgorithm.substring(0, with);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a signature algorithm matches a key algorithm, i.e. a
|
||||
* signature can be initialized with a key.
|
||||
*
|
||||
* @param kAlg must not be null
|
||||
* @param sAlg must not be null
|
||||
* @throws IllegalArgumentException if they do not match
|
||||
*/
|
||||
public static void checkKeyAndSigAlgMatch(String kAlg, String sAlg) {
|
||||
String sAlgUp = sAlg.toUpperCase(Locale.US);
|
||||
if ((sAlgUp.endsWith("WITHRSA") && !kAlg.equalsIgnoreCase("RSA")) ||
|
||||
(sAlgUp.endsWith("WITHECDSA") && !kAlg.equalsIgnoreCase("EC")) ||
|
||||
(sAlgUp.endsWith("WITHDSA") && !kAlg.equalsIgnoreCase("DSA"))) {
|
||||
throw new IllegalArgumentException(
|
||||
"key algorithm not compatible with signature algorithm");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default signature algorithm for a private key. The digest
|
||||
* part might evolve with time. Remember to update the spec of
|
||||
* {@link jdk.security.jarsigner.JarSigner.Builder#getDefaultSignatureAlgorithm(PrivateKey)}
|
||||
* if updated.
|
||||
*
|
||||
* @param k cannot be null
|
||||
* @return the default alg, might be null if unsupported
|
||||
*/
|
||||
public static String getDefaultSigAlgForKey(PrivateKey k) {
|
||||
switch (k.getAlgorithm().toUpperCase(Locale.ENGLISH)) {
|
||||
case "EC":
|
||||
return ecStrength(KeyUtil.getKeySize(k))
|
||||
+ "withECDSA";
|
||||
case "DSA":
|
||||
return ifcFfcStrength(KeyUtil.getKeySize(k))
|
||||
+ "withDSA";
|
||||
case "RSA":
|
||||
return ifcFfcStrength(KeyUtil.getKeySize(k))
|
||||
+ "withRSA";
|
||||
case "RSASSA-PSS":
|
||||
return "RSASSA-PSS";
|
||||
case "EDDSA":
|
||||
return edAlgFromKey(k);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Most commonly used PSSParameterSpec and AlgorithmId
|
||||
private static class PSSParamsHolder {
|
||||
|
||||
final static PSSParameterSpec PSS_256_SPEC = new PSSParameterSpec(
|
||||
"SHA-256", "MGF1",
|
||||
new MGF1ParameterSpec("SHA-256"),
|
||||
32, PSSParameterSpec.TRAILER_FIELD_BC);
|
||||
final static PSSParameterSpec PSS_384_SPEC = new PSSParameterSpec(
|
||||
"SHA-384", "MGF1",
|
||||
new MGF1ParameterSpec("SHA-384"),
|
||||
48, PSSParameterSpec.TRAILER_FIELD_BC);
|
||||
final static PSSParameterSpec PSS_512_SPEC = new PSSParameterSpec(
|
||||
"SHA-512", "MGF1",
|
||||
new MGF1ParameterSpec("SHA-512"),
|
||||
64, PSSParameterSpec.TRAILER_FIELD_BC);
|
||||
|
||||
final static AlgorithmId PSS_256_ID;
|
||||
final static AlgorithmId PSS_384_ID;
|
||||
final static AlgorithmId PSS_512_ID;
|
||||
|
||||
static {
|
||||
try {
|
||||
PSS_256_ID = new AlgorithmId(RSASSA_PSS_oid,
|
||||
new DerValue(PSSParameters.getEncoded(PSS_256_SPEC)));
|
||||
PSS_384_ID = new AlgorithmId(RSASSA_PSS_oid,
|
||||
new DerValue(PSSParameters.getEncoded(PSS_384_SPEC)));
|
||||
PSS_512_ID = new AlgorithmId(RSASSA_PSS_oid,
|
||||
new DerValue(PSSParameters.getEncoded(PSS_512_SPEC)));
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError("Should not happen", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static AlgorithmId getWithParameterSpec(String algName,
|
||||
AlgorithmParameterSpec spec) throws NoSuchAlgorithmException {
|
||||
|
||||
if (spec == null) {
|
||||
return AlgorithmId.get(algName);
|
||||
} else if (spec == PSSParamsHolder.PSS_256_SPEC) {
|
||||
return PSSParamsHolder.PSS_256_ID;
|
||||
} else if (spec == PSSParamsHolder.PSS_384_SPEC) {
|
||||
return PSSParamsHolder.PSS_384_ID;
|
||||
} else if (spec == PSSParamsHolder.PSS_512_SPEC) {
|
||||
return PSSParamsHolder.PSS_512_ID;
|
||||
} else if (spec instanceof EdDSAParameterSpec) {
|
||||
return AlgorithmId.get(algName);
|
||||
} else {
|
||||
try {
|
||||
AlgorithmParameters result =
|
||||
AlgorithmParameters.getInstance(algName);
|
||||
result.init(spec);
|
||||
return get(result);
|
||||
} catch (InvalidParameterSpecException | NoSuchAlgorithmException e) {
|
||||
throw new ProviderException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static AlgorithmParameterSpec getDefaultAlgorithmParameterSpec(
|
||||
String sigAlg, PrivateKey k) {
|
||||
if (sigAlg.equalsIgnoreCase("RSASSA-PSS")) {
|
||||
if (k instanceof RSAKey) {
|
||||
AlgorithmParameterSpec spec = ((RSAKey) k).getParams();
|
||||
if (spec instanceof PSSParameterSpec) {
|
||||
return spec;
|
||||
}
|
||||
}
|
||||
switch (ifcFfcStrength(KeyUtil.getKeySize(k))) {
|
||||
case "SHA256":
|
||||
return PSSParamsHolder.PSS_256_SPEC;
|
||||
case "SHA384":
|
||||
return PSSParamsHolder.PSS_384_SPEC;
|
||||
case "SHA512":
|
||||
return PSSParamsHolder.PSS_512_SPEC;
|
||||
default:
|
||||
throw new AssertionError("Should not happen");
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static String edAlgFromKey(PrivateKey k) {
|
||||
if (k instanceof EdECPrivateKey) {
|
||||
EdECPrivateKey edKey = (EdECPrivateKey) k;
|
||||
return edKey.getParams().getName();
|
||||
}
|
||||
return "EdDSA";
|
||||
}
|
||||
|
||||
// Values from SP800-57 part 1 rev 4 tables 2 and 3
|
||||
private static String ecStrength (int bitLength) {
|
||||
if (bitLength >= 512) { // 256 bits of strength
|
||||
return "SHA512";
|
||||
} else if (bitLength >= 384) { // 192 bits of strength
|
||||
return "SHA384";
|
||||
} else { // 128 bits of strength and less
|
||||
return "SHA256";
|
||||
}
|
||||
}
|
||||
|
||||
// Same values for RSA and DSA
|
||||
private static String ifcFfcStrength (int bitLength) {
|
||||
if (bitLength > 7680) { // 256 bits
|
||||
return "SHA512";
|
||||
} else if (bitLength > 3072) { // 192 bits
|
||||
return "SHA384";
|
||||
} else { // 128 bits and less
|
||||
return "SHA256";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,6 @@ import java.security.cert.X509Certificate;
|
||||
import java.security.cert.X509CRLEntry;
|
||||
import java.security.cert.CRLException;
|
||||
import java.security.*;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.util.*;
|
||||
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
@ -457,16 +456,15 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
* @param key the private key used for signing.
|
||||
* @param algorithm the name of the signature algorithm used.
|
||||
*
|
||||
* @exception NoSuchAlgorithmException on unsupported signature
|
||||
* algorithms.
|
||||
* @exception NoSuchAlgorithmException on unsupported signature algorithms.
|
||||
* @exception InvalidKeyException on incorrect key.
|
||||
* @exception NoSuchProviderException on incorrect provider.
|
||||
* @exception SignatureException on signature errors.
|
||||
* @exception CRLException if any mandatory data was omitted.
|
||||
*/
|
||||
public void sign(PrivateKey key, String algorithm)
|
||||
throws CRLException, NoSuchAlgorithmException, InvalidKeyException,
|
||||
NoSuchProviderException, SignatureException {
|
||||
throws CRLException, NoSuchAlgorithmException, InvalidKeyException,
|
||||
NoSuchProviderException, SignatureException {
|
||||
sign(key, algorithm, null);
|
||||
}
|
||||
|
||||
@ -475,41 +473,23 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
*
|
||||
* @param key the private key used for signing.
|
||||
* @param algorithm the name of the signature algorithm used.
|
||||
* @param provider the name of the provider.
|
||||
* @param provider (optional) the name of the provider.
|
||||
*
|
||||
* @exception NoSuchAlgorithmException on unsupported signature
|
||||
* algorithms.
|
||||
* @exception NoSuchAlgorithmException on unsupported signature algorithms.
|
||||
* @exception InvalidKeyException on incorrect key.
|
||||
* @exception NoSuchProviderException on incorrect provider.
|
||||
* @exception SignatureException on signature errors.
|
||||
* @exception CRLException if any mandatory data was omitted.
|
||||
*/
|
||||
public void sign(PrivateKey key, String algorithm, String provider)
|
||||
throws CRLException, NoSuchAlgorithmException, InvalidKeyException,
|
||||
NoSuchProviderException, SignatureException {
|
||||
throws CRLException, NoSuchAlgorithmException, InvalidKeyException,
|
||||
NoSuchProviderException, SignatureException {
|
||||
try {
|
||||
if (readOnly)
|
||||
throw new CRLException("cannot over-write existing CRL");
|
||||
Signature sigEngine = null;
|
||||
if (provider == null || provider.isEmpty())
|
||||
sigEngine = Signature.getInstance(algorithm);
|
||||
else
|
||||
sigEngine = Signature.getInstance(algorithm, provider);
|
||||
|
||||
AlgorithmParameterSpec params = AlgorithmId
|
||||
.getDefaultAlgorithmParameterSpec(algorithm, key);
|
||||
try {
|
||||
SignatureUtil.initSignWithParam(sigEngine, key, params, null);
|
||||
} catch (InvalidAlgorithmParameterException e) {
|
||||
throw new SignatureException(e);
|
||||
}
|
||||
|
||||
if (params != null) {
|
||||
sigAlgId = AlgorithmId.get(sigEngine.getParameters());
|
||||
} else {
|
||||
// in case the name is reset
|
||||
sigAlgId = AlgorithmId.get(sigEngine.getAlgorithm());
|
||||
}
|
||||
Signature sigEngine = SignatureUtil.fromKey(algorithm, key, provider);
|
||||
sigAlgId = SignatureUtil.fromSignature(sigEngine, key);
|
||||
infoSigAlgId = sigAlgId;
|
||||
|
||||
DerOutputStream out = new DerOutputStream();
|
||||
|
@ -34,7 +34,6 @@ import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.security.*;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.security.cert.*;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.*;
|
||||
@ -278,6 +277,9 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
|
||||
* Construct an initialized X509 Certificate. The certificate is stored
|
||||
* in raw form and has to be signed to be useful.
|
||||
*
|
||||
* The ALGORITHM_ID attribute will be rewritten when signed. The initial
|
||||
* value is ignored.
|
||||
*
|
||||
* @param certInfo the X509CertificateInfo which the Certificate is to be
|
||||
* created from.
|
||||
*/
|
||||
@ -510,15 +512,14 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
|
||||
* @param algorithm the name of the signature algorithm used.
|
||||
*
|
||||
* @exception InvalidKeyException on incorrect key.
|
||||
* @exception NoSuchAlgorithmException on unsupported signature
|
||||
* algorithms.
|
||||
* @exception NoSuchAlgorithmException on unsupported signature algorithms.
|
||||
* @exception NoSuchProviderException if there's no default provider.
|
||||
* @exception SignatureException on signature errors.
|
||||
* @exception CertificateException on encoding errors.
|
||||
*/
|
||||
public void sign(PrivateKey key, String algorithm)
|
||||
throws CertificateException, NoSuchAlgorithmException,
|
||||
InvalidKeyException, NoSuchProviderException, SignatureException {
|
||||
throws CertificateException, NoSuchAlgorithmException,
|
||||
InvalidKeyException, NoSuchProviderException, SignatureException {
|
||||
sign(key, algorithm, null);
|
||||
}
|
||||
|
||||
@ -530,79 +531,32 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
|
||||
*
|
||||
* @param key the private key used for signing.
|
||||
* @param algorithm the name of the signature algorithm used.
|
||||
* @param provider the name of the provider.
|
||||
* @param provider (optional) the name of the provider.
|
||||
*
|
||||
* @exception NoSuchAlgorithmException on unsupported signature
|
||||
* algorithms.
|
||||
* @exception NoSuchAlgorithmException on unsupported signature algorithms.
|
||||
* @exception InvalidKeyException on incorrect key.
|
||||
* @exception NoSuchProviderException on incorrect provider.
|
||||
* @exception SignatureException on signature errors.
|
||||
* @exception CertificateException on encoding errors.
|
||||
*/
|
||||
public void sign(PrivateKey key, String algorithm, String provider)
|
||||
throws CertificateException, NoSuchAlgorithmException,
|
||||
InvalidKeyException, NoSuchProviderException, SignatureException {
|
||||
try {
|
||||
sign(key, null, algorithm, provider);
|
||||
} catch (InvalidAlgorithmParameterException e) {
|
||||
// should not happen; re-throw just in case
|
||||
throw new SignatureException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an X.509 certificate, and signs it using the given key
|
||||
* (associating a signature algorithm and an X.500 name), signature
|
||||
* parameters, and security provider. If the given provider name
|
||||
* is null or empty, the implementation look up will be based on
|
||||
* provider configurations.
|
||||
* This operation is used to implement the certificate generation
|
||||
* functionality of a certificate authority.
|
||||
*
|
||||
* @param key the private key used for signing
|
||||
* @param signingParams the parameters used for signing
|
||||
* @param algorithm the name of the signature algorithm used
|
||||
* @param provider the name of the provider, may be null
|
||||
*
|
||||
* @exception NoSuchAlgorithmException on unsupported signature
|
||||
* algorithms
|
||||
* @exception InvalidKeyException on incorrect key
|
||||
* @exception InvalidAlgorithmParameterException on invalid signature
|
||||
* parameters
|
||||
* @exception NoSuchProviderException on incorrect provider
|
||||
* @exception SignatureException on signature errors
|
||||
* @exception CertificateException on encoding errors
|
||||
*/
|
||||
public void sign(PrivateKey key, AlgorithmParameterSpec signingParams,
|
||||
String algorithm, String provider)
|
||||
throws CertificateException, NoSuchAlgorithmException,
|
||||
InvalidKeyException, InvalidAlgorithmParameterException,
|
||||
NoSuchProviderException, SignatureException {
|
||||
InvalidKeyException, NoSuchProviderException, SignatureException {
|
||||
try {
|
||||
if (readOnly) {
|
||||
throw new CertificateEncodingException(
|
||||
"cannot over-write existing certificate");
|
||||
}
|
||||
Signature sigEngine = null;
|
||||
if (provider == null || provider.isEmpty()) {
|
||||
sigEngine = Signature.getInstance(algorithm);
|
||||
} else {
|
||||
sigEngine = Signature.getInstance(algorithm, provider);
|
||||
}
|
||||
Signature sigEngine = SignatureUtil.fromKey(
|
||||
algorithm, key, provider);
|
||||
algId = SignatureUtil.fromSignature(sigEngine, key);
|
||||
|
||||
SignatureUtil.initSignWithParam(sigEngine, key, signingParams,
|
||||
null);
|
||||
|
||||
if (signingParams != null) {
|
||||
algId = AlgorithmId.get(sigEngine.getParameters());
|
||||
} else {
|
||||
// in case the name is reset
|
||||
algId = AlgorithmId.get(sigEngine.getAlgorithm());
|
||||
}
|
||||
DerOutputStream out = new DerOutputStream();
|
||||
DerOutputStream tmp = new DerOutputStream();
|
||||
|
||||
// encode certificate info
|
||||
info.set(X509CertInfo.ALGORITHM_ID,
|
||||
new CertificateAlgorithmId(algId));
|
||||
info.encode(tmp);
|
||||
byte[] rawCert = tmp.toByteArray();
|
||||
|
||||
@ -621,7 +575,7 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new CertificateEncodingException(e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -29,11 +29,16 @@ import com.sun.jarsigner.ContentSigner;
|
||||
import com.sun.jarsigner.ContentSignerParameters;
|
||||
import jdk.internal.access.JavaUtilZipFileAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import sun.security.pkcs.PKCS7;
|
||||
import sun.security.pkcs.PKCS9Attribute;
|
||||
import sun.security.pkcs.PKCS9Attributes;
|
||||
import sun.security.timestamp.HttpTimestamper;
|
||||
import sun.security.tools.PathList;
|
||||
import sun.security.tools.jarsigner.TimestampedSigner;
|
||||
import sun.security.util.Event;
|
||||
import sun.security.util.ManifestDigester;
|
||||
import sun.security.util.SignatureFileVerifier;
|
||||
import sun.security.util.SignatureUtil;
|
||||
import sun.security.x509.AlgorithmId;
|
||||
|
||||
import java.io.*;
|
||||
@ -47,8 +52,10 @@ import java.security.cert.CertPath;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.spec.InvalidParameterSpecException;
|
||||
import java.util.*;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
@ -113,8 +120,9 @@ public final class JarSigner {
|
||||
// Implementation-specific properties:
|
||||
String tSAPolicyID;
|
||||
String tSADigestAlg;
|
||||
boolean signManifest = true;
|
||||
boolean externalSF = true;
|
||||
boolean sectionsonly = false;
|
||||
boolean internalsf = false;
|
||||
boolean directsign = false;
|
||||
String altSignerPath;
|
||||
String altSigner;
|
||||
|
||||
@ -236,8 +244,7 @@ public final class JarSigner {
|
||||
throws NoSuchAlgorithmException {
|
||||
// Check availability
|
||||
Signature.getInstance(Objects.requireNonNull(algorithm));
|
||||
AlgorithmId.checkKeyAndSigAlgMatch(
|
||||
privateKey.getAlgorithm(), algorithm);
|
||||
SignatureUtil.checkKeyAndSigAlgMatch(privateKey, algorithm);
|
||||
this.sigalg = algorithm;
|
||||
this.sigProvider = null;
|
||||
return this;
|
||||
@ -267,8 +274,7 @@ public final class JarSigner {
|
||||
Signature.getInstance(
|
||||
Objects.requireNonNull(algorithm),
|
||||
Objects.requireNonNull(provider));
|
||||
AlgorithmId.checkKeyAndSigAlgMatch(
|
||||
privateKey.getAlgorithm(), algorithm);
|
||||
SignatureUtil.checkKeyAndSigAlgMatch(privateKey, algorithm);
|
||||
this.sigalg = algorithm;
|
||||
this.sigProvider = provider;
|
||||
return this;
|
||||
@ -352,6 +358,10 @@ public final class JarSigner {
|
||||
* <li>"sectionsonly": "true" if the .SF file only contains the hash
|
||||
* value for each section of the manifest and not for the whole
|
||||
* manifest, "false" otherwise. Default "false".
|
||||
* <li>"directsign": "true" if the signature is calculated on the
|
||||
* content directly, "false" if it's calculated on signed attributes
|
||||
* which itself is calculated from the content and stored in the
|
||||
* signer's SignerInfo. Default "false".
|
||||
* </ul>
|
||||
* All property names are case-insensitive.
|
||||
*
|
||||
@ -380,30 +390,13 @@ public final class JarSigner {
|
||||
this.tSAPolicyID = value;
|
||||
break;
|
||||
case "internalsf":
|
||||
switch (value) {
|
||||
case "true":
|
||||
externalSF = false;
|
||||
break;
|
||||
case "false":
|
||||
externalSF = true;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid internalsf value");
|
||||
}
|
||||
this.internalsf = parseBoolean("interalsf", value);
|
||||
break;
|
||||
case "sectionsonly":
|
||||
switch (value) {
|
||||
case "true":
|
||||
signManifest = false;
|
||||
break;
|
||||
case "false":
|
||||
signManifest = true;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid signManifest value");
|
||||
}
|
||||
this.sectionsonly = parseBoolean("sectionsonly", value);
|
||||
break;
|
||||
case "directsign":
|
||||
this.directsign = parseBoolean("directsign", value);
|
||||
break;
|
||||
case "altsignerpath":
|
||||
altSignerPath = value;
|
||||
@ -418,6 +411,18 @@ public final class JarSigner {
|
||||
return this;
|
||||
}
|
||||
|
||||
private static boolean parseBoolean(String name, String value) {
|
||||
switch (value) {
|
||||
case "true":
|
||||
return true;
|
||||
case "false":
|
||||
return false;
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid " + name + " value");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default digest algorithm.
|
||||
*
|
||||
@ -453,7 +458,9 @@ public final class JarSigner {
|
||||
* will throw an {@link IllegalArgumentException}.
|
||||
*/
|
||||
public static String getDefaultSignatureAlgorithm(PrivateKey key) {
|
||||
return AlgorithmId.getDefaultSigAlgForKey(Objects.requireNonNull(key));
|
||||
// Attention: sync the spec with SignatureUtil::ecStrength and
|
||||
// SignatureUtil::ifcFfcStrength.
|
||||
return SignatureUtil.getDefaultSigAlgForKey(Objects.requireNonNull(key));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -501,9 +508,13 @@ public final class JarSigner {
|
||||
// Implementation-specific properties:
|
||||
private final String tSAPolicyID;
|
||||
private final String tSADigestAlg;
|
||||
private final boolean signManifest; // "sign" the whole manifest
|
||||
private final boolean externalSF; // leave the .SF out of the PKCS7 block
|
||||
private final boolean sectionsonly; // do not "sign" the whole manifest
|
||||
private final boolean internalsf; // include the .SF inside the PKCS7 block
|
||||
private final boolean directsign;
|
||||
|
||||
@Deprecated(since="16", forRemoval=true)
|
||||
private final String altSignerPath;
|
||||
@Deprecated(since="16", forRemoval=true)
|
||||
private final String altSigner;
|
||||
private boolean extraAttrsDetected;
|
||||
|
||||
@ -545,10 +556,14 @@ public final class JarSigner {
|
||||
this.tSADigestAlg = Builder.getDefaultDigestAlgorithm();
|
||||
}
|
||||
this.tSAPolicyID = builder.tSAPolicyID;
|
||||
this.signManifest = builder.signManifest;
|
||||
this.externalSF = builder.externalSF;
|
||||
this.sectionsonly = builder.sectionsonly;
|
||||
this.internalsf = builder.internalsf;
|
||||
this.altSigner = builder.altSigner;
|
||||
this.altSignerPath = builder.altSignerPath;
|
||||
|
||||
this.directsign = this.altSigner != null
|
||||
? true
|
||||
: builder.directsign;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -574,7 +589,8 @@ public final class JarSigner {
|
||||
throw new JarSignerException("Error applying timestamp", e);
|
||||
} catch (IOException ioe) {
|
||||
throw new JarSignerException("I/O error", ioe);
|
||||
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
|
||||
} catch (NoSuchAlgorithmException | InvalidKeyException
|
||||
| InvalidParameterSpecException e) {
|
||||
throw new JarSignerException("Error in signer materials", e);
|
||||
} catch (SignatureException se) {
|
||||
throw new JarSignerException("Error creating signature", se);
|
||||
@ -645,11 +661,13 @@ public final class JarSigner {
|
||||
case "tsapolicyid":
|
||||
return tSAPolicyID;
|
||||
case "internalsf":
|
||||
return Boolean.toString(!externalSF);
|
||||
return Boolean.toString(internalsf);
|
||||
case "sectionsonly":
|
||||
return Boolean.toString(!signManifest);
|
||||
return Boolean.toString(sectionsonly);
|
||||
case "altsignerpath":
|
||||
return altSignerPath;
|
||||
case "directsign":
|
||||
return Boolean.toString(directsign);
|
||||
case "altsigner":
|
||||
return altSigner;
|
||||
default:
|
||||
@ -660,7 +678,7 @@ public final class JarSigner {
|
||||
|
||||
private void sign0(ZipFile zipFile, OutputStream os)
|
||||
throws IOException, CertificateException, NoSuchAlgorithmException,
|
||||
SignatureException, InvalidKeyException {
|
||||
SignatureException, InvalidKeyException, InvalidParameterSpecException {
|
||||
MessageDigest[] digests;
|
||||
try {
|
||||
digests = new MessageDigest[digestalg.length];
|
||||
@ -829,39 +847,70 @@ public final class JarSigner {
|
||||
// Calculate SignatureFile (".SF") and SignatureBlockFile
|
||||
ManifestDigester manDig = new ManifestDigester(mfRawBytes);
|
||||
SignatureFile sf = new SignatureFile(digests, manifest, manDig,
|
||||
signerName, signManifest);
|
||||
signerName, sectionsonly);
|
||||
|
||||
byte[] block;
|
||||
|
||||
Signature signer;
|
||||
if (sigProvider == null ) {
|
||||
signer = Signature.getInstance(sigalg);
|
||||
} else {
|
||||
signer = Signature.getInstance(sigalg, sigProvider);
|
||||
}
|
||||
signer.initSign(privateKey);
|
||||
|
||||
baos.reset();
|
||||
sf.write(baos);
|
||||
byte[] content = baos.toByteArray();
|
||||
|
||||
signer.update(content);
|
||||
byte[] signature = signer.sign();
|
||||
// Use new method if directSign is false or it's a modern
|
||||
// algorithm not supported by existing ContentSigner.
|
||||
// Make this always true after we remove ContentSigner.
|
||||
boolean useNewMethod = !directsign
|
||||
|| !sigalg.toUpperCase(Locale.ENGLISH).contains("WITH");
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
ContentSigner signingMechanism = null;
|
||||
if (altSigner != null) {
|
||||
signingMechanism = loadSigningMechanism(altSigner,
|
||||
altSignerPath);
|
||||
// For newer sigalg without "with", always use the new PKCS7
|
||||
// generateToken method. Otherwise, use deprecated ContentSigner.
|
||||
if (useNewMethod) {
|
||||
if (altSigner != null) {
|
||||
throw new IllegalArgumentException(directsign
|
||||
? ("Customized ContentSigner is not supported for " + sigalg)
|
||||
: "Customized ContentSigner does not support authenticated attributes");
|
||||
}
|
||||
Function<byte[], PKCS9Attributes> timestamper = null;
|
||||
if (tsaUrl != null) {
|
||||
timestamper = s -> {
|
||||
try {
|
||||
// Timestamp the signature
|
||||
HttpTimestamper tsa = new HttpTimestamper(tsaUrl);
|
||||
byte[] tsToken = PKCS7.generateTimestampToken(
|
||||
tsa, tSAPolicyID, tSADigestAlg, s);
|
||||
|
||||
return new PKCS9Attributes(new PKCS9Attribute[]{
|
||||
new PKCS9Attribute(
|
||||
PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_OID,
|
||||
tsToken)});
|
||||
} catch (IOException | CertificateException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
// We now create authAttrs in block data, so "direct == false".
|
||||
block = PKCS7.generateNewSignedData(sigalg, sigProvider, privateKey, certChain,
|
||||
content, internalsf, directsign, timestamper);
|
||||
} else {
|
||||
Signature signer = SignatureUtil.fromKey(sigalg, privateKey, sigProvider);
|
||||
signer.update(content);
|
||||
byte[] signature = signer.sign();
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
ContentSignerParameters params =
|
||||
new JarSignerParameters(null, tsaUrl, tSAPolicyID,
|
||||
tSADigestAlg, signature,
|
||||
signer.getAlgorithm(), certChain, content, zipFile);
|
||||
@SuppressWarnings("removal")
|
||||
ContentSigner signingMechanism = (altSigner != null)
|
||||
? loadSigningMechanism(altSigner, altSignerPath)
|
||||
: new TimestampedSigner();
|
||||
block = signingMechanism.generateSignedData(
|
||||
params,
|
||||
!internalsf,
|
||||
params.getTimestampingAuthority() != null
|
||||
|| params.getTimestampingAuthorityCertificate() != null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
ContentSignerParameters params =
|
||||
new JarSignerParameters(null, tsaUrl, tSAPolicyID,
|
||||
tSADigestAlg, signature,
|
||||
signer.getAlgorithm(), certChain, content, zipFile);
|
||||
block = sf.generateBlock(params, externalSF, signingMechanism);
|
||||
|
||||
String sfFilename = sf.getMetaName();
|
||||
String bkFilename = sf.getBlockName(privateKey);
|
||||
|
||||
@ -1121,7 +1170,7 @@ public final class JarSigner {
|
||||
Manifest mf,
|
||||
ManifestDigester md,
|
||||
String baseName,
|
||||
boolean signManifest) {
|
||||
boolean sectionsonly) {
|
||||
|
||||
this.baseName = baseName;
|
||||
|
||||
@ -1134,7 +1183,7 @@ public final class JarSigner {
|
||||
mattr.putValue(Attributes.Name.SIGNATURE_VERSION.toString(), "1.0");
|
||||
mattr.putValue("Created-By", version + " (" + javaVendor + ")");
|
||||
|
||||
if (signManifest) {
|
||||
if (!sectionsonly) {
|
||||
for (MessageDigest digest: digests) {
|
||||
mattr.putValue(digest.getAlgorithm() + "-Digest-Manifest",
|
||||
Base64.getEncoder().encodeToString(
|
||||
@ -1188,30 +1237,13 @@ public final class JarSigner {
|
||||
|
||||
// get .DSA (or .DSA, .EC) file name
|
||||
public String getBlockName(PrivateKey privateKey) {
|
||||
String keyAlgorithm = privateKey.getAlgorithm();
|
||||
return getBaseSignatureFilesName(baseName) + keyAlgorithm;
|
||||
}
|
||||
|
||||
// Generates the PKCS#7 content of block file
|
||||
@SuppressWarnings("removal")
|
||||
public byte[] generateBlock(ContentSignerParameters params,
|
||||
boolean externalSF,
|
||||
ContentSigner signingMechanism)
|
||||
throws NoSuchAlgorithmException,
|
||||
IOException, CertificateException {
|
||||
|
||||
if (signingMechanism == null) {
|
||||
signingMechanism = new TimestampedSigner();
|
||||
}
|
||||
return signingMechanism.generateSignedData(
|
||||
params,
|
||||
externalSF,
|
||||
params.getTimestampingAuthority() != null
|
||||
|| params.getTimestampingAuthorityCertificate() != null);
|
||||
String type = SignatureFileVerifier.getBlockExtension(privateKey);
|
||||
return getBaseSignatureFilesName(baseName) + type;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
@Deprecated(since="16", forRemoval=true)
|
||||
class JarSignerParameters implements ContentSignerParameters {
|
||||
|
||||
private String[] args;
|
||||
|
@ -163,6 +163,7 @@ public class Main {
|
||||
boolean debug = false; // debug
|
||||
boolean signManifest = true; // "sign" the whole manifest
|
||||
boolean externalSF = true; // leave the .SF out of the PKCS7 block
|
||||
boolean directSign = false; // sign SF directly or thru signedAttrs
|
||||
boolean strict = false; // treat warnings as error
|
||||
boolean revocationCheck = false; // Revocation check flag
|
||||
|
||||
@ -472,6 +473,8 @@ public class Main {
|
||||
signManifest = false;
|
||||
} else if (collator.compare(flags, "-internalsf") ==0) {
|
||||
externalSF = false;
|
||||
} else if (collator.compare(flags, "-directsign") ==0) {
|
||||
directSign = true;
|
||||
} else if (collator.compare(flags, "-verify") ==0) {
|
||||
verify = true;
|
||||
} else if (collator.compare(flags, "-verbose") ==0) {
|
||||
@ -660,6 +663,9 @@ public class Main {
|
||||
System.out.println(rb.getString
|
||||
(".internalsf.include.the.SF.file.inside.the.signature.block"));
|
||||
System.out.println();
|
||||
System.out.println(rb.getString
|
||||
(".directsign.sign.the.SF.file.directly.no.signerinfo.signedattributes"));
|
||||
System.out.println();
|
||||
System.out.println(rb.getString
|
||||
(".sectionsonly.don.t.compute.hash.of.entire.manifest"));
|
||||
System.out.println();
|
||||
@ -955,9 +961,10 @@ public class Main {
|
||||
SignerInfo si = p7.getSignerInfos()[0];
|
||||
X509Certificate signer = si.getCertificate(p7);
|
||||
String digestAlg = digestMap.get(s);
|
||||
String sigAlg = AlgorithmId.makeSigAlg(
|
||||
si.getDigestAlgorithmId().getName(),
|
||||
si.getDigestEncryptionAlgorithmId().getName());
|
||||
String sigAlg = SignerInfo.makeSigAlg(
|
||||
si.getDigestAlgorithmId(),
|
||||
si.getDigestEncryptionAlgorithmId(),
|
||||
si.getAuthenticatedAttributes() == null);
|
||||
PublicKey key = signer.getPublicKey();
|
||||
PKCS7 tsToken = si.getTsToken();
|
||||
if (tsToken != null) {
|
||||
@ -968,9 +975,10 @@ public class Main {
|
||||
TimestampToken tsTokenInfo = new TimestampToken(encTsTokenInfo);
|
||||
PublicKey tsKey = tsSigner.getPublicKey();
|
||||
String tsDigestAlg = tsTokenInfo.getHashAlgorithm().getName();
|
||||
String tsSigAlg = AlgorithmId.makeSigAlg(
|
||||
tsSi.getDigestAlgorithmId().getName(),
|
||||
tsSi.getDigestEncryptionAlgorithmId().getName());
|
||||
String tsSigAlg = SignerInfo.makeSigAlg(
|
||||
tsSi.getDigestAlgorithmId(),
|
||||
tsSi.getDigestEncryptionAlgorithmId(),
|
||||
tsSi.getAuthenticatedAttributes() == null);
|
||||
Calendar c = Calendar.getInstance(
|
||||
TimeZone.getTimeZone("UTC"),
|
||||
Locale.getDefault(Locale.Category.FORMAT));
|
||||
@ -1598,7 +1606,7 @@ public class Main {
|
||||
|
||||
/**
|
||||
* Maps certificates (as keys) to alias names associated in the keystore
|
||||
* {@link #store} (as values).
|
||||
* {@link #keystore} (as values).
|
||||
*/
|
||||
Hashtable<Certificate, String> storeHash = new Hashtable<>();
|
||||
|
||||
@ -1725,7 +1733,7 @@ public class Main {
|
||||
tsaURI = new URI(tsaUrl);
|
||||
} else if (tsaAlias != null) {
|
||||
tsaCert = getTsaCert(tsaAlias);
|
||||
tsaURI = TimestampedSigner.getTimestampingURI(tsaCert);
|
||||
tsaURI = PKCS7.getTimestampingURI(tsaCert);
|
||||
}
|
||||
|
||||
if (tsaURI != null) {
|
||||
@ -1765,6 +1773,7 @@ public class Main {
|
||||
|
||||
builder.setProperty("sectionsOnly", Boolean.toString(!signManifest));
|
||||
builder.setProperty("internalSF", Boolean.toString(!externalSF));
|
||||
builder.setProperty("directsign", Boolean.toString(directSign));
|
||||
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
@ -1830,7 +1839,8 @@ public class Main {
|
||||
// validate it.
|
||||
try (JarFile check = new JarFile(signedJarFile)) {
|
||||
PKCS7 p7 = new PKCS7(check.getInputStream(check.getEntry(
|
||||
"META-INF/" + sigfile + "." + privateKey.getAlgorithm())));
|
||||
"META-INF/" + sigfile + "."
|
||||
+ SignatureFileVerifier.getBlockExtension(privateKey))));
|
||||
Timestamp ts = null;
|
||||
try {
|
||||
SignerInfo si = p7.getSignerInfos()[0];
|
||||
|
@ -101,6 +101,8 @@ public class Resources extends java.util.ListResourceBundle {
|
||||
" (This option is deprecated and will be removed in a future release.)"},
|
||||
{".internalsf.include.the.SF.file.inside.the.signature.block",
|
||||
"[-internalsf] include the .SF file inside the signature block"},
|
||||
{".directsign.sign.the.SF.file.directly.no.signerinfo.signedattributes",
|
||||
"[-directsign] sign the .SF file directly (no SignerInfo signedAttributes)"},
|
||||
{".sectionsonly.don.t.compute.hash.of.entire.manifest",
|
||||
"[-sectionsonly] don't compute hash of entire manifest"},
|
||||
{".protected.keystore.has.protected.authentication.path",
|
||||
|
@ -33,8 +33,6 @@ import java.security.cert.X509Certificate;
|
||||
|
||||
import com.sun.jarsigner.*;
|
||||
import sun.security.pkcs.PKCS7;
|
||||
import sun.security.util.*;
|
||||
import sun.security.x509.*;
|
||||
|
||||
/**
|
||||
* This class implements a content signing service.
|
||||
@ -45,15 +43,10 @@ import sun.security.x509.*;
|
||||
*
|
||||
* @author Vincent Ryan
|
||||
*/
|
||||
@Deprecated(since="16", forRemoval=true)
|
||||
@SuppressWarnings("removal")
|
||||
public final class TimestampedSigner extends ContentSigner {
|
||||
|
||||
/*
|
||||
* Object identifier for the timestamping access descriptors.
|
||||
*/
|
||||
private static final ObjectIdentifier AD_TIMESTAMPING_Id =
|
||||
ObjectIdentifier.of(KnownOIDs.AD_TimeStamping);
|
||||
|
||||
/**
|
||||
* Instantiates a content signer that supports timestamped signatures.
|
||||
*/
|
||||
@ -93,12 +86,6 @@ public final class TimestampedSigner extends ContentSigner {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
// Parse the signature algorithm to extract the digest
|
||||
// algorithm. The expected format is:
|
||||
// "<digest>with<encryption>"
|
||||
// or "<digest>with<encryption>and<mgf>"
|
||||
String signatureAlgorithm = params.getSignatureAlgorithm();
|
||||
|
||||
X509Certificate[] signerChain = params.getSignerCertificateChain();
|
||||
byte[] signature = params.getSignature();
|
||||
|
||||
@ -110,7 +97,7 @@ public final class TimestampedSigner extends ContentSigner {
|
||||
tsaURI = params.getTimestampingAuthority();
|
||||
if (tsaURI == null) {
|
||||
// Examine TSA cert
|
||||
tsaURI = getTimestampingURI(
|
||||
tsaURI = PKCS7.getTimestampingURI(
|
||||
params.getTimestampingAuthorityCertificate());
|
||||
if (tsaURI == null) {
|
||||
throw new CertificateException(
|
||||
@ -123,52 +110,4 @@ public final class TimestampedSigner extends ContentSigner {
|
||||
params.getTSAPolicyID(),
|
||||
params.getTSADigestAlg());
|
||||
}
|
||||
|
||||
/**
|
||||
* Examine the certificate for a Subject Information Access extension
|
||||
* (<a href="http://tools.ietf.org/html/rfc5280">RFC 5280</a>).
|
||||
* The extension's {@code accessMethod} field should contain the object
|
||||
* identifier defined for timestamping: 1.3.6.1.5.5.7.48.3 and its
|
||||
* {@code accessLocation} field should contain an HTTP or HTTPS URL.
|
||||
*
|
||||
* @param tsaCertificate An X.509 certificate for the TSA.
|
||||
* @return An HTTP or HTTPS URI or null if none was found.
|
||||
*/
|
||||
public static URI getTimestampingURI(X509Certificate tsaCertificate) {
|
||||
|
||||
if (tsaCertificate == null) {
|
||||
return null;
|
||||
}
|
||||
// Parse the extensions
|
||||
try {
|
||||
byte[] extensionValue = tsaCertificate.getExtensionValue
|
||||
(KnownOIDs.SubjectInfoAccess.value());
|
||||
if (extensionValue == null) {
|
||||
return null;
|
||||
}
|
||||
DerInputStream der = new DerInputStream(extensionValue);
|
||||
der = new DerInputStream(der.getOctetString());
|
||||
DerValue[] derValue = der.getSequence(5);
|
||||
AccessDescription description;
|
||||
GeneralName location;
|
||||
URIName uri;
|
||||
for (int i = 0; i < derValue.length; i++) {
|
||||
description = new AccessDescription(derValue[i]);
|
||||
if (description.getAccessMethod()
|
||||
.equals(AD_TIMESTAMPING_Id)) {
|
||||
location = description.getAccessLocation();
|
||||
if (location.getType() == GeneralNameInterface.NAME_URI) {
|
||||
uri = (URIName) location.getName();
|
||||
if (uri.getScheme().equalsIgnoreCase("http") ||
|
||||
uri.getScheme().equalsIgnoreCase("https")) {
|
||||
return uri.getURI();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
// ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
116
test/jdk/jdk/security/jarsigner/Properties.java
Normal file
116
test/jdk/jdk/security/jarsigner/Properties.java
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8242068
|
||||
* @summary test the properties
|
||||
* @library /test/lib
|
||||
* @modules java.base/sun.security.tools.keytool
|
||||
* java.base/sun.security.x509
|
||||
* java.base/sun.security.util
|
||||
* jdk.jartool
|
||||
*/
|
||||
|
||||
import jdk.security.jarsigner.JarSigner;
|
||||
import jdk.test.lib.Asserts;
|
||||
import jdk.test.lib.security.DerUtils;
|
||||
import jdk.test.lib.util.JarUtils;
|
||||
import sun.security.tools.keytool.CertAndKeyGen;
|
||||
import sun.security.x509.X500Name;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.util.List;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarInputStream;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
public class Properties {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
Files.writeString(Path.of("anything"), "anything");
|
||||
JarUtils.createJarFile(Path.of("src.jar"), Path.of("."),
|
||||
Files.write(Path.of("anything"), new byte[100]));
|
||||
|
||||
var cakg = new CertAndKeyGen("EC", "SHA1withECDSA");
|
||||
cakg.generate("secp256r1");
|
||||
JarSigner.Builder jsb = new JarSigner.Builder(
|
||||
cakg.getPrivateKey(),
|
||||
CertificateFactory.getInstance("X.509").generateCertPath(List.of(
|
||||
cakg.getSelfCertificate(new X500Name("CN=Me"), 100))));
|
||||
jsb.signerName("E");
|
||||
String sf;
|
||||
|
||||
byte[] i0 = sign(jsb.setProperty("internalsf", "false"));
|
||||
// EncapsulatedContentInfo no content
|
||||
DerUtils.shouldNotExist(i0, "1021");
|
||||
|
||||
byte[] i1 = sign(jsb.setProperty("internalsf", "true"));
|
||||
// EncapsulatedContentInfo has content being the SF
|
||||
sf = new String(DerUtils.innerDerValue(i1, "10210").getOctetString());
|
||||
Asserts.assertTrue(sf.startsWith("Signature-Version"));
|
||||
|
||||
// There is a SignedAttributes
|
||||
byte[] d0 = sign(jsb.setProperty("directsign", "false"));
|
||||
Asserts.assertTrue(DerUtils.innerDerValue(d0, "10403")
|
||||
.isContextSpecific((byte)0));
|
||||
|
||||
// There is no SignedAttributes
|
||||
byte[] d1 = sign(jsb.setProperty("directsign", "true"));
|
||||
Asserts.assertFalse(DerUtils.innerDerValue(d1, "10403")
|
||||
.isContextSpecific((byte)0));
|
||||
|
||||
// Has a hash for the whole manifest
|
||||
byte[] s0 = sign(jsb.setProperty("sectionsonly", "false"));
|
||||
sf = new String(DerUtils.innerDerValue(s0, "10210").getOctetString());
|
||||
Asserts.assertTrue(sf.contains("SHA-256-Digest-Manifest:"));
|
||||
|
||||
// Has no hash for the whole manifest
|
||||
byte[] s1 = sign(jsb.setProperty("sectionsonly", "true"));
|
||||
sf = new String(DerUtils.innerDerValue(s1, "10210").getOctetString());
|
||||
Asserts.assertFalse(sf.contains("SHA-256-Digest-Manifest:"));
|
||||
}
|
||||
|
||||
// Sign and returns the content of the PKCS7 signature block inside
|
||||
static byte[] sign(JarSigner.Builder b) throws Exception {
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
try (ZipFile zf = new ZipFile("src.jar")) {
|
||||
b.build().sign(zf, bout);
|
||||
}
|
||||
var jf = new JarInputStream(
|
||||
new ByteArrayInputStream(bout.toByteArray()));
|
||||
while (true) {
|
||||
JarEntry je = jf.getNextJarEntry();
|
||||
if (je == null) {
|
||||
throw new RuntimeException("Cannot find signature");
|
||||
}
|
||||
if (je.getName().equals("META-INF/E.EC")) {
|
||||
return jf.readAllBytes();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -23,7 +23,7 @@
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8056174
|
||||
* @bug 8056174 8242068
|
||||
* @summary Make sure JarSigner impl conforms to spec
|
||||
* @library /test/lib
|
||||
* @modules java.base/sun.security.tools.keytool
|
||||
@ -125,7 +125,10 @@ public class Spec {
|
||||
iae(()->b1.setProperty("internalsf", "Hello"));
|
||||
npe(()->b1.setProperty("sectionsonly", null));
|
||||
iae(()->b1.setProperty("sectionsonly", "OK"));
|
||||
npe(()->b1.setProperty("sectionsonly", null));
|
||||
npe(()->b1.setProperty("altsigner", null));
|
||||
iae(()->b1.setProperty("directsign", "OK"));
|
||||
npe(()->b1.setProperty("directsign", null));
|
||||
npe(()->b1.eventHandler(null));
|
||||
|
||||
// default values
|
||||
@ -143,6 +146,7 @@ public class Spec {
|
||||
assertTrue(js2.getProperty("tsapolicyid") == null);
|
||||
assertTrue(js2.getProperty("internalsf").equals("false"));
|
||||
assertTrue(js2.getProperty("sectionsonly").equals("false"));
|
||||
assertTrue(js2.getProperty("directsign").equals("false"));
|
||||
assertTrue(js2.getProperty("altsigner") == null);
|
||||
uoe(()->js2.getProperty("invalid"));
|
||||
|
||||
@ -159,6 +163,7 @@ public class Spec {
|
||||
.setProperty("tsapolicyid", "1.2.3.4")
|
||||
.setProperty("internalsf", "true")
|
||||
.setProperty("sectionsonly", "true")
|
||||
.setProperty("directsign", "true")
|
||||
.setProperty("altsigner", "MyContentSigner")
|
||||
.eventHandler(myeh);
|
||||
JarSigner js3 = b3.build();
|
||||
@ -171,6 +176,7 @@ public class Spec {
|
||||
assertTrue(js3.getProperty("tsapolicyid").equals("1.2.3.4"));
|
||||
assertTrue(js3.getProperty("internalsf").equals("true"));
|
||||
assertTrue(js3.getProperty("sectionsonly").equals("true"));
|
||||
assertTrue(js3.getProperty("directsign").equals("true"));
|
||||
assertTrue(js3.getProperty("altsigner").equals("MyContentSigner"));
|
||||
assertTrue(js3.getProperty("altsignerpath") == null);
|
||||
|
||||
|
@ -35,7 +35,6 @@
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.Signature;
|
||||
import java.util.Enumeration;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
@ -80,9 +79,6 @@ public class PKCS10AttrEncoding {
|
||||
X509Key publicKey = (X509Key) pair.getPublic();
|
||||
PrivateKey privateKey = pair.getPrivate();
|
||||
|
||||
Signature signature = Signature.getInstance(sigAlg);
|
||||
signature.initSign(privateKey);
|
||||
|
||||
// Create the PKCS10 request
|
||||
PKCS10Attribute[] attrs = new PKCS10Attribute[len];
|
||||
for (int j = 0; j < len; j++) {
|
||||
@ -95,7 +91,7 @@ public class PKCS10AttrEncoding {
|
||||
|
||||
// Encode the PKCS10 request and generate another PKCS10 request from
|
||||
// the encoded byte array
|
||||
req.encodeAndSign(subject, signature);
|
||||
req.encodeAndSign(subject, privateKey, sigAlg);
|
||||
PKCS10 resp = new PKCS10(req.getEncoded());
|
||||
System.out.println("List of attributes in DER encoded PKCS10 Request:");
|
||||
checkAttributes(resp.getAttributes().getElements());
|
||||
|
@ -22,14 +22,11 @@
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.KeyStore;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
@ -57,7 +54,7 @@ import sun.security.timestamp.TimestampToken;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6543842 6543440 6939248 8009636 8024302 8163304 8169911 8180289 8172404 8247960
|
||||
* @bug 6543842 6543440 6939248 8009636 8024302 8163304 8169911 8180289 8172404 8247960 8242068
|
||||
* @summary checking response of timestamp
|
||||
* @modules java.base/sun.security.pkcs
|
||||
* java.base/sun.security.timestamp
|
||||
@ -355,6 +352,26 @@ public class TimestampCheck {
|
||||
.shouldHaveExitValue(4);
|
||||
checkMultiple("sign2.jar");
|
||||
|
||||
// signed with everyone
|
||||
signVerbose("normal", "unsigned.jar", "signall.jar", "signer",
|
||||
"-sigalg", "SHA3-256withRSA")
|
||||
.shouldHaveExitValue(0);
|
||||
signVerbose("normal", "signall.jar", "signall.jar", "dsakey")
|
||||
.shouldHaveExitValue(0);
|
||||
signVerbose("normal", "signall.jar", "signall.jar", "eckey")
|
||||
.shouldHaveExitValue(0);
|
||||
signVerbose("normal", "signall.jar", "signall.jar", "psskey")
|
||||
.shouldHaveExitValue(0);
|
||||
signVerbose("normal", "signall.jar", "signall.jar", "edkey")
|
||||
.shouldHaveExitValue(0);
|
||||
verify("signall.jar", "-verbose")
|
||||
.shouldHaveExitValue(0)
|
||||
.shouldContain("Signature algorithm: SHA3-256withRSA")
|
||||
.shouldContain("Signature algorithm: RSASSA-PSS")
|
||||
.shouldContain("Signature algorithm: SHA256withECDSA")
|
||||
.shouldContain("Signature algorithm: Ed25519")
|
||||
.shouldContain("Signature algorithm: SHA256withDSA");
|
||||
|
||||
// Legacy algorithms
|
||||
sign("tsweak", "-digestalg", "SHA1",
|
||||
"-sigalg", "SHA1withRSA", "-tsadigestalg", "SHA1")
|
||||
@ -817,6 +834,9 @@ public class TimestampCheck {
|
||||
keytool("-alias signer -genkeypair -ext bc -dname CN=signer");
|
||||
keytool("-alias oldsigner -genkeypair -dname CN=oldsigner");
|
||||
keytool("-alias dsakey -genkeypair -keyalg DSA -dname CN=dsakey");
|
||||
keytool("-alias eckey -genkeypair -keyalg EC -dname CN=eckey");
|
||||
keytool("-alias psskey -genkeypair -keyalg RSASSA-PSS -dname CN=psskey");
|
||||
keytool("-alias edkey -genkeypair -keyalg Ed25519 -dname CN=edkey");
|
||||
keytool("-alias weakkeysize -genkeypair -keysize 1024 -dname CN=weakkeysize");
|
||||
keytool("-alias disabledkeysize -genkeypair -keysize 512 -dname CN=disabledkeysize");
|
||||
keytool("-alias badku -genkeypair -dname CN=badku");
|
||||
@ -846,6 +866,9 @@ public class TimestampCheck {
|
||||
gencert("signer");
|
||||
gencert("oldsigner", "-startdate -30d -validity 20");
|
||||
gencert("dsakey");
|
||||
gencert("eckey");
|
||||
gencert("psskey");
|
||||
gencert("edkey");
|
||||
gencert("weakkeysize");
|
||||
gencert("disabledkeysize");
|
||||
gencert("badku", "-ext ku:critical=keyAgreement");
|
||||
|
@ -23,51 +23,224 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8242184
|
||||
* @summary CRL generation error with RSASSA-PSS
|
||||
* @bug 8242184 8242068
|
||||
* @summary keytool and jarsigner for all algorithms
|
||||
* @library /test/lib
|
||||
* @modules java.base/sun.security.util
|
||||
* @run testng/timeout=300 GenerateAll
|
||||
*/
|
||||
|
||||
import jdk.test.lib.SecurityTools;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.security.DerUtils;
|
||||
import jdk.test.lib.util.JarUtils;
|
||||
import org.testng.annotations.AfterTest;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
import static sun.security.util.KnownOIDs.*;
|
||||
|
||||
import sun.security.util.KnownOIDs;
|
||||
import sun.security.util.ObjectIdentifier;
|
||||
import sun.security.util.SignatureUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.KeyStore;
|
||||
import java.security.PrivateKey;
|
||||
import java.util.Base64;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class GenerateAll {
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
@BeforeTest
|
||||
public void beforeTest() throws Exception {
|
||||
// Create a CA in a separate keystore
|
||||
kt("-genkeypair -alias ca -dname CN=CA -keyalg ec -ext bc -keystore ca");
|
||||
kt("-export -alias ca -file ca.crt -rfc -keystore ca");
|
||||
|
||||
kt("-genkeypair -alias ca -dname CN=CA -keyalg ec");
|
||||
// Import CA cert to user keystore so we can import reply later
|
||||
kt("-import -alias root -file ca.crt -noprompt");
|
||||
|
||||
String[] aliases = {
|
||||
"rsa", "dsa", "rrr", "rsassa-pss", "ec"};
|
||||
JarUtils.createJarFile(Path.of("a.jar"), Path.of("."), Path.of("ks"));
|
||||
}
|
||||
|
||||
for (String alias : aliases) {
|
||||
// "rrr": keyalg is rsa, sigalg is rsassa-pss
|
||||
// otherwise: keyalg is alias, sigalg auto derived
|
||||
String keyAlg = alias.equals("rrr") ? "rsa" : alias;
|
||||
String extra = alias.equals("rrr") ? " -sigalg rsassa-pss" : "";
|
||||
@DataProvider(name = "eddsa")
|
||||
public Object[][] eddsaData() {
|
||||
return new Object[][]{
|
||||
{"eddsa", null, "ed25519"},
|
||||
{"eddsa", "eddsa", "ed25519"},
|
||||
{"eddsa", "ed25519", "ed25519"},
|
||||
{"eddsa", "ed448", null},
|
||||
{"ed25519", null, "ed25519"},
|
||||
{"ed25519", "eddsa", "ed25519"},
|
||||
{"ed25519", "ed25519", "ed25519"},
|
||||
{"ed25519", "ed448", null},
|
||||
{"ed448", null, "ed448"},
|
||||
{"ed448", "eddsa", "ed448"},
|
||||
{"ed448", "ed25519", null},
|
||||
{"ed448", "ed448", "ed448"},
|
||||
};
|
||||
}
|
||||
|
||||
// gen
|
||||
kt("-genkeypair -alias " + alias + " -dname CN=" + alias
|
||||
+ " -keyalg " + keyAlg + extra);
|
||||
/**
|
||||
* Test various names of EdDSA
|
||||
* @param keyAlg keytool -keyalg
|
||||
* @param sigAlg (optional) keytool -sigalg
|
||||
* @param expected expected algorithm of generated signature
|
||||
*/
|
||||
@Test(dataProvider = "eddsa")
|
||||
public void eddsaTest(String keyAlg, String sigAlg, String expected)
|
||||
throws Exception {
|
||||
String alias = keyAlg + "-" + sigAlg;
|
||||
OutputAnalyzer oa = kt0("-genkeypair -alias " + alias
|
||||
+ " -dname CN=" + alias + " -keyalg " + keyAlg
|
||||
+ (sigAlg == null ? "" : (" -sigalg " + sigAlg)));
|
||||
if (expected == null) {
|
||||
oa.shouldNotHaveExitValue(0);
|
||||
} else {
|
||||
oa.shouldHaveExitValue(0);
|
||||
kt("-alias " + alias + " -export -file " + alias + ".crt");
|
||||
byte[] crt = Files.readAllBytes(Path.of(alias + ".crt"));
|
||||
ObjectIdentifier oid = oid(expected);
|
||||
DerUtils.checkAlg(crt, "020", oid); // tbsCertificate.signature
|
||||
DerUtils.checkAlg(crt, "0600", oid); // tbsCertificate.subjectPublicKeyInfo.algorithm
|
||||
DerUtils.checkAlg(crt, "10", oid); // signatureAlgorithm
|
||||
}
|
||||
}
|
||||
|
||||
// req
|
||||
kt("-certreq -alias " + alias + " -file " + alias + ".req");
|
||||
kt("-printcertreq -file " + alias + ".req");
|
||||
@DataProvider(name = "all")
|
||||
public Object[][] dataProvider() {
|
||||
return new Object[][]{
|
||||
{"rsa", "rsa", null, "RSA", SHA_256, SHA256withRSA},
|
||||
{"dsa", "dsa", null, "DSA", SHA_256, SHA256withDSA},
|
||||
{"r", "rsa", "rsassa-pss", "RSA", SHA_256, RSASSA_PSS},
|
||||
{"pss", "rsassa-pss", null, "RSA", SHA_256, RSASSA_PSS},
|
||||
{"ec", "ec", null, "EC", SHA_256, SHA256withECDSA},
|
||||
{"ed25519", "ed25519", null, "EC", SHA_512, Ed25519},
|
||||
{"ed448", "ed448", null, "EC", SHAKE256_LEN, Ed448},
|
||||
};
|
||||
}
|
||||
|
||||
// gencert
|
||||
kt("-gencert -alias ca -infile " + alias
|
||||
+ ".req -outfile " + alias + ".crt");
|
||||
kt("-printcert -file " + alias + ".crt");
|
||||
/**
|
||||
* Testing all algorithms.
|
||||
* @param alias alias
|
||||
* @param keyAlg keytool -keyalg
|
||||
* @param sigAlg (optional) keytool -sigalg
|
||||
* @param ext block extension inside signed JAR
|
||||
* @param expDigAlg expected digAlg in PKCS7 SignerInfo
|
||||
* @param expEncAlg expected encAlg in PKCS7 SignerInfo
|
||||
*/
|
||||
@Test(dataProvider = "all")
|
||||
public void test(String alias, String keyAlg, String sigAlg, String ext,
|
||||
KnownOIDs expDigAlg, KnownOIDs expEncAlg) throws Throwable {
|
||||
|
||||
// crl
|
||||
kt("-gencrl -alias " + alias + " -id 0 -file " + alias + ".crl");
|
||||
kt("-printcrl -file " + alias + ".crl")
|
||||
.shouldContain("Verified by " + alias);
|
||||
char[] pass = "changeit".toCharArray();
|
||||
|
||||
// If no sigAlg, derive automatically
|
||||
String extra = sigAlg == null ? "" : (" -sigalg " + sigAlg);
|
||||
|
||||
// gen
|
||||
kt("-genkeypair -alias " + alias + " -dname CN=" + alias
|
||||
+ " -keyalg " + keyAlg + extra);
|
||||
kt("-export -alias " + alias + " -rfc -file " + alias + ".self");
|
||||
|
||||
// req
|
||||
kt("-certreq -alias " + alias + " -file " + alias + ".req" + extra);
|
||||
kt("-printcertreq -file " + alias + ".req");
|
||||
|
||||
// gencert
|
||||
kt("-gencert -alias ca -infile " + alias
|
||||
+ ".req -outfile " + alias + ".crt -rfc -keystore ca");
|
||||
kt("-printcert -file " + alias + ".crt");
|
||||
kt("-importcert -alias " + alias + " -file " + alias + ".crt");
|
||||
|
||||
// crl
|
||||
kt("-gencrl -alias " + alias + " -id 0 -rfc -file "
|
||||
+ alias + ".crl" + extra);
|
||||
kt("-printcrl -file " + alias + ".crl")
|
||||
.shouldContain("Verified by " + alias);
|
||||
|
||||
// sign
|
||||
js("a.jar " + alias + extra);
|
||||
|
||||
// check data
|
||||
KeyStore ks = KeyStore.getInstance(new File("ks"), pass);
|
||||
PrivateKey pk = (PrivateKey)ks.getKey(alias, pass);
|
||||
|
||||
if (sigAlg == null) {
|
||||
sigAlg = SignatureUtil.getDefaultSigAlgForKey(pk);
|
||||
}
|
||||
|
||||
byte[] crt = read(alias + ".self");
|
||||
DerUtils.checkAlg(crt, "020", oid(sigAlg)); // tbsCertificate.signature
|
||||
DerUtils.checkAlg(crt, "0600", oid(keyAlg)); // tbsCertificate.subjectPublicKeyInfo.algorithm
|
||||
assertEquals(
|
||||
DerUtils.innerDerValue(crt, "02"), // tbsCertificate.signature
|
||||
DerUtils.innerDerValue(crt, "1")); // signatureAlgorithm
|
||||
|
||||
byte[] req = read(alias + ".req");
|
||||
DerUtils.checkAlg(req, "10", oid(sigAlg)); // signatureAlgorithm
|
||||
DerUtils.checkAlg(req, "0200", oid(keyAlg)); // certificationRequestInfo.subjectPKInfo.algorithm
|
||||
|
||||
byte[] crl = read(alias + ".crl");
|
||||
DerUtils.checkAlg(crl, "000", oid(sigAlg)); // tbsCertList.signature
|
||||
assertEquals(
|
||||
DerUtils.innerDerValue(crl, "00"), // tbsCertList.signature
|
||||
DerUtils.innerDerValue(crl, "1")); // signatureAlgorithm
|
||||
|
||||
try (JarFile jf = new JarFile("a.jar")) {
|
||||
JarEntry je = jf.getJarEntry(
|
||||
"META-INF/" + alias.toUpperCase() + "." + ext);
|
||||
byte[] p7 = jf.getInputStream(je).readAllBytes();
|
||||
// SignerInfo.digestAlgorithm
|
||||
DerUtils.checkAlg(p7, "104020", oid(expDigAlg));
|
||||
// SignerInfo.signatureAlgorithm
|
||||
if (DerUtils.innerDerValue(p7, "10403").isContextSpecific()) {
|
||||
// SignerInfo has signedAttributes at 104030
|
||||
DerUtils.checkAlg(p7, "104040", oid(expEncAlg));
|
||||
} else {
|
||||
DerUtils.checkAlg(p7, "104030", oid(expEncAlg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AfterTest
|
||||
public void afterTest() throws Exception {
|
||||
js("-verify a.jar -verbose -certs");
|
||||
}
|
||||
|
||||
static ObjectIdentifier oid(String name) {
|
||||
return ObjectIdentifier.of(KnownOIDs.findMatch(name));
|
||||
}
|
||||
|
||||
static ObjectIdentifier oid(KnownOIDs ko) {
|
||||
return ObjectIdentifier.of(ko);
|
||||
}
|
||||
|
||||
static byte[] read(String f) throws IOException {
|
||||
try (var v = Files.lines(Path.of(f))) {
|
||||
return Base64.getDecoder().decode(v.filter(s -> !s.startsWith("-----"))
|
||||
.collect(Collectors.joining("")));
|
||||
}
|
||||
}
|
||||
|
||||
static OutputAnalyzer kt(String arg) throws Exception {
|
||||
return SecurityTools.keytool("-keystore ks -storepass changeit " + arg)
|
||||
return kt0(arg).shouldHaveExitValue(0);
|
||||
}
|
||||
|
||||
static OutputAnalyzer kt0(String arg) throws Exception {
|
||||
return SecurityTools.keytool("-keystore ks -storepass changeit " + arg);
|
||||
}
|
||||
|
||||
static OutputAnalyzer js(String arg) throws Exception {
|
||||
return SecurityTools.jarsigner("-keystore ks -storepass changeit " + arg)
|
||||
.shouldHaveExitValue(0);
|
||||
}
|
||||
}
|
||||
|
@ -33,15 +33,13 @@ import java.security.cert.X509Certificate;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
|
||||
import sun.security.util.KnownOIDs;
|
||||
import sun.security.util.SignatureUtil;
|
||||
import sun.security.x509.AlgorithmId;
|
||||
|
||||
/**
|
||||
@ -208,9 +206,18 @@ public class TsaHandler implements HttpHandler {
|
||||
protected String getSignerAlias(String alias, String sigAlgo)
|
||||
throws Exception {
|
||||
if (alias == null) {
|
||||
String keyAlgo = sigAlgo == null
|
||||
? null
|
||||
: AlgorithmId.getEncAlgFromSigAlg(sigAlgo);
|
||||
String keyAlgo;
|
||||
if (sigAlgo == null) {
|
||||
keyAlgo = null;
|
||||
} else {
|
||||
String lower = sigAlgo.toLowerCase(Locale.ROOT);
|
||||
int pos = lower.indexOf("with");
|
||||
if (pos < 0) {
|
||||
keyAlgo = sigAlgo;
|
||||
} else {
|
||||
keyAlgo = sigAlgo.substring(pos + 4);
|
||||
}
|
||||
}
|
||||
Enumeration<String> aliases = keyStore.aliases();
|
||||
while(aliases.hasMoreElements()) {
|
||||
String bufAlias = aliases.nextElement();
|
||||
|
@ -34,10 +34,7 @@ import jdk.test.lib.hexdump.HexPrinter;
|
||||
import sun.security.pkcs.ContentInfo;
|
||||
import sun.security.pkcs.PKCS7;
|
||||
import sun.security.pkcs.SignerInfo;
|
||||
import sun.security.util.DerOutputStream;
|
||||
import sun.security.util.DerValue;
|
||||
import sun.security.util.KnownOIDs;
|
||||
import sun.security.util.ObjectIdentifier;
|
||||
import sun.security.util.*;
|
||||
import sun.security.x509.AlgorithmId;
|
||||
import sun.security.x509.X500Name;
|
||||
|
||||
@ -209,7 +206,7 @@ public class TsaSigner {
|
||||
ObjectIdentifier.of(KnownOIDs.TimeStampTokenInfo),
|
||||
new DerValue(eContentOut.toByteArray()));
|
||||
|
||||
String defaultSigAlgo = AlgorithmId.getDefaultSigAlgForKey(
|
||||
String defaultSigAlgo = SignatureUtil.getDefaultSigAlgForKey(
|
||||
signerEntry.privateKey);
|
||||
String sigAlgo = interceptor.getSigAlgo(defaultSigAlgo);
|
||||
Signature signature = Signature.getInstance(sigAlgo);
|
||||
@ -221,8 +218,8 @@ public class TsaSigner {
|
||||
SignerInfo signerInfo = new SignerInfo(
|
||||
new X500Name(issuerName),
|
||||
signerEntry.cert.getSerialNumber(),
|
||||
AlgorithmId.get(
|
||||
AlgorithmId.getDigAlgFromSigAlg(sigAlgo)),
|
||||
SignatureUtil.getDigestAlgInPkcs7SignerInfo(
|
||||
signature, sigAlgo, signerEntry.privateKey, false),
|
||||
AlgorithmId.get(sigAlgo),
|
||||
signature.sign());
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user