c82ad845e1
Reviewed-by: rhalade, ascarpino
276 lines
9.5 KiB
Java
276 lines
9.5 KiB
Java
/*
|
|
* Copyright (c) 2015, 2024, 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 8048357
|
|
* @summary test PKCS7 data signing, encoding and verification
|
|
* @library /test/lib
|
|
* @modules java.base/sun.security.pkcs
|
|
* java.base/sun.security.util
|
|
* java.base/sun.security.x509
|
|
* @run main SignerOrder default 1024
|
|
* @run main SignerOrder Sha256 2048
|
|
*/
|
|
import java.io.IOException;
|
|
import java.math.BigInteger;
|
|
import java.security.KeyPair;
|
|
import java.security.KeyPairGenerator;
|
|
import java.security.PrivateKey;
|
|
import java.security.Signature;
|
|
import java.security.SignatureException;
|
|
import java.security.cert.X509Certificate;
|
|
import java.util.Date;
|
|
import sun.security.pkcs.ContentInfo;
|
|
import sun.security.pkcs.PKCS7;
|
|
import sun.security.pkcs.SignerInfo;
|
|
import sun.security.util.DerOutputStream;
|
|
import sun.security.x509.AlgorithmId;
|
|
import sun.security.x509.CertificateAlgorithmId;
|
|
import sun.security.x509.CertificateSerialNumber;
|
|
import sun.security.x509.CertificateValidity;
|
|
import sun.security.x509.CertificateVersion;
|
|
import sun.security.x509.CertificateX509Key;
|
|
import sun.security.x509.X500Name;
|
|
import sun.security.x509.X509CertImpl;
|
|
import sun.security.x509.X509CertInfo;
|
|
import sun.security.x509.X509Key;
|
|
import jdk.test.lib.hexdump.HexPrinter;
|
|
|
|
public class SignerOrder {
|
|
|
|
//signer infos
|
|
static final byte[] data1 = "12345".getBytes();
|
|
static final byte[] data2 = "abcde".getBytes();
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
String digestAlg = "default".equals(args[0]) ? null : args[0];
|
|
int keySize = Integer.parseInt(args[1]);
|
|
SignerInfo[] signerInfos = new SignerInfo[9];
|
|
SimpleSigner signer1 = new SimpleSigner(digestAlg, null, null, null, keySize);
|
|
signerInfos[8] = signer1.genSignerInfo(data1);
|
|
signerInfos[7] = signer1.genSignerInfo(new byte[]{});
|
|
signerInfos[6] = signer1.genSignerInfo(data2);
|
|
|
|
SimpleSigner signer2 = new SimpleSigner(digestAlg, null, null, null, keySize);
|
|
signerInfos[5] = signer2.genSignerInfo(data1);
|
|
signerInfos[4] = signer2.genSignerInfo(new byte[]{});
|
|
signerInfos[3] = signer2.genSignerInfo(data2);
|
|
|
|
SimpleSigner signer3 = new SimpleSigner(digestAlg, null, null, null, keySize);
|
|
signerInfos[2] = signer3.genSignerInfo(data1);
|
|
signerInfos[1] = signer3.genSignerInfo(new byte[]{});
|
|
signerInfos[0] = signer3.genSignerInfo(data2);
|
|
|
|
ContentInfo contentInfo = new ContentInfo(data1);
|
|
|
|
AlgorithmId[] algIds = {new AlgorithmId(AlgorithmId.SHA256_oid)};
|
|
|
|
X509Certificate[] certs = {signer3.getCert(), signer2.getCert(),
|
|
signer1.getCert()};
|
|
|
|
PKCS7 pkcs71 = new PKCS7(algIds, contentInfo,
|
|
certs,
|
|
signerInfos);
|
|
|
|
System.out.println("SignerInfos in original.");
|
|
printSignerInfos(pkcs71.getSignerInfos());
|
|
|
|
DerOutputStream out = new DerOutputStream();
|
|
pkcs71.encodeSignedData(out);
|
|
|
|
PKCS7 pkcs72 = new PKCS7(out.toByteArray());
|
|
System.out.println("\nSignerInfos read back in:");
|
|
printSignerInfos(pkcs72.getSignerInfos());
|
|
|
|
System.out.println("Verified signers of original:");
|
|
SignerInfo[] verifs1 = pkcs71.verify(null);
|
|
|
|
System.out.println("Verified signers of after read-in:");
|
|
SignerInfo[] verifs2 = pkcs72.verify(null);
|
|
|
|
if (verifs1.length != verifs2.length) {
|
|
throw new RuntimeException("Length or Original vs read-in "
|
|
+ "should be same");
|
|
}
|
|
}
|
|
|
|
static void printSignerInfos(SignerInfo signerInfo) throws IOException {
|
|
DerOutputStream strm = new DerOutputStream();
|
|
signerInfo.encode(strm);
|
|
System.out.println("SignerInfo, length: "
|
|
+ strm.toByteArray().length);
|
|
HexPrinter.simple().format(strm.toByteArray());
|
|
System.out.println("\n");
|
|
strm.reset();
|
|
}
|
|
|
|
static void printSignerInfos(SignerInfo[] signerInfos) throws IOException {
|
|
DerOutputStream strm = new DerOutputStream();
|
|
for (int i = 0; i < signerInfos.length; i++) {
|
|
signerInfos[i].encode(strm);
|
|
System.out.println("SignerInfo[" + i + "], length: "
|
|
+ strm.toByteArray().length);
|
|
HexPrinter.simple().format(strm.toByteArray());
|
|
System.out.println("\n");
|
|
strm.reset();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* A simple extension of sun.security.x509.X500Signer that adds a no-fuss
|
|
* signing algorithm.
|
|
*/
|
|
class SimpleSigner {
|
|
|
|
private final Signature sig;
|
|
private final X500Name agent;
|
|
private final AlgorithmId digestAlgId;
|
|
private final AlgorithmId encryptionAlgId;
|
|
private final AlgorithmId algId; // signature algid;
|
|
//combines digest + encryption
|
|
private final X509Key publicKey;
|
|
private final PrivateKey privateKey;
|
|
private final X509Certificate cert;
|
|
|
|
public SimpleSigner(String digestAlg,
|
|
String encryptionAlg,
|
|
KeyPair keyPair,
|
|
X500Name agent,
|
|
int keySize) throws Exception {
|
|
|
|
String signAlgoDigest;
|
|
if (agent == null) {
|
|
agent = new X500Name("cn=test");
|
|
}
|
|
if (encryptionAlg == null) {
|
|
encryptionAlg = "DSA";
|
|
}
|
|
if (digestAlg == null) {
|
|
digestAlg = "SHA";
|
|
signAlgoDigest = encryptionAlg;
|
|
} else {
|
|
signAlgoDigest = digestAlg + "with" + encryptionAlg;
|
|
}
|
|
if (keyPair == null) {
|
|
KeyPairGenerator keyGen =
|
|
KeyPairGenerator.getInstance(encryptionAlg);
|
|
keyGen.initialize(keySize);
|
|
keyPair = keyGen.generateKeyPair();
|
|
}
|
|
publicKey = (X509Key) keyPair.getPublic();
|
|
privateKey = keyPair.getPrivate();
|
|
|
|
if ("DSA".equals(encryptionAlg)) {
|
|
this.sig = Signature.getInstance(signAlgoDigest);
|
|
} else { // RSA
|
|
this.sig = Signature.getInstance(digestAlg + "/" + encryptionAlg);
|
|
}
|
|
this.sig.initSign(privateKey);
|
|
|
|
this.agent = agent;
|
|
this.digestAlgId = AlgorithmId.get(digestAlg);
|
|
this.encryptionAlgId = AlgorithmId.get(encryptionAlg);
|
|
this.algId = AlgorithmId.get(this.sig.getAlgorithm());
|
|
|
|
this.cert = getSelfCert();
|
|
}
|
|
|
|
/**
|
|
* Take the data and sign it.
|
|
*
|
|
* @param buf buffer holding the next chunk of the data to be signed
|
|
* @param offset starting point of to-be-signed data
|
|
* @param len how many bytes of data are to be signed
|
|
* @return the signature for the input data.
|
|
* @exception SignatureException on errors.
|
|
*/
|
|
public byte[] simpleSign(byte[] buf, int offset, int len)
|
|
throws SignatureException {
|
|
sig.update(buf, offset, len);
|
|
return sig.sign();
|
|
}
|
|
|
|
/**
|
|
* Returns the digest algorithm used to sign.
|
|
*/
|
|
public AlgorithmId getDigestAlgId() {
|
|
return digestAlgId;
|
|
}
|
|
|
|
/**
|
|
* Returns the encryption algorithm used to sign.
|
|
*/
|
|
public AlgorithmId getEncryptionAlgId() {
|
|
return encryptionAlgId;
|
|
}
|
|
|
|
/**
|
|
* Returns the name of the signing agent.
|
|
*/
|
|
public X500Name getSigner() {
|
|
return agent;
|
|
}
|
|
|
|
public X509Certificate getCert() {
|
|
return cert;
|
|
}
|
|
|
|
private X509Certificate getSelfCert() throws Exception {
|
|
long validity = 1000;
|
|
X509CertImpl certLocal;
|
|
Date firstDate, lastDate;
|
|
|
|
firstDate = new Date();
|
|
lastDate = new Date();
|
|
lastDate.setTime(lastDate.getTime() + validity + 1000);
|
|
|
|
CertificateValidity interval = new CertificateValidity(firstDate,
|
|
lastDate);
|
|
|
|
X509CertInfo info = new X509CertInfo();
|
|
// Add all mandatory attributes
|
|
info.setVersion(new CertificateVersion(CertificateVersion.V1));
|
|
info.setSerialNumber(new CertificateSerialNumber(
|
|
(int) (firstDate.getTime() / 1000)));
|
|
info.setAlgorithmId(new CertificateAlgorithmId(algId));
|
|
info.setSubject(agent);
|
|
info.setKey(new CertificateX509Key(publicKey));
|
|
info.setValidity(interval);
|
|
info.setIssuer(agent);
|
|
|
|
certLocal = X509CertImpl.newSigned(info, privateKey, algId.getName());
|
|
|
|
return certLocal;
|
|
}
|
|
|
|
public SignerInfo genSignerInfo(byte[] data) throws SignatureException {
|
|
return new SignerInfo((X500Name) cert.getIssuerDN(),
|
|
new BigInteger("" + cert.getSerialNumber()),
|
|
getDigestAlgId(), algId,
|
|
simpleSign(data, 0, data.length));
|
|
}
|
|
}
|