private byte[] fetchSymmetricKeyData(PGPPrivateKey privKey, Provider asymProvider)
      throws PGPException {
    Cipher c1 = getKeyCipher(keyData.getAlgorithm(), asymProvider);

    try {
      c1.init(Cipher.DECRYPT_MODE, privKey.getKey());
    } catch (InvalidKeyException e) {
      throw new PGPException("error setting asymmetric cipher", e);
    }

    BigInteger[] keyD = keyData.getEncSessionKey();

    if (keyData.getAlgorithm() == PGPPublicKey.RSA_ENCRYPT
        || keyData.getAlgorithm() == PGPPublicKey.RSA_GENERAL) {
      byte[] bi = keyD[0].toByteArray();

      if (bi[0] == 0) {
        c1.update(bi, 1, bi.length - 1);
      } else {
        c1.update(bi);
      }
    } else {
      ElGamalKey k = (ElGamalKey) privKey.getKey();
      int size = (k.getParameters().getP().bitLength() + 7) / 8;
      byte[] tmp = new byte[size];

      byte[] bi = keyD[0].toByteArray();
      if (bi.length > size) {
        c1.update(bi, 1, bi.length - 1);
      } else {
        System.arraycopy(bi, 0, tmp, tmp.length - bi.length, bi.length);
        c1.update(tmp);
      }

      bi = keyD[1].toByteArray();
      for (int i = 0; i != tmp.length; i++) {
        tmp[i] = 0;
      }

      if (bi.length > size) {
        c1.update(bi, 1, bi.length - 1);
      } else {
        System.arraycopy(bi, 0, tmp, tmp.length - bi.length, bi.length);
        c1.update(tmp);
      }
    }

    byte[] plain;
    try {
      plain = c1.doFinal();
    } catch (Exception e) {
      throw new PGPException("exception decrypting secret key", e);
    }

    if (!confirmCheckSum(plain)) {
      throw new PGPKeyValidationException("key checksum failed");
    }

    return plain;
  }
Esempio n. 2
0
  private static SecretKeyPacket buildSecretKeyPacket(
      boolean isMasterKey,
      PGPPrivateKey privKey,
      PGPPublicKey pubKey,
      PBESecretKeyEncryptor keyEncryptor,
      PGPDigestCalculator checksumCalculator)
      throws PGPException {
    BCPGObject secKey = (BCPGObject) privKey.getPrivateKeyDataPacket();

    if (secKey == null) {
      if (isMasterKey) {
        return new SecretKeyPacket(
            pubKey.publicPk, SymmetricKeyAlgorithmTags.NULL, null, null, new byte[0]);
      } else {
        return new SecretSubkeyPacket(
            pubKey.publicPk, SymmetricKeyAlgorithmTags.NULL, null, null, new byte[0]);
      }
    }

    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 != null) ? keyEncryptor.getAlgorithm() : SymmetricKeyAlgorithmTags.NULL;

      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) {
          return new SecretKeyPacket(pubKey.publicPk, encAlgorithm, s2kUsage, s2k, iv, encData);
        } else {
          return new SecretSubkeyPacket(pubKey.publicPk, encAlgorithm, s2kUsage, s2k, iv, encData);
        }
      } else {
        if (isMasterKey) {
          return new SecretKeyPacket(pubKey.publicPk, encAlgorithm, null, null, bOut.toByteArray());
        } else {
          return new SecretSubkeyPacket(
              pubKey.publicPk, encAlgorithm, null, null, bOut.toByteArray());
        }
      }
    } catch (PGPException e) {
      throw e;
    } catch (Exception e) {
      throw new PGPException("Exception encrypting key", e);
    }
  }