/** * Parse the ServerCertificate message. * * @param is The stream where to parse from. * @return A Certificate object with the certs, the server has sended. * @throws IOException If something goes wrong during parsing. */ protected static Certificate parse(InputStream is) throws IOException { X509CertificateStructure[] certs; int left = TlsUtils.readUint24(is); if (left == 0) { return EMPTY_CHAIN; } Vector tmp = new Vector(); while (left > 0) { int size = TlsUtils.readUint24(is); left -= 3 + size; byte[] buf = new byte[size]; TlsUtils.readFully(buf, is); ByteArrayInputStream bis = new ByteArrayInputStream(buf); ASN1InputStream ais = new ASN1InputStream(bis); DERObject o = ais.readObject(); tmp.addElement(X509CertificateStructure.getInstance(o)); if (bis.available() > 0) { throw new IllegalArgumentException( "Sorry, there is garbage data left after the certificate"); } } certs = new X509CertificateStructure[tmp.size()]; for (int i = 0; i < tmp.size(); i++) { certs[i] = (X509CertificateStructure) tmp.elementAt(i); } return new Certificate(certs); }
public void processServerCertificate(Certificate serverCertificate) throws IOException { X509CertificateStructure x509Cert = serverCertificate.certs[0]; SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo(); try { this.serverPublicKey = PublicKeyFactory.createKey(keyInfo); } catch (RuntimeException e) { throw new TlsFatalAlert(AlertDescription.unsupported_certificate); } if (tlsSigner == null) { try { this.dhAgreeServerPublicKey = validateDHPublicKey((DHPublicKeyParameters) this.serverPublicKey); } catch (ClassCastException e) { throw new TlsFatalAlert(AlertDescription.certificate_unknown); } TlsUtils.validateKeyUsage(x509Cert, KeyUsage.keyAgreement); } else { if (!tlsSigner.isValidPublicKey(this.serverPublicKey)) { throw new TlsFatalAlert(AlertDescription.certificate_unknown); } TlsUtils.validateKeyUsage(x509Cert, KeyUsage.digitalSignature); } // TODO /* * Perform various checks per RFC2246 7.4.2: "Unless otherwise specified, the * signing algorithm for the certificate must be the same as the algorithm for the * certificate key." */ }
protected Signer ˊ( SignatureAndHashAlgorithm paramSignatureAndHashAlgorithm, boolean paramBoolean1, boolean paramBoolean2, CipherParameters paramCipherParameters) { int i; if (paramSignatureAndHashAlgorithm != null) { i = 1; } else { i = 0; } if (i != TlsUtils.ᐝ(this.aSQ)) { throw new IllegalStateException(); } if ((paramSignatureAndHashAlgorithm != null) && ((paramSignatureAndHashAlgorithm.mK() != 2) || (paramSignatureAndHashAlgorithm.mL() != mS()))) { throw new IllegalStateException(); } short s; if (paramSignatureAndHashAlgorithm == null) { s = 2; } else { s = paramSignatureAndHashAlgorithm.mK(); } if (paramBoolean1) { paramSignatureAndHashAlgorithm = new NullDigest(); } else { paramSignatureAndHashAlgorithm = TlsUtils.ͺ(s); } paramSignatureAndHashAlgorithm = new DSADigestSigner(ʻ(s), paramSignatureAndHashAlgorithm); paramSignatureAndHashAlgorithm.ˊ(paramBoolean2, ˋ(paramBoolean2, paramCipherParameters)); return paramSignatureAndHashAlgorithm; }
public void processServerCertificate(Certificate serverCertificate) throws IOException { if (serverCertificate.isEmpty()) { throw new TlsFatalAlert(AlertDescription.bad_certificate); } org.ripple.bouncycastle.asn1.x509.Certificate x509Cert = serverCertificate.getCertificateAt(0); SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo(); try { this.serverPublicKey = PublicKeyFactory.createKey(keyInfo); } catch (RuntimeException e) { throw new TlsFatalAlert(AlertDescription.unsupported_certificate, e); } if (tlsSigner == null) { try { this.dhAgreePublicKey = TlsDHUtils.validateDHPublicKey((DHPublicKeyParameters) this.serverPublicKey); this.dhParameters = validateDHParameters(dhAgreePublicKey.getParameters()); } catch (ClassCastException e) { throw new TlsFatalAlert(AlertDescription.certificate_unknown, e); } TlsUtils.validateKeyUsage(x509Cert, KeyUsage.keyAgreement); } else { if (!tlsSigner.isValidPublicKey(this.serverPublicKey)) { throw new TlsFatalAlert(AlertDescription.certificate_unknown); } TlsUtils.validateKeyUsage(x509Cert, KeyUsage.digitalSignature); } super.processServerCertificate(serverCertificate); }
/** * Parse a {@link DigitallySigned} from an {@link InputStream}. * * @param context the {@link TlsContext} of the current connection. * @param input the {@link InputStream} to parse from. * @return a {@link DigitallySigned} object. * @throws IOException */ public static DigitallySigned parse(TlsContext context, InputStream input) throws IOException { SignatureAndHashAlgorithm algorithm = null; if (TlsUtils.isTLSv12(context)) { algorithm = SignatureAndHashAlgorithm.parse(input); } byte[] signature = TlsUtils.readOpaque16(input); return new DigitallySigned(algorithm, signature); }
protected void generateEphemeralClientKeyExchange(ECDomainParameters ecParams, OutputStream os) throws IOException { AsymmetricCipherKeyPair ecAgreeClientKeyPair = generateECKeyPair(ecParams); this.ecAgreeClientPrivateKey = (ECPrivateKeyParameters) ecAgreeClientKeyPair.getPrivate(); byte[] keData = externalizeKey((ECPublicKeyParameters) ecAgreeClientKeyPair.getPublic()); TlsUtils.writeUint24(keData.length + 1, os); TlsUtils.writeOpaque8(keData, os); }
protected void generateEphemeralClientKeyExchange(DHParameters dhParams, OutputStream os) throws IOException { AsymmetricCipherKeyPair dhAgreeClientKeyPair = generateDHKeyPair(dhParams); this.dhAgreeClientPrivateKey = (DHPrivateKeyParameters) dhAgreeClientKeyPair.getPrivate(); BigInteger Yc = ((DHPublicKeyParameters) dhAgreeClientKeyPair.getPublic()).getY(); byte[] keData = BigIntegers.asUnsignedByteArray(Yc); TlsUtils.writeUint24(keData.length + 2, os); TlsUtils.writeOpaque16(keData, os); }
private void sendCertificateVerify(byte[] data) throws IOException { /* * Send signature of handshake messages so far to prove we are the owner of the * cert See RFC 2246 sections 4.7, 7.4.3 and 7.4.8 */ ByteArrayOutputStream bos = new ByteArrayOutputStream(); TlsUtils.writeUint8(HandshakeType.certificate_verify, bos); TlsUtils.writeUint24(data.length + 2, bos); TlsUtils.writeOpaque16(data, bos); byte[] message = bos.toByteArray(); rs.writeMessage(ContentType.handshake, message, 0, message.length); }
private void processHandshake() throws IOException { boolean read; do { read = false; /* * We need the first 4 bytes, they contain type and length of the message. */ if (handshakeQueue.size() >= 4) { byte[] beginning = new byte[4]; handshakeQueue.read(beginning, 0, 4, 0); ByteArrayInputStream bis = new ByteArrayInputStream(beginning); short type = TlsUtils.readUint8(bis); int len = TlsUtils.readUint24(bis); /* * Check if we have enough bytes in the buffer to read the full message. */ if (handshakeQueue.size() >= (len + 4)) { /* * Read the message. */ byte[] buf = new byte[len]; handshakeQueue.read(buf, 0, len, 4); handshakeQueue.removeData(len + 4); /* * RFC 2246 7.4.9. The value handshake_messages includes all handshake * messages starting at client hello up to, but not including, this * finished message. [..] Note: [Also,] Hello Request messages are * omitted from handshake hashes. */ switch (type) { case HandshakeType.hello_request: case HandshakeType.finished: break; default: rs.updateHandshakeData(beginning, 0, 4); rs.updateHandshakeData(buf, 0, len); break; } /* * Now, parse the message. */ processHandshakeMessage(type, buf); read = true; } } } while (read); }
private void sendClientCertificate(Certificate clientCert) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); TlsUtils.writeUint8(HandshakeType.certificate, bos); // Reserve space for length TlsUtils.writeUint24(0, bos); clientCert.encode(bos); byte[] message = bos.toByteArray(); // Patch actual length back in TlsUtils.writeUint24(message.length - 4, message, 1); rs.writeMessage(ContentType.handshake, message, 0, message.length); }
public void generateClientKeyExchange(OutputStream os) throws IOException { if (agreementCredentials != null) { TlsUtils.writeUint24(0, os); } else { generateEphemeralClientKeyExchange(ecAgreeServerPublicKey.getParameters(), os); } }
private void sendClientKeyExchange() throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); TlsUtils.writeUint8(HandshakeType.client_key_exchange, bos); // Reserve space for length TlsUtils.writeUint24(0, bos); this.keyExchange.generateClientKeyExchange(bos); byte[] message = bos.toByteArray(); // Patch actual length back in TlsUtils.writeUint24(message.length - 4, message, 1); rs.writeMessage(ContentType.handshake, message, 0, message.length); }
public void processServerCertificate(Certificate serverCertificate) throws IOException { X509CertificateStructure x509Cert = serverCertificate.certs[0]; SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo(); try { this.serverPublicKey = PublicKeyFactory.createKey(keyInfo); } catch (RuntimeException e) { throw new TlsFatalAlert(AlertDescription.unsupported_certificate); } // Sanity check the PublicKeyFactory if (this.serverPublicKey.isPrivate()) { throw new TlsFatalAlert(AlertDescription.internal_error); } this.rsaServerPublicKey = validateRSAPublicKey((RSAKeyParameters) this.serverPublicKey); TlsUtils.validateKeyUsage(x509Cert, KeyUsage.keyEncipherment); // TODO /* * Perform various checks per RFC2246 7.4.2: "Unless otherwise specified, the * signing algorithm for the certificate must be the same as the algorithm for the * certificate key." */ }
protected void processCertificateVerify( ServerHandshakeState state, byte[] body, TlsHandshakeHash prepareFinishHash) throws IOException { ByteArrayInputStream buf = new ByteArrayInputStream(body); DigitallySigned clientCertificateVerify = DigitallySigned.parse(state.serverContext, buf); TlsProtocol.assertEmpty(buf); // Verify the CertificateVerify message contains a correct signature. try { // TODO For TLS 1.2, this needs to be the hash specified in the DigitallySigned byte[] certificateVerifyHash = TlsProtocol.getCurrentPRFHash(state.serverContext, prepareFinishHash, null); org.bouncycastle.asn1.x509.Certificate x509Cert = state.clientCertificate.getCertificateAt(0); SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo(); AsymmetricKeyParameter publicKey = PublicKeyFactory.createKey(keyInfo); TlsSigner tlsSigner = TlsUtils.createTlsSigner(state.clientCertificateType); tlsSigner.init(state.serverContext); tlsSigner.verifyRawSignature( clientCertificateVerify.getAlgorithm(), clientCertificateVerify.getSignature(), publicKey, certificateVerifyHash); } catch (Exception e) { throw new TlsFatalAlert(AlertDescription.decrypt_error); } }
protected DigitallySigned parseSignature(InputStream input) throws IOException { DigitallySigned signature = DigitallySigned.parse(context, input); SignatureAndHashAlgorithm signatureAlgorithm = signature.getAlgorithm(); if (signatureAlgorithm != null) { TlsUtils.verifySupportedSignatureAlgorithm(supportedSignatureAlgorithms, signatureAlgorithm); } return signature; }
/** * Encodes version of the ClientCertificate message * * @param os stream to write the message to * @throws IOException If something goes wrong */ protected void encode(OutputStream os) throws IOException { Vector encCerts = new Vector(); int totalSize = 0; for (int i = 0; i < this.certs.length; ++i) { byte[] encCert = certs[i].getEncoded(ASN1Encodable.DER); encCerts.addElement(encCert); totalSize += encCert.length + 3; } TlsUtils.writeUint24(totalSize + 3, os); TlsUtils.writeUint24(totalSize, os); for (int i = 0; i < encCerts.size(); ++i) { byte[] encCert = (byte[]) encCerts.elementAt(i); TlsUtils.writeOpaque24(encCert, os); } }
/** * Parse a {@link CertificateRequest} from an {@link InputStream}. * * @param context the {@link TlsContext} of the current connection. * @param input the {@link InputStream} to parse from. * @return a {@link CertificateRequest} object. * @throws IOException */ public static CertificateRequest parse(TlsContext context, InputStream input) throws IOException { int numTypes = TlsUtils.readUint8(input); short[] certificateTypes = new short[numTypes]; for (int i = 0; i < numTypes; ++i) { certificateTypes[i] = TlsUtils.readUint8(input); } Vector supportedSignatureAlgorithms = null; if (TlsUtils.isTLSv12(context)) { // TODO Check whether SignatureAlgorithm.anonymous is allowed here supportedSignatureAlgorithms = TlsUtils.parseSupportedSignatureAlgorithms(false, input); } Vector certificateAuthorities = new Vector(); byte[] certAuthData = TlsUtils.readOpaque16(input); ByteArrayInputStream bis = new ByteArrayInputStream(certAuthData); while (bis.available() > 0) { byte[] derEncoding = TlsUtils.readOpaque16(bis); ASN1Primitive asn1 = TlsUtils.readDERObject(derEncoding); certificateAuthorities.addElement(X500Name.getInstance(asn1)); } return new CertificateRequest( certificateTypes, supportedSignatureAlgorithms, certificateAuthorities); }
/** * Parse a {@link OCSPStatusRequest} from an {@link InputStream}. * * @param input the {@link InputStream} to parse from. * @return a {@link OCSPStatusRequest} object. * @throws IOException */ public static OCSPStatusRequest parse(InputStream input) throws IOException { Vector responderIDList = new Vector(); { int length = TlsUtils.readUint16(input); if (length > 0) { byte[] data = TlsUtils.readFully(length, input); ByteArrayInputStream buf = new ByteArrayInputStream(data); do { byte[] derEncoding = TlsUtils.readOpaque16(buf); ResponderID responderID = ResponderID.getInstance(TlsUtils.readDERObject(derEncoding)); responderIDList.addElement(responderID); } while (buf.available() > 0); } } Extensions requestExtensions = null; { int length = TlsUtils.readUint16(input); if (length > 0) { byte[] derEncoding = TlsUtils.readFully(length, input); requestExtensions = Extensions.getInstance(TlsUtils.readDERObject(derEncoding)); } } return new OCSPStatusRequest(responderIDList, requestExtensions); }
public Hashtable getClientExtensions() throws IOException { Hashtable clientExtensions = new Hashtable(); ByteArrayOutputStream srpData = new ByteArrayOutputStream(); TlsUtils.writeOpaque8(this.identity, srpData); clientExtensions.put(EXT_SRP, srpData.toByteArray()); return clientExtensions; }
public byte[] generateCertificateSignature(byte[] hash) throws IOException { try { if (TlsUtils.isTLSv12(context)) { return signer.generateRawSignature(signatureAndHashAlgorithm, privateKey, hash); } else { return signer.generateRawSignature(privateKey, hash); } } catch (CryptoException e) { throw new TlsFatalAlert(AlertDescription.internal_error, e); } }
public void generateClientKeyExchange(OutputStream os) throws IOException { /* * RFC 2246 7.4.7.2 If the client certificate already contains a suitable * Diffie-Hellman key, then Yc is implicit and does not need to be sent again. In * this case, the Client Key Exchange message will be sent, but will be empty. */ if (agreementCredentials != null) { TlsUtils.writeUint24(0, os); } else { generateEphemeralClientKeyExchange(dhAgreeServerPublicKey.getParameters(), os); } }
/** * Encode this {@link CertificateRequest} to an {@link OutputStream}. * * @param output the {@link OutputStream} to encode to. * @throws IOException */ public void encode(OutputStream output) throws IOException { if (certificateTypes == null || certificateTypes.length == 0) { TlsUtils.writeUint8(0, output); } else { TlsUtils.writeUint8ArrayWithUint8Length(certificateTypes, output); } if (supportedSignatureAlgorithms != null) { // TODO Check whether SignatureAlgorithm.anonymous is allowed here TlsUtils.encodeSupportedSignatureAlgorithms(supportedSignatureAlgorithms, false, output); } if (certificateAuthorities == null || certificateAuthorities.isEmpty()) { TlsUtils.writeUint16(0, output); } else { Vector derEncodings = new Vector(certificateAuthorities.size()); int totalLength = 0; for (int i = 0; i < certificateAuthorities.size(); ++i) { X500Name certificateAuthority = (X500Name) certificateAuthorities.elementAt(i); byte[] derEncoding = certificateAuthority.getEncoded(ASN1Encoding.DER); derEncodings.addElement(derEncoding); totalLength += derEncoding.length; } TlsUtils.checkUint16(totalLength); TlsUtils.writeUint16(totalLength, output); for (int i = 0; i < derEncodings.size(); ++i) { byte[] encDN = (byte[]) derEncodings.elementAt(i); output.write(encDN); } } }
/** * Determines whether a specific array of <tt>byte</tt>s appears to contain a DTLS record. * * @param buf the array of <tt>byte</tt>s to be analyzed * @param off the offset within <tt>buf</tt> at which the analysis is to start * @param len the number of bytes within <tt>buf</tt> starting at <tt>off</tt> to be analyzed * @return <tt>true</tt> if the specified <tt>buf</tt> appears to contain a DTLS record */ public static boolean isDtlsRecord(byte[] buf, int off, int len) { boolean b = false; if (len >= DTLS_RECORD_HEADER_LENGTH) { short type = TlsUtils.readUint8(buf, off); switch (type) { case ContentType.alert: case ContentType.application_data: case ContentType.change_cipher_spec: case ContentType.handshake: int major = buf[off + 1] & 0xff; int minor = buf[off + 2] & 0xff; ProtocolVersion version = null; if ((major == ProtocolVersion.DTLSv10.getMajorVersion()) && (minor == ProtocolVersion.DTLSv10.getMinorVersion())) { version = ProtocolVersion.DTLSv10; } if ((version == null) && (major == ProtocolVersion.DTLSv12.getMajorVersion()) && (minor == ProtocolVersion.DTLSv12.getMinorVersion())) { version = ProtocolVersion.DTLSv12; } if (version != null) { int length = TlsUtils.readUint16(buf, off + 11); if (DTLS_RECORD_HEADER_LENGTH + length <= len) b = true; } break; default: // Unless a new ContentType has been defined by the Bouncy // Castle Crypto APIs, the specified buf does not represent a // DTLS record. break; } } return b; }
public void generateClientKeyExchange(OutputStream os) throws IOException { /* * Choose a PremasterSecret and send it encrypted to the server */ premasterSecret = new byte[48]; context.getSecureRandom().nextBytes(premasterSecret); TlsUtils.writeVersion(premasterSecret, 0); PKCS1Encoding encoding = new PKCS1Encoding(new RSABlindedEngine()); encoding.init( true, new ParametersWithRandom(this.rsaServerPublicKey, context.getSecureRandom())); try { byte[] keData = encoding.processBlock(premasterSecret, 0, premasterSecret.length); TlsUtils.writeUint24(keData.length + 2, os); TlsUtils.writeOpaque16(keData, os); } catch (InvalidCipherTextException e) { /* * This should never happen, only during decryption. */ throw new TlsFatalAlert(AlertDescription.internal_error); } }
protected Signer makeSigner( SignatureAndHashAlgorithm algorithm, boolean raw, boolean forSigning, CipherParameters cp) { if ((algorithm != null) != TlsUtils.isTLSv12(context)) { throw new IllegalStateException(); } if (algorithm != null && algorithm.getSignature() != SignatureAlgorithm.rsa) { throw new IllegalStateException(); } Digest d; if (raw) { d = new NullDigest(); } else if (algorithm == null) { d = new CombinedHash(); } else { d = TlsUtils.createHash(algorithm.getHash()); } Signer s; if (algorithm != null) { /* * RFC 5246 4.7. In RSA signing, the opaque vector contains the signature generated * using the RSASSA-PKCS1-v1_5 signature scheme defined in [PKCS1]. */ s = new RSADigestSigner(d, TlsUtils.getOIDForHashAlgorithm(algorithm.getHash())); } else { /* * RFC 5246 4.7. Note that earlier versions of TLS used a different RSA signature scheme * that did not include a DigestInfo encoding. */ s = new GenericSigner(createRSAImpl(), d); } s.init(forSigning, cp); return s; }
public TlsBlockCipher( TlsClientContext context, BlockCipher encryptCipher, BlockCipher decryptCipher, Digest writeDigest, Digest readDigest, int cipherKeySize) { this.context = context; this.randomData = new byte[256]; context.getSecureRandom().nextBytes(randomData); this.encryptCipher = encryptCipher; this.decryptCipher = decryptCipher; int key_block_size = (2 * cipherKeySize) + writeDigest.getDigestSize() + readDigest.getDigestSize() + encryptCipher.getBlockSize() + decryptCipher.getBlockSize(); byte[] key_block = TlsUtils.calculateKeyBlock(context, key_block_size); int offset = 0; // Init MACs writeMac = new TlsMac(context, writeDigest, key_block, offset, writeDigest.getDigestSize()); offset += writeDigest.getDigestSize(); readMac = new TlsMac(context, readDigest, key_block, offset, readDigest.getDigestSize()); offset += readDigest.getDigestSize(); // Init Ciphers this.initCipher( true, encryptCipher, key_block, cipherKeySize, offset, offset + (cipherKeySize * 2)); offset += cipherKeySize; this.initCipher( false, decryptCipher, key_block, cipherKeySize, offset, offset + cipherKeySize + encryptCipher.getBlockSize()); }
public DefaultTlsSignerCredentials( TlsContext context, Certificate certificate, AsymmetricKeyParameter privateKey, SignatureAndHashAlgorithm signatureAndHashAlgorithm) { if (certificate == null) { throw new IllegalArgumentException("'certificate' cannot be null"); } if (certificate.isEmpty()) { throw new IllegalArgumentException("'certificate' cannot be empty"); } if (privateKey == null) { throw new IllegalArgumentException("'privateKey' cannot be null"); } if (!privateKey.isPrivate()) { throw new IllegalArgumentException("'privateKey' must be private"); } if (TlsUtils.isTLSv12(context) && signatureAndHashAlgorithm == null) { throw new IllegalArgumentException( "'signatureAndHashAlgorithm' cannot be null for (D)TLS 1.2+"); } if (privateKey instanceof RSAKeyParameters) { this.signer = new TlsRSASigner(); } else if (privateKey instanceof DSAPrivateKeyParameters) { this.signer = new TlsDSSSigner(); } else if (privateKey instanceof ECPrivateKeyParameters) { this.signer = new TlsECDSASigner(); } else { throw new IllegalArgumentException( "'privateKey' type not supported: " + privateKey.getClass().getName()); } this.signer.init(context); this.context = context; this.certificate = certificate; this.privateKey = privateKey; this.signatureAndHashAlgorithm = signatureAndHashAlgorithm; }
protected void notifyClientCertificate(ServerHandshakeState state, Certificate clientCertificate) throws IOException { if (state.certificateRequest == null) { throw new IllegalStateException(); } if (state.clientCertificate != null) { throw new TlsFatalAlert(AlertDescription.unexpected_message); } state.clientCertificate = clientCertificate; if (clientCertificate.isEmpty()) { state.keyExchange.skipClientCredentials(); } else { /* * TODO RFC 5246 7.4.6. If the certificate_authorities list in the certificate request * message was non-empty, one of the certificates in the certificate chain SHOULD be * issued by one of the listed CAs. */ state.clientCertificateType = TlsUtils.getClientCertificateType( clientCertificate, state.serverCredentials.getCertificate()); state.keyExchange.processClientCertificate(clientCertificate); } /* * RFC 5246 7.4.6. If the client does not send any certificates, the server MAY at its * discretion either continue the handshake without client authentication, or respond with a * fatal handshake_failure alert. Also, if some aspect of the certificate chain was * unacceptable (e.g., it was not signed by a known, trusted CA), the server MAY at its * discretion either continue the handshake (considering the client unauthenticated) or send * a fatal alert. */ state.server.notifyClientCertificate(clientCertificate); }
/** * Encode this {@link OCSPStatusRequest} to an {@link OutputStream}. * * @param output the {@link OutputStream} to encode to. * @throws IOException */ public void encode(OutputStream output) throws IOException { if (responderIDList == null || responderIDList.isEmpty()) { TlsUtils.writeUint16(0, output); } else { ByteArrayOutputStream buf = new ByteArrayOutputStream(); for (int i = 0; i < responderIDList.size(); ++i) { ResponderID responderID = (ResponderID) responderIDList.elementAt(i); byte[] derEncoding = responderID.getEncoded(ASN1Encoding.DER); TlsUtils.writeOpaque16(derEncoding, buf); } TlsUtils.checkUint16(buf.size()); TlsUtils.writeUint16(buf.size(), output); buf.writeTo(output); } if (requestExtensions == null) { TlsUtils.writeUint16(0, output); } else { byte[] derEncoding = requestExtensions.getEncoded(ASN1Encoding.DER); TlsUtils.checkUint16(derEncoding.length); TlsUtils.writeUint16(derEncoding.length, output); output.write(derEncoding); } }
/** * Encode this {@link DigitallySigned} to an {@link OutputStream}. * * @param output the {@link OutputStream} to encode to. * @throws IOException */ public void encode(OutputStream output) throws IOException { if (algorithm != null) { algorithm.encode(output); } TlsUtils.writeOpaque16(signature, output); }