Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/pkcs10/PKCS10.java
38831 views
/*1* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/242526package sun.security.pkcs10;2728import java.io.PrintStream;29import java.io.IOException;30import java.math.BigInteger;3132import java.security.cert.CertificateException;33import java.security.*;3435import java.util.Base64;3637import sun.security.util.*;38import sun.security.x509.AlgorithmId;39import sun.security.x509.X509Key;40import sun.security.x509.X500Name;41import sun.security.util.SignatureUtil;424344/**45* A PKCS #10 certificate request is created and sent to a Certificate46* Authority, which then creates an X.509 certificate and returns it to47* the entity that requested it. A certificate request basically consists48* of the subject's X.500 name, public key, and optionally some attributes,49* signed using the corresponding private key.50*51* The ASN.1 syntax for a Certification Request is:52* <pre>53* CertificationRequest ::= SEQUENCE {54* certificationRequestInfo CertificationRequestInfo,55* signatureAlgorithm SignatureAlgorithmIdentifier,56* signature Signature57* }58*59* SignatureAlgorithmIdentifier ::= AlgorithmIdentifier60* Signature ::= BIT STRING61*62* CertificationRequestInfo ::= SEQUENCE {63* version Version,64* subject Name,65* subjectPublicKeyInfo SubjectPublicKeyInfo,66* attributes [0] IMPLICIT Attributes67* }68* Attributes ::= SET OF Attribute69* </pre>70*71* @author David Brownell72* @author Amit Kapoor73* @author Hemma Prafullchandra74*/75public class PKCS10 {76/**77* Constructs an unsigned PKCS #10 certificate request. Before this78* request may be used, it must be encoded and signed. Then it79* must be retrieved in some conventional format (e.g. string).80*81* @param publicKey the public key that should be placed82* into the certificate generated by the CA.83*/84public PKCS10(PublicKey publicKey) {85subjectPublicKeyInfo = publicKey;86attributeSet = new PKCS10Attributes();87}8889/**90* Constructs an unsigned PKCS #10 certificate request. Before this91* request may be used, it must be encoded and signed. Then it92* must be retrieved in some conventional format (e.g. string).93*94* @param publicKey the public key that should be placed95* into the certificate generated by the CA.96* @param attributes additonal set of PKCS10 attributes requested97* for in the certificate.98*/99public PKCS10(PublicKey publicKey, PKCS10Attributes attributes) {100subjectPublicKeyInfo = publicKey;101attributeSet = attributes;102}103104/**105* Parses an encoded, signed PKCS #10 certificate request, verifying106* the request's signature as it does so. This constructor would107* typically be used by a Certificate Authority, from which a new108* certificate would then be constructed.109*110* @param data the DER-encoded PKCS #10 request.111* @exception IOException for low level errors reading the data112* @exception SignatureException when the signature is invalid113* @exception NoSuchAlgorithmException when the signature114* algorithm is not supported in this environment115*/116public PKCS10(byte[] data)117throws IOException, SignatureException, NoSuchAlgorithmException {118DerInputStream in;119DerValue[] seq;120AlgorithmId id;121byte[] sigData;122Signature sig;123124encoded = data;125126//127// Outer sequence: request, signature algorithm, signature.128// Parse, and prepare to verify later.129//130in = new DerInputStream(data);131seq = in.getSequence(3);132133if (seq.length != 3)134throw new IllegalArgumentException("not a PKCS #10 request");135136data = seq[0].toByteArray(); // reusing this variable137id = AlgorithmId.parse(seq[1]);138sigData = seq[2].getBitString();139140//141// Inner sequence: version, name, key, attributes142//143BigInteger serial;144DerValue val;145146serial = seq[0].data.getBigInteger();147if (!serial.equals(BigInteger.ZERO))148throw new IllegalArgumentException("not PKCS #10 v1");149150subject = new X500Name(seq[0].data);151subjectPublicKeyInfo = X509Key.parse(seq[0].data.getDerValue());152153// Cope with a somewhat common illegal PKCS #10 format154if (seq[0].data.available() != 0)155attributeSet = new PKCS10Attributes(seq[0].data);156else157attributeSet = new PKCS10Attributes();158159if (seq[0].data.available() != 0)160throw new IllegalArgumentException("illegal PKCS #10 data");161162//163// OK, we parsed it all ... validate the signature using the164// key and signature algorithm we found.165//166try {167sigAlg = id.getName();168sig = Signature.getInstance(sigAlg);169SignatureUtil.initVerifyWithParam(sig, subjectPublicKeyInfo,170SignatureUtil.getParamSpec(sigAlg, id.getParameters()));171172sig.update(data);173if (!sig.verify(sigData)) {174throw new SignatureException("Invalid PKCS #10 signature");175}176} catch (InvalidKeyException e) {177throw new SignatureException("Invalid key");178} catch (InvalidAlgorithmParameterException e) {179throw new SignatureException("Invalid signature parameters", e);180} catch (ProviderException e) {181throw new SignatureException("Error parsing signature parameters",182e.getCause());183}184}185186/**187* Create the signed certificate request. This will later be188* retrieved in either string or binary format.189*190* @param subject identifies the signer (by X.500 name).191* @param signature private key and signing algorithm to use.192* @exception IOException on errors.193* @exception CertificateException on certificate handling errors.194* @exception SignatureException on signature handling errors.195*/196public void encodeAndSign(X500Name subject, Signature signature)197throws CertificateException, IOException, SignatureException {198DerOutputStream out, scratch;199byte[] certificateRequestInfo;200byte[] sig;201202if (encoded != null)203throw new SignatureException("request is already signed");204205this.subject = subject;206207/*208* Encode cert request info, wrap in a sequence for signing209*/210scratch = new DerOutputStream();211scratch.putInteger(BigInteger.ZERO); // PKCS #10 v1.0212subject.encode(scratch); // X.500 name213scratch.write(subjectPublicKeyInfo.getEncoded()); // public key214attributeSet.encode(scratch);215216out = new DerOutputStream();217out.write(DerValue.tag_Sequence, scratch); // wrap it!218certificateRequestInfo = out.toByteArray();219scratch = out;220221/*222* Sign it ...223*/224signature.update(certificateRequestInfo, 0,225certificateRequestInfo.length);226sig = signature.sign();227sigAlg = signature.getAlgorithm();228229/*230* Build guts of SIGNED macro231*/232AlgorithmId algId = null;233try {234AlgorithmParameters params = signature.getParameters();235algId = params == null236? AlgorithmId.get(signature.getAlgorithm())237: AlgorithmId.get(params);238} catch (NoSuchAlgorithmException nsae) {239throw new SignatureException(nsae);240}241242algId.encode(scratch); // sig algorithm243scratch.putBitString(sig); // sig244245/*246* Wrap those guts in a sequence247*/248out = new DerOutputStream();249out.write(DerValue.tag_Sequence, scratch);250encoded = out.toByteArray();251}252253/**254* Returns the subject's name.255*/256public X500Name getSubjectName() { return subject; }257258/**259* Returns the subject's public key.260*/261public PublicKey getSubjectPublicKeyInfo()262{ return subjectPublicKeyInfo; }263264/**265* Returns the signature algorithm.266*/267public String getSigAlg() { return sigAlg; }268269/**270* Returns the additional attributes requested.271*/272public PKCS10Attributes getAttributes()273{ return attributeSet; }274275/**276* Returns the encoded and signed certificate request as a277* DER-encoded byte array.278*279* @return the certificate request, or null if encodeAndSign()280* has not yet been called.281*/282public byte[] getEncoded() {283if (encoded != null)284return encoded.clone();285else286return null;287}288289/**290* Prints an E-Mailable version of the certificate request on the print291* stream passed. The format is a common base64 encoded one, supported292* by most Certificate Authorities because Netscape web servers have293* used this for some time. Some certificate authorities expect some294* more information, in particular contact information for the web295* server administrator.296*297* @param out the print stream where the certificate request298* will be printed.299* @exception IOException when an output operation failed300* @exception SignatureException when the certificate request was301* not yet signed.302*/303public void print(PrintStream out)304throws IOException, SignatureException {305if (encoded == null)306throw new SignatureException("Cert request was not signed");307308309byte[] CRLF = new byte[] {'\r', '\n'};310out.println("-----BEGIN NEW CERTIFICATE REQUEST-----");311out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(encoded));312out.println("-----END NEW CERTIFICATE REQUEST-----");313}314315/**316* Provides a short description of this request.317*/318public String toString() {319return "[PKCS #10 certificate request:\n"320+ subjectPublicKeyInfo.toString()321+ " subject: <" + subject + ">" + "\n"322+ " attributes: " + attributeSet.toString()323+ "\n]";324}325326/**327* Compares this object for equality with the specified328* object. If the <code>other</code> object is an329* <code>instanceof</code> <code>PKCS10</code>, then330* its encoded form is retrieved and compared with the331* encoded form of this certificate request.332*333* @param other the object to test for equality with this object.334* @return true iff the encoded forms of the two certificate335* requests match, false otherwise.336*/337public boolean equals(Object other) {338if (this == other)339return true;340if (!(other instanceof PKCS10))341return false;342if (encoded == null) // not signed yet343return false;344byte[] otherEncoded = ((PKCS10)other).getEncoded();345if (otherEncoded == null)346return false;347348return java.util.Arrays.equals(encoded, otherEncoded);349}350351/**352* Returns a hashcode value for this certificate request from its353* encoded form.354*355* @return the hashcode value.356*/357public int hashCode() {358int retval = 0;359if (encoded != null)360for (int i = 1; i < encoded.length; i++)361retval += encoded[i] * i;362return(retval);363}364365private X500Name subject;366private PublicKey subjectPublicKeyInfo;367private String sigAlg;368private PKCS10Attributes attributeSet;369private byte[] encoded; // signed370}371372373