Ejemplo n.º 1
0
  /**
   * Sign the provided payment request.
   *
   * @param paymentRequest Payment request to sign, in its builder form.
   * @param certificateChain Certificate chain to send with the payment request, ordered from client
   *     certificate to root certificate. The root certificate itself may be omitted.
   * @param privateKey The key to sign with. Must match the public key from the first certificate of
   *     the certificate chain.
   */
  public static void signPaymentRequest(
      Protos.PaymentRequest.Builder paymentRequest,
      X509Certificate[] certificateChain,
      PrivateKey privateKey) {
    try {
      final Protos.X509Certificates.Builder certificates = Protos.X509Certificates.newBuilder();
      for (final Certificate certificate : certificateChain)
        certificates.addCertificate(ByteString.copyFrom(certificate.getEncoded()));

      paymentRequest.setPkiType("x509+sha256");
      paymentRequest.setPkiData(certificates.build().toByteString());
      paymentRequest.setSignature(ByteString.EMPTY);
      final Protos.PaymentRequest paymentRequestToSign = paymentRequest.build();

      final String algorithm;
      if ("RSA".equalsIgnoreCase(privateKey.getAlgorithm())) algorithm = "SHA256withRSA";
      else throw new IllegalStateException(privateKey.getAlgorithm());

      final Signature signature = Signature.getInstance(algorithm);
      signature.initSign(privateKey);
      signature.update(paymentRequestToSign.toByteArray());

      paymentRequest.setSignature(ByteString.copyFrom(signature.sign()));
    } catch (final GeneralSecurityException x) {
      // Should never happen so don't make users have to think about it.
      throw new RuntimeException(x);
    }
  }
  /** java.security.KeyStore#getKey(java.lang.String, char[]) */
  public void test_getKeyLjava_lang_String$C() throws Exception {

    // Test for method java.security.Key
    // java.security.KeyStore.getKey(java.lang.String, char[])
    // creatCertificate();
    CertificateFactory cf = CertificateFactory.getInstance("X.509");
    X509Certificate cert[] = new X509Certificate[2];
    cert[0] = (X509Certificate) cf.generateCertificate(certArray);
    cert[1] = (X509Certificate) cf.generateCertificate(certArray2);
    KeyStore keyTest = KeyStore.getInstance(KeyStore.getDefaultType());
    keyTest.load(null, null);

    keyTest.setKeyEntry("alias2", getPrivateKey(), pssWord, cert);
    PrivateKey returnedKey = (PrivateKey) keyTest.getKey("alias2", pssWord);
    byte[] retB = returnedKey.getEncoded();
    byte[] priB = getPrivateKey().getEncoded();
    assertTrue(Arrays.equals(retB, priB));
    assertEquals(getPrivateKey().getAlgorithm(), returnedKey.getAlgorithm());
    assertEquals(getPrivateKey().getFormat(), returnedKey.getFormat());

    try {
      keyTest.getKey("alias2", "wrong".toCharArray());
      fail();
    } catch (UnrecoverableKeyException expected) {
    }

    keyTest.setCertificateEntry("alias1", cert[1]);
    assertNull(
        "the private key returned from getKey for a certificate entry is not null",
        keyTest.getKey("alias1", pssWord));
  }
Ejemplo n.º 3
0
  private void validateKeys(PublicKey pubKey, PrivateKey privKey) {

    if (pubKey.getAlgorithm() != privKey.getAlgorithm())
      throw new IllegalArgumentException("Public and private key have different algorithms");

    // No encryption for DSA
    if (pubKey.getAlgorithm() != "RSA") return;

    try {

      String data = "ENCRYPT_DATA";
      SecureRandom random = new SecureRandom();
      Cipher cipher = Cipher.getInstance(pubKey.getAlgorithm());
      cipher.init(Cipher.ENCRYPT_MODE, privKey, random);
      byte[] encryptedData = cipher.doFinal(data.getBytes());

      cipher.init(Cipher.DECRYPT_MODE, pubKey, random);
      String decreptedData = new String(cipher.doFinal(encryptedData));
      if (!decreptedData.equals(data)) throw new IllegalArgumentException("Bad public-private key");

    } catch (BadPaddingException e) {
      throw new IllegalArgumentException("Bad public-private key", e);
    } catch (IllegalBlockSizeException e) {
      throw new IllegalArgumentException("Bad public-private key", e);
    } catch (NoSuchPaddingException e) {
      throw new IllegalArgumentException("Bad public-private key", e);
    } catch (InvalidKeyException e) {
      throw new IllegalArgumentException("Invalid public-private key", e);
    } catch (NoSuchAlgorithmException e) {
      throw new IllegalArgumentException("Invalid algorithm for public-private key", e);
    }
  }
Ejemplo n.º 4
0
 @Test
 public void testPrivateKey() throws Exception {
   KeyPair keyPair = KeyPairFactory.newRsa2048();
   String pem = PemUtils.toPem(keyPair.getPrivate());
   assertNotNull(pem);
   PrivateKey privateKey = PemUtils.loadPrivateKeyFromPem(pem);
   assertTrue(privateKey.getAlgorithm().equalsIgnoreCase(BcCmsConstants.KEY_PAIR_ALGO));
 }
  /**
   * Create a new PKCS#7 object from the specified key.
   *
   * @param privKey the private key to be used for signing.
   * @param certChain the certificate chain associated with the private key.
   * @param crlList the crl list associated with the private key.
   * @param hashAlgorithm the hashing algorithm used to compute the message digest. Must be "MD5",
   *     "MD2", "SHA1" or "SHA"
   * @param provider the provider to use.
   */
  public PKCS7SignedData(
      PrivateKey privKey,
      Certificate[] certChain,
      CRL[] crlList,
      String hashAlgorithm,
      String provider)
      throws SecurityException, InvalidKeyException, NoSuchProviderException,
          NoSuchAlgorithmException {
    this.privKey = privKey;

    if (hashAlgorithm.equals("MD5")) {
      digestAlgorithm = ID_MD5;
    } else if (hashAlgorithm.equals("MD2")) {
      digestAlgorithm = ID_MD2;
    } else if (hashAlgorithm.equals("SHA")) {
      digestAlgorithm = ID_SHA1;
    } else if (hashAlgorithm.equals("SHA1")) {
      digestAlgorithm = ID_SHA1;
    } else {
      throw new NoSuchAlgorithmException("Unknown Hash Algorithm " + hashAlgorithm);
    }

    version = signerversion = 1;
    certs = new ArrayList();
    crls = new ArrayList();
    digestalgos = new HashSet();
    digestalgos.add(digestAlgorithm);

    //
    // Copy in the certificates and crls used to sign the private key.
    //
    signCert = (X509Certificate) certChain[0];
    for (int i = 0; i < certChain.length; i++) {
      certs.add(certChain[i]);
    }

    if (crlList != null) {
      for (int i = 0; i < crlList.length; i++) {
        crls.add(crlList[i]);
      }
    }

    //
    // Now we have private key, find out what the digestEncryptionAlgorithm is.
    //
    digestEncryptionAlgorithm = privKey.getAlgorithm();
    if (digestEncryptionAlgorithm.equals("RSA")) {
      digestEncryptionAlgorithm = ID_RSA;
    } else if (digestEncryptionAlgorithm.equals("DSA")) {
      digestEncryptionAlgorithm = ID_DSA;
    } else {
      throw new NoSuchAlgorithmException("Unknown Key Algorithm " + digestEncryptionAlgorithm);
    }

    sig = Signature.getInstance(getDigestAlgorithm(), provider);

    sig.initSign(privKey);
  }
  @Override
  public KeyType getKeyType() throws CVKeyTypeNotSupportedException {
    String strAlgo = m_key.getAlgorithm();

    if ("RSA".equals(strAlgo)) {
      return KeyType.KEY_RSA;
    } else if ("EC".equals(strAlgo) || "ECC".equals(strAlgo) || "ECDSA".equals(strAlgo)) {
      return KeyType.KEY_ECDSA;
    }

    throw new CVKeyTypeNotSupportedException();
  }
 // 私钥加密
 public static byte[] encryptByPrivateKey(String key, byte[] data) throws Exception {
   // 实例化密钥材�?
   PKCS8EncodedKeySpec pcs8spec = new PKCS8EncodedKeySpec(Base64.decode(key.getBytes()));
   // 实例化密钥工�?
   KeyFactory keyfactory = KeyFactory.getInstance(Key_ALGORITHM);
   // 生成私钥
   PrivateKey pritekey = keyfactory.generatePrivate(pcs8spec);
   // 私钥加密
   Cipher cipher = Cipher.getInstance(pritekey.getAlgorithm());
   cipher.init(Cipher.ENCRYPT_MODE, pritekey);
   return cipher.doFinal(data);
 }
Ejemplo n.º 8
0
  /**
   * Sign a given message with a given PrivateKey object. This method shall only be used to
   * implement signing in the context of SSL client certificate support.
   *
   * <p>The message will actually be a hash, computed by OpenSSL itself, depending on the type of
   * the key. The result should match exactly what the vanilla implementations of the following
   * OpenSSL function calls do:
   *
   * <p>- For a RSA private key, this should be equivalent to calling RSA_private_encrypt(...,
   * RSA_PKCS1_PADDING), i.e. it must generate a raw RSA signature. The message must be either a
   * combined, 36-byte MD5+SHA1 message digest or a DigestInfo value wrapping a message digest.
   *
   * <p>- For a ECDSA private keys, this should be equivalent to calling ECDSA_sign(0,...). The
   * message must be a hash and the function shall compute a direct ECDSA signature for it.
   *
   * @param privateKey The PrivateKey handle.
   * @param message The message to sign.
   * @return signature as a byte buffer.
   *     <p>Important: Due to a platform bug, this function will always fail on Android < 4.2 for
   *     RSA PrivateKey objects. See the getOpenSSLHandleForPrivateKey() below for work-around.
   */
  @CalledByNative
  private static byte[] rawSignDigestWithPrivateKey(PrivateKey privateKey, byte[] message) {
    // Get the Signature for this key.
    Signature signature = null;
    // Hint: Algorithm names come from:
    // http://docs.oracle.com/javase/6/docs/technotes/guides/security/StandardNames.html
    try {
      String keyAlgorithm = privateKey.getAlgorithm();
      if ("RSA".equalsIgnoreCase(keyAlgorithm)) {
        // IMPORTANT: Due to a platform bug, this will throw NoSuchAlgorithmException
        // on Android 4.1.x. Fixed in 4.2 and higher.
        // See https://android-review.googlesource.com/#/c/40352/
        signature = Signature.getInstance("NONEwithRSA");
      } else if ("EC".equalsIgnoreCase(keyAlgorithm)) {
        signature = Signature.getInstance("NONEwithECDSA");
      }
    } catch (NoSuchAlgorithmException e) {
      // Intentionally do nothing.
    }

    if (signature == null) {
      Log.e(TAG, "Unsupported private key algorithm: " + privateKey.getAlgorithm());
      return null;
    }

    // Sign the message.
    try {
      signature.initSign(privateKey);
      signature.update(message);
      return signature.sign();
    } catch (Exception e) {
      Log.e(
          TAG,
          "Exception while signing message with "
              + privateKey.getAlgorithm()
              + " private key: "
              + e);
      return null;
    }
  }
Ejemplo n.º 9
0
 public PrivateKey getPrivateKey(String alias) {
   PrivateKey pk = keyManager.getPrivateKey(alias);
   if (Debug.verboseOn())
     Debug.logVerbose(
         "getPrivateKey for alias ["
             + alias
             + "] got "
             + (pk == null
                 ? "[Not Found!]"
                 : "[alg:" + pk.getAlgorithm() + ";format:" + pk.getFormat() + "]"),
         module);
   // Debug.logInfo(new Exception(), "Location where getPrivateKey is called", module);
   return pk;
 }
Ejemplo n.º 10
0
  private String decryptCredential(final String cred) {
    try {
      final PrivateKeyFactoryBean factory = new PrivateKeyFactoryBean();
      factory.setAlgorithm("RSA");
      factory.setLocation(new ClassPathResource("RSA1024Private.p8"));
      factory.setSingleton(false);
      final PrivateKey privateKey = factory.getObject();

      logger.debug("Initializing cipher based on [{}]", privateKey.getAlgorithm());
      final Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());

      logger.debug("Decoding value [{}]", cred);
      final byte[] cred64 = CompressionUtils.decodeBase64ToByteArray(cred);

      logger.debug("Initializing decrypt-mode via private key [{}]", privateKey.getAlgorithm());
      cipher.init(Cipher.DECRYPT_MODE, privateKey);

      final byte[] cipherData = cipher.doFinal(cred64);
      return new String(cipherData);
    } catch (final Exception e) {
      throw new RuntimeException(e);
    }
  }
Ejemplo n.º 11
0
 private SaslServer createSaslServer(
     final String mechanism,
     final String serverName,
     final X509TrustManager trustManager,
     final PrivateKey privateKey,
     final X509Certificate... certificateChain)
     throws Exception {
   return new SaslServerBuilder(EntitySaslServerFactory.class, mechanism)
       .setProtocol("test")
       .setServerName(serverName)
       .setCredential(
           new X509CertificateChainPrivateCredential(privateKey, certificateChain),
           privateKey.getAlgorithm())
       .setTrustManager(trustManager)
       .build();
 }
Ejemplo n.º 12
0
  /**
   * Compute the raw signature value over the supplied input.
   *
   * <p>It is up to the caller to ensure that the specified algorithm ID is consistent with the type
   * of signing key supplied.
   *
   * @param signingKey the private key with which to compute the signature
   * @param jcaAlgorithmID the Java JCA algorithm ID to use
   * @param input the input over which to compute the signature
   * @return the computed signature value
   * @throws SecurityException thrown if the signature computation results in an error
   */
  public static byte[] sign(PrivateKey signingKey, String jcaAlgorithmID, byte[] input)
      throws SecurityException {
    log.debug(
        "Computing signature over input using private key of type {} and JCA algorithm ID {}",
        signingKey.getAlgorithm(),
        jcaAlgorithmID);

    try {
      Signature signature = Signature.getInstance(jcaAlgorithmID);
      signature.initSign(signingKey);
      signature.update(input);
      byte[] rawSignature = signature.sign();
      log.debug("Computed signature: {}", new String(Hex.encode(rawSignature)));
      return rawSignature;
    } catch (GeneralSecurityException e) {
      log.error("Error during signature generation", e);
      throw new SecurityException("Error during signature generation", e);
    }
  }
  private String getSigAlgorithm(PrivateKey key, String digestOID) {
    String enc = null;

    if (key instanceof RSAPrivateKey || "RSA".equalsIgnoreCase(key.getAlgorithm())) {
      enc = "RSA";
    } else if (key instanceof DSAPrivateKey || "DSA".equalsIgnoreCase(key.getAlgorithm())) {
      enc = "DSA";
    } else if ("ECDSA".equalsIgnoreCase(key.getAlgorithm())
        || "EC".equalsIgnoreCase(key.getAlgorithm())) {
      enc = "ECDSA";
    } else if (key instanceof GOST3410PrivateKey
        || "GOST3410".equalsIgnoreCase(key.getAlgorithm())) {
      enc = "GOST3410";
    } else if ("ECGOST3410".equalsIgnoreCase(key.getAlgorithm())) {
      enc = CMSSignedGenerator.ENCRYPTION_ECGOST3410;
    }

    return TSPUtil.getDigestAlgName(digestOID) + "with" + enc;
  }
Ejemplo n.º 14
0
   public PKCS7SignedData(PrivateKey var1, Certificate[] var2, CRL[] var3, String var4, String var5) throws SecurityException, InvalidKeyException, NoSuchProviderException, NoSuchAlgorithmException {
      this.ID_PKCS7_DATA = "1.2.840.113549.1.7.1";
      this.ID_PKCS7_SIGNED_DATA = "1.2.840.113549.1.7.2";
      this.ID_MD5 = "1.2.840.113549.2.5";
      this.ID_MD2 = "1.2.840.113549.2.2";
      this.ID_SHA1 = "1.3.14.3.2.26";
      this.ID_RSA = "1.2.840.113549.1.1.1";
      this.ID_DSA = "1.2.840.10040.4.1";
      this.privKey = var1;
      if("MD5".equals(var4)) {
         this.digestAlgorithm = "1.2.840.113549.2.5";
      } else if("MD2".equals(var4)) {
         this.digestAlgorithm = "1.2.840.113549.2.2";
      } else if("SHA".equals(var4)) {
         this.digestAlgorithm = "1.3.14.3.2.26";
      } else {
         if(!"SHA1".equals(var4)) {
            String var18 = "Unknown Hash Algorithm " + var4;
            throw new NoSuchAlgorithmException(var18);
         }

         this.digestAlgorithm = "1.3.14.3.2.26";
      }

      this.signerversion = 1;
      this.version = 1;
      ArrayList var6 = new ArrayList();
      this.certs = var6;
      ArrayList var7 = new ArrayList();
      this.crls = var7;
      HashSet var8 = new HashSet();
      this.digestalgos = var8;
      Set var9 = this.digestalgos;
      String var10 = this.digestAlgorithm;
      var9.add(var10);
      X509Certificate var12 = (X509Certificate)var2[0];
      this.signCert = var12;
      int var13 = 0;

      while(true) {
         int var14 = var2.length;
         if(var13 >= var14) {
            if(var3 != null) {
               var13 = 0;

               while(true) {
                  int var19 = var3.length;
                  if(var13 >= var19) {
                     break;
                  }

                  Collection var20 = this.crls;
                  CRL var21 = var3[var13];
                  var20.add(var21);
                  ++var13;
               }
            }

            String var23 = var1.getAlgorithm();
            this.digestEncryptionAlgorithm = var23;
            String var24 = this.digestEncryptionAlgorithm;
            if("RSA".equals(var24)) {
               this.digestEncryptionAlgorithm = "1.2.840.113549.1.1.1";
            } else {
               String var26 = this.digestEncryptionAlgorithm;
               if(!"DSA".equals(var26)) {
                  StringBuilder var27 = (new StringBuilder()).append("Unknown Key Algorithm ");
                  String var28 = this.digestEncryptionAlgorithm;
                  String var29 = var27.append(var28).toString();
                  throw new NoSuchAlgorithmException(var29);
               }

               this.digestEncryptionAlgorithm = "1.2.840.10040.4.1";
            }

            Signature var25 = Signature.getInstance(this.getDigestAlgorithm(), var5);
            this.sig = var25;
            this.sig.initSign(var1);
            return;
         }

         Collection var15 = this.certs;
         Certificate var16 = var2[var13];
         var15.add(var16);
         ++var13;
      }
   }
  /**
   * Processes ServerHelloDone: makes verification of the server messages; sends client messages,
   * computers masterSecret, sends ChangeCipherSpec
   */
  @DSComment("Package priviledge")
  @DSBan(DSCat.DEFAULT_MODIFIER)
  @DSGenerator(
      tool_name = "Doppelganger",
      tool_version = "2.0",
      generated_on = "2013-12-30 13:01:10.434 -0500",
      hash_original_method = "2DDF37E22088D1FE8BC73EB3CA83F3A0",
      hash_generated_method = "D2F899ECF0C8F0AF7307958FBF03F0A2")
  void processServerHelloDone() {
    PrivateKey clientKey = null;

    if (serverCert != null) {
      if (session.cipherSuite.isAnonymous()) {
        unexpectedMessage();
        return;
      }
      verifyServerCert();
    } else {
      if (!session.cipherSuite.isAnonymous()) {
        unexpectedMessage();
        return;
      }
    }

    // Client certificate
    if (certificateRequest != null) {
      X509Certificate[] certs = null;
      // obtain certificates from key manager
      String alias = null;
      String[] certTypes = certificateRequest.getTypesAsString();
      X500Principal[] issuers = certificateRequest.certificate_authorities;
      X509KeyManager km = parameters.getKeyManager();
      if (km instanceof X509ExtendedKeyManager) {
        X509ExtendedKeyManager ekm = (X509ExtendedKeyManager) km;
        if (this.socketOwner != null) {
          alias = ekm.chooseClientAlias(certTypes, issuers, this.socketOwner);
        } else {
          alias = ekm.chooseEngineClientAlias(certTypes, issuers, this.engineOwner);
        }
        if (alias != null) {
          certs = ekm.getCertificateChain(alias);
        }
      } else {
        alias = km.chooseClientAlias(certTypes, issuers, this.socketOwner);
        if (alias != null) {
          certs = km.getCertificateChain(alias);
        }
      }

      session.localCertificates = certs;
      clientCert = new CertificateMessage(certs);
      clientKey = km.getPrivateKey(alias);
      send(clientCert);
    }
    // Client key exchange
    if (session.cipherSuite.keyExchange == CipherSuite.KEY_EXCHANGE_RSA
        || session.cipherSuite.keyExchange == CipherSuite.KEY_EXCHANGE_RSA_EXPORT) {
      // RSA encrypted premaster secret message
      Cipher c;
      try {
        c = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        if (serverKeyExchange != null) {
          c.init(Cipher.ENCRYPT_MODE, serverKeyExchange.getRSAPublicKey());
        } else {
          c.init(Cipher.ENCRYPT_MODE, serverCert.certs[0]);
        }
      } catch (Exception e) {
        fatalAlert(AlertProtocol.INTERNAL_ERROR, "Unexpected exception", e);
        return;
      }
      preMasterSecret = new byte[48];
      parameters.getSecureRandom().nextBytes(preMasterSecret);
      System.arraycopy(clientHello.client_version, 0, preMasterSecret, 0, 2);
      try {
        clientKeyExchange =
            new ClientKeyExchange(c.doFinal(preMasterSecret), serverHello.server_version[1] == 1);
      } catch (Exception e) {
        fatalAlert(AlertProtocol.INTERNAL_ERROR, "Unexpected exception", e);
        return;
      }
    } else {
      try {
        KeyFactory kf = KeyFactory.getInstance("DH");
        KeyAgreement agreement = KeyAgreement.getInstance("DH");
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH");
        PublicKey serverPublic;
        DHParameterSpec spec;
        if (serverKeyExchange != null) {
          serverPublic =
              kf.generatePublic(
                  new DHPublicKeySpec(
                      serverKeyExchange.par3, serverKeyExchange.par1, serverKeyExchange.par2));
          spec = new DHParameterSpec(serverKeyExchange.par1, serverKeyExchange.par2);
        } else {
          serverPublic = serverCert.certs[0].getPublicKey();
          spec = ((DHPublicKey) serverPublic).getParams();
        }
        kpg.initialize(spec);

        KeyPair kp = kpg.generateKeyPair();
        Key key = kp.getPublic();
        if (clientCert != null
            && serverCert != null
            && (session.cipherSuite.keyExchange == CipherSuite.KEY_EXCHANGE_DHE_RSA
                || session.cipherSuite.keyExchange == CipherSuite.KEY_EXCHANGE_DHE_DSS)) {
          PublicKey client_pk = clientCert.certs[0].getPublicKey();
          PublicKey server_pk = serverCert.certs[0].getPublicKey();
          if (client_pk instanceof DHKey && server_pk instanceof DHKey) {
            if (((DHKey) client_pk)
                    .getParams()
                    .getG()
                    .equals(((DHKey) server_pk).getParams().getG())
                && ((DHKey) client_pk)
                    .getParams()
                    .getP()
                    .equals(((DHKey) server_pk).getParams().getG())) {
              // client cert message DH public key parameters
              // matched those specified by the
              //   server in its certificate,
              clientKeyExchange = new ClientKeyExchange(); // empty
            }
          }
        } else {
          clientKeyExchange = new ClientKeyExchange(((DHPublicKey) key).getY());
        }
        key = kp.getPrivate();
        agreement.init(key);
        agreement.doPhase(serverPublic, true);
        preMasterSecret = agreement.generateSecret();
      } catch (Exception e) {
        fatalAlert(AlertProtocol.INTERNAL_ERROR, "Unexpected exception", e);
        return;
      }
    }
    if (clientKeyExchange != null) {
      send(clientKeyExchange);
    }

    computerMasterSecret();

    // send certificate verify for all certificates except those containing
    // fixed DH parameters
    if (clientCert != null && !clientKeyExchange.isEmpty()) {
      // Certificate verify
      String authType = clientKey.getAlgorithm();
      DigitalSignature ds = new DigitalSignature(authType);
      ds.init(clientKey);

      if ("RSA".equals(authType)) {
        ds.setMD5(io_stream.getDigestMD5());
        ds.setSHA(io_stream.getDigestSHA());
      } else if ("DSA".equals(authType)) {
        ds.setSHA(io_stream.getDigestSHA());
        // The Signature should be empty in case of anonymous signature algorithm:
        // } else if ("DH".equals(authType)) {
      }
      certificateVerify = new CertificateVerify(ds.sign());
      send(certificateVerify);
    }

    sendChangeCipherSpec();
  }