private static byte[] checksum(PGPDigestCalculator digCalc, byte[] bytes, int length)
      throws PGPException {
    if (digCalc != null) {
      OutputStream dOut = digCalc.getOutputStream();

      try {
        dOut.write(bytes, 0, length);

        dOut.close();
      } catch (Exception e) {
        throw new PGPException("checksum digest calculation failed: " + e.getMessage(), e);
      }
      return digCalc.getDigest();
    } else {
      int checksum = 0;

      for (int i = 0; i != length; i++) {
        checksum += bytes[i] & 0xff;
      }

      byte[] check = new byte[2];

      check[0] = (byte) (checksum >> 8);
      check[1] = (byte) checksum;

      return check;
    }
  }
  PGPSecretKey(
      PGPPrivateKey privKey,
      PGPPublicKey pubKey,
      PGPDigestCalculator checksumCalculator,
      boolean isMasterKey,
      PBESecretKeyEncryptor keyEncryptor)
      throws PGPException {
    this.pub = pubKey;

    BCPGObject secKey = (BCPGObject) privKey.getPrivateKeyDataPacket();

    try {
      ByteArrayOutputStream bOut = new ByteArrayOutputStream();
      BCPGOutputStream pOut = new BCPGOutputStream(bOut);

      pOut.writeObject(secKey);

      byte[] keyData = bOut.toByteArray();

      pOut.write(checksum(checksumCalculator, keyData, keyData.length));

      int encAlgorithm = keyEncryptor.getAlgorithm();

      if (encAlgorithm != SymmetricKeyAlgorithmTags.NULL) {
        keyData = bOut.toByteArray(); // include checksum

        byte[] encData = keyEncryptor.encryptKeyData(keyData, 0, keyData.length);
        byte[] iv = keyEncryptor.getCipherIV();

        S2K s2k = keyEncryptor.getS2K();

        int s2kUsage;

        if (checksumCalculator != null) {
          if (checksumCalculator.getAlgorithm() != HashAlgorithmTags.SHA1) {
            throw new PGPException("only SHA1 supported for key checksum calculations.");
          }
          s2kUsage = SecretKeyPacket.USAGE_SHA1;
        } else {
          s2kUsage = SecretKeyPacket.USAGE_CHECKSUM;
        }

        if (isMasterKey) {
          this.secret = new SecretKeyPacket(pub.publicPk, encAlgorithm, s2kUsage, s2k, iv, encData);
        } else {
          this.secret =
              new SecretSubkeyPacket(pub.publicPk, encAlgorithm, s2kUsage, s2k, iv, encData);
        }
      } else {
        if (isMasterKey) {
          this.secret =
              new SecretKeyPacket(pub.publicPk, encAlgorithm, null, null, bOut.toByteArray());
        } else {
          this.secret =
              new SecretSubkeyPacket(pub.publicPk, encAlgorithm, null, null, bOut.toByteArray());
        }
      }
    } catch (PGPException e) {
      throw e;
    } catch (Exception e) {
      throw new PGPException("Exception encrypting key", e);
    }
  }