Search in sources :

Example 66 with Cipher

use of javax.crypto.Cipher in project poi by apache.

the class StandardDecryptor method verifyPassword.

@Override
public boolean verifyPassword(String password) {
    EncryptionVerifier ver = getEncryptionInfo().getVerifier();
    SecretKey skey = generateSecretKey(password, ver, getKeySizeInBytes());
    Cipher cipher = getCipher(skey);
    try {
        byte[] encryptedVerifier = ver.getEncryptedVerifier();
        byte[] verifier = cipher.doFinal(encryptedVerifier);
        setVerifier(verifier);
        MessageDigest sha1 = CryptoFunctions.getMessageDigest(ver.getHashAlgorithm());
        byte[] calcVerifierHash = sha1.digest(verifier);
        byte[] encryptedVerifierHash = ver.getEncryptedVerifierHash();
        byte[] decryptedVerifierHash = cipher.doFinal(encryptedVerifierHash);
        // see 2.3.4.9 Password Verification (Standard Encryption)
        // ... The number of bytes used by the encrypted Verifier hash MUST be 32 ...
        // TODO: check and trim/pad the hashes to 32
        byte[] verifierHash = Arrays.copyOf(decryptedVerifierHash, calcVerifierHash.length);
        if (Arrays.equals(calcVerifierHash, verifierHash)) {
            setSecretKey(skey);
            return true;
        } else {
            return false;
        }
    } catch (GeneralSecurityException e) {
        throw new EncryptedDocumentException(e);
    }
}
Also used : EncryptionVerifier(org.apache.poi.poifs.crypt.EncryptionVerifier) SecretKey(javax.crypto.SecretKey) EncryptedDocumentException(org.apache.poi.EncryptedDocumentException) GeneralSecurityException(java.security.GeneralSecurityException) Cipher(javax.crypto.Cipher) MessageDigest(java.security.MessageDigest)

Example 67 with Cipher

use of javax.crypto.Cipher in project poi by apache.

the class AgileEncryptor method updateIntegrityHMAC.

/**
     * Generate an HMAC, as specified in [RFC2104], of the encrypted form of the data (message), 
     * which the DataIntegrity element will verify by using the Salt generated in step 2 as the key. 
     * Note that the entire EncryptedPackage stream (1), including the StreamSize field, MUST be 
     * used as the message.
     * 
     * Encrypt the HMAC as in step 3 by using a blockKey byte array consisting of the following bytes:
     * 0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, and 0x33.
     **/
protected void updateIntegrityHMAC(File tmpFile, int oleStreamSize) throws GeneralSecurityException, IOException {
    // as the integrity hmac needs to contain the StreamSize,
    // it's not possible to calculate it on-the-fly while buffering
    // TODO: add stream size parameter to getDataStream()
    AgileEncryptionHeader header = (AgileEncryptionHeader) getEncryptionInfo().getHeader();
    int blockSize = header.getBlockSize();
    HashAlgorithm hashAlgo = header.getHashAlgorithm();
    Mac integrityMD = CryptoFunctions.getMac(hashAlgo);
    byte[] hmacKey = getBlock0(this.integritySalt, getNextBlockSize(this.integritySalt.length, blockSize));
    integrityMD.init(new SecretKeySpec(hmacKey, hashAlgo.jceHmacId));
    byte[] buf = new byte[1024];
    LittleEndian.putLong(buf, 0, oleStreamSize);
    integrityMD.update(buf, 0, LittleEndianConsts.LONG_SIZE);
    InputStream fis = new FileInputStream(tmpFile);
    try {
        int readBytes;
        while ((readBytes = fis.read(buf)) != -1) {
            integrityMD.update(buf, 0, readBytes);
        }
    } finally {
        fis.close();
    }
    byte[] hmacValue = integrityMD.doFinal();
    byte[] hmacValueFilled = getBlock0(hmacValue, getNextBlockSize(hmacValue.length, blockSize));
    byte[] iv = CryptoFunctions.generateIv(header.getHashAlgorithm(), header.getKeySalt(), kIntegrityValueBlock, blockSize);
    Cipher cipher = CryptoFunctions.getCipher(getSecretKey(), header.getCipherAlgorithm(), header.getChainingMode(), iv, Cipher.ENCRYPT_MODE);
    byte[] encryptedHmacValue = cipher.doFinal(hmacValueFilled);
    header.setEncryptedHmacValue(encryptedHmacValue);
}
Also used : SecretKeySpec(javax.crypto.spec.SecretKeySpec) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) Cipher(javax.crypto.Cipher) CryptoFunctions.getCipher(org.apache.poi.poifs.crypt.CryptoFunctions.getCipher) Mac(javax.crypto.Mac) FileInputStream(java.io.FileInputStream) STHashAlgorithm(com.microsoft.schemas.office.x2006.encryption.STHashAlgorithm) HashAlgorithm(org.apache.poi.poifs.crypt.HashAlgorithm)

Example 68 with Cipher

use of javax.crypto.Cipher in project poi by apache.

the class AgileEncryptor method confirmPassword.

@Override
public void confirmPassword(String password, byte[] keySpec, byte[] keySalt, byte[] verifier, byte[] verifierSalt, byte[] integritySalt) {
    AgileEncryptionVerifier ver = (AgileEncryptionVerifier) getEncryptionInfo().getVerifier();
    AgileEncryptionHeader header = (AgileEncryptionHeader) getEncryptionInfo().getHeader();
    ver.setSalt(verifierSalt);
    header.setKeySalt(keySalt);
    int blockSize = header.getBlockSize();
    pwHash = hashPassword(password, ver.getHashAlgorithm(), verifierSalt, ver.getSpinCount());
    /**
         * encryptedVerifierHashInput: This attribute MUST be generated by using the following steps:
         * 1. Generate a random array of bytes with the number of bytes used specified by the saltSize
         *    attribute.
         * 2. Generate an encryption key as specified in section 2.3.4.11 by using the user-supplied password,
         *    the binary byte array used to create the saltValue attribute, and a blockKey byte array
         *    consisting of the following bytes: 0xfe, 0xa7, 0xd2, 0x76, 0x3b, 0x4b, 0x9e, and 0x79.
         * 3. Encrypt the random array of bytes generated in step 1 by using the binary form of the saltValue
         *    attribute as an initialization vector as specified in section 2.3.4.12. If the array of bytes is not an
         *    integral multiple of blockSize bytes, pad the array with 0x00 to the next integral multiple of
         *    blockSize bytes.
         * 4. Use base64 to encode the result of step 3.
         */
    byte[] encryptedVerifier = hashInput(ver, pwHash, kVerifierInputBlock, verifier, Cipher.ENCRYPT_MODE);
    ver.setEncryptedVerifier(encryptedVerifier);
    /**
         * encryptedVerifierHashValue: This attribute MUST be generated by using the following steps:
         * 1. Obtain the hash value of the random array of bytes generated in step 1 of the steps for
         *    encryptedVerifierHashInput.
         * 2. Generate an encryption key as specified in section 2.3.4.11 by using the user-supplied password,
         *    the binary byte array used to create the saltValue attribute, and a blockKey byte array
         *    consisting of the following bytes: 0xd7, 0xaa, 0x0f, 0x6d, 0x30, 0x61, 0x34, and 0x4e.
         * 3. Encrypt the hash value obtained in step 1 by using the binary form of the saltValue attribute as
         *    an initialization vector as specified in section 2.3.4.12. If hashSize is not an integral multiple of
         *    blockSize bytes, pad the hash value with 0x00 to an integral multiple of blockSize bytes.
         * 4. Use base64 to encode the result of step 3.
         */
    MessageDigest hashMD = getMessageDigest(ver.getHashAlgorithm());
    byte[] hashedVerifier = hashMD.digest(verifier);
    byte[] encryptedVerifierHash = hashInput(ver, pwHash, kHashedVerifierBlock, hashedVerifier, Cipher.ENCRYPT_MODE);
    ver.setEncryptedVerifierHash(encryptedVerifierHash);
    /**
         * encryptedKeyValue: This attribute MUST be generated by using the following steps:
         * 1. Generate a random array of bytes that is the same size as specified by the
         *    Encryptor.KeyData.keyBits attribute of the parent element.
         * 2. Generate an encryption key as specified in section 2.3.4.11, using the user-supplied password,
         *    the binary byte array used to create the saltValue attribute, and a blockKey byte array
         *    consisting of the following bytes: 0x14, 0x6e, 0x0b, 0xe7, 0xab, 0xac, 0xd0, and 0xd6.
         * 3. Encrypt the random array of bytes generated in step 1 by using the binary form of the saltValue
         *    attribute as an initialization vector as specified in section 2.3.4.12. If the array of bytes is not an
         *    integral multiple of blockSize bytes, pad the array with 0x00 to an integral multiple of
         *    blockSize bytes.
         * 4. Use base64 to encode the result of step 3.
         */
    byte[] encryptedKey = hashInput(ver, pwHash, kCryptoKeyBlock, keySpec, Cipher.ENCRYPT_MODE);
    ver.setEncryptedKey(encryptedKey);
    SecretKey secretKey = new SecretKeySpec(keySpec, header.getCipherAlgorithm().jceId);
    setSecretKey(secretKey);
    /*
         * 2.3.4.14 DataIntegrity Generation (Agile Encryption)
         * 
         * The DataIntegrity element contained within an Encryption element MUST be generated by using
         * the following steps:
         * 1. Obtain the intermediate key by decrypting the encryptedKeyValue from a KeyEncryptor
         *    contained within the KeyEncryptors sequence. Use this key for encryption operations in the
         *    remaining steps of this section.
         * 2. Generate a random array of bytes, known as Salt, of the same length as the value of the
         *    KeyData.hashSize attribute.
         * 3. Encrypt the random array of bytes generated in step 2 by using the binary form of the
         *    KeyData.saltValue attribute and a blockKey byte array consisting of the following bytes:
         *    0x5f, 0xb2, 0xad, 0x01, 0x0c, 0xb9, 0xe1, and 0xf6 used to form an initialization vector as
         *    specified in section 2.3.4.12. If the array of bytes is not an integral multiple of blockSize
         *    bytes, pad the array with 0x00 to the next integral multiple of blockSize bytes.
         * 4. Assign the encryptedHmacKey attribute to the base64-encoded form of the result of step 3.
         * 5. Generate an HMAC, as specified in [RFC2104], of the encrypted form of the data (message),
         *    which the DataIntegrity element will verify by using the Salt generated in step 2 as the key.
         *    Note that the entire EncryptedPackage stream (1), including the StreamSize field, MUST be
         *    used as the message.
         * 6. Encrypt the HMAC as in step 3 by using a blockKey byte array consisting of the following bytes:
         *    0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, and 0x33.
         * 7.  Assign the encryptedHmacValue attribute to the base64-encoded form of the result of step 6. 
         */
    this.integritySalt = integritySalt.clone();
    try {
        byte[] vec = CryptoFunctions.generateIv(header.getHashAlgorithm(), header.getKeySalt(), kIntegrityKeyBlock, header.getBlockSize());
        Cipher cipher = getCipher(secretKey, header.getCipherAlgorithm(), header.getChainingMode(), vec, Cipher.ENCRYPT_MODE);
        byte[] hmacKey = getBlock0(this.integritySalt, getNextBlockSize(this.integritySalt.length, blockSize));
        byte[] encryptedHmacKey = cipher.doFinal(hmacKey);
        header.setEncryptedHmacKey(encryptedHmacKey);
        cipher = Cipher.getInstance("RSA");
        for (AgileCertificateEntry ace : ver.getCertificates()) {
            cipher.init(Cipher.ENCRYPT_MODE, ace.x509.getPublicKey());
            ace.encryptedKey = cipher.doFinal(getSecretKey().getEncoded());
            Mac x509Hmac = CryptoFunctions.getMac(header.getHashAlgorithm());
            x509Hmac.init(getSecretKey());
            ace.certVerifier = x509Hmac.doFinal(ace.x509.getEncoded());
        }
    } catch (GeneralSecurityException e) {
        throw new EncryptedDocumentException(e);
    }
}
Also used : AgileCertificateEntry(org.apache.poi.poifs.crypt.agile.AgileEncryptionVerifier.AgileCertificateEntry) SecretKey(javax.crypto.SecretKey) EncryptedDocumentException(org.apache.poi.EncryptedDocumentException) SecretKeySpec(javax.crypto.spec.SecretKeySpec) GeneralSecurityException(java.security.GeneralSecurityException) Cipher(javax.crypto.Cipher) CryptoFunctions.getCipher(org.apache.poi.poifs.crypt.CryptoFunctions.getCipher) MessageDigest(java.security.MessageDigest) CryptoFunctions.getMessageDigest(org.apache.poi.poifs.crypt.CryptoFunctions.getMessageDigest) Mac(javax.crypto.Mac)

Example 69 with Cipher

use of javax.crypto.Cipher in project poi by apache.

the class SignatureInfo method signDigest.

/**
     * Sign (encrypt) the digest with the private key.
     * Currently only rsa is supported.
     *
     * @param digest the hashed input
     * @return the encrypted hash
     */
public byte[] signDigest(byte[] digest) {
    Cipher cipher = CryptoFunctions.getCipher(signatureConfig.getKey(), CipherAlgorithm.rsa, ChainingMode.ecb, null, Cipher.ENCRYPT_MODE, "PKCS1Padding");
    try {
        ByteArrayOutputStream digestInfoValueBuf = new ByteArrayOutputStream();
        digestInfoValueBuf.write(signatureConfig.getHashMagic());
        digestInfoValueBuf.write(digest);
        byte[] digestInfoValue = digestInfoValueBuf.toByteArray();
        byte[] signatureValue = cipher.doFinal(digestInfoValue);
        return signatureValue;
    } catch (Exception e) {
        throw new EncryptedDocumentException(e);
    }
}
Also used : EncryptedDocumentException(org.apache.poi.EncryptedDocumentException) Cipher(javax.crypto.Cipher) ByteArrayOutputStream(java.io.ByteArrayOutputStream) XPathExpressionException(javax.xml.xpath.XPathExpressionException) GeneralSecurityException(java.security.GeneralSecurityException) InvalidFormatException(org.apache.poi.openxml4j.exceptions.InvalidFormatException) SAXException(org.xml.sax.SAXException) MarshalException(javax.xml.crypto.MarshalException) XMLSignatureException(javax.xml.crypto.dsig.XMLSignatureException) NoSuchElementException(java.util.NoSuchElementException) IOException(java.io.IOException) XmlException(org.apache.xmlbeans.XmlException) EncryptedDocumentException(org.apache.poi.EncryptedDocumentException)

Example 70 with Cipher

use of javax.crypto.Cipher in project poi by apache.

the class AesZipFileZipEntrySource method copyToFile.

private static void copyToFile(InputStream is, File tmpFile, CipherAlgorithm cipherAlgorithm, byte[] keyBytes, byte[] ivBytes) throws IOException, GeneralSecurityException {
    SecretKeySpec skeySpec = new SecretKeySpec(keyBytes, cipherAlgorithm.jceId);
    Cipher ciEnc = CryptoFunctions.getCipher(skeySpec, cipherAlgorithm, ChainingMode.cbc, ivBytes, Cipher.ENCRYPT_MODE, "PKCS5Padding");
    ZipInputStream zis = new ZipInputStream(is);
    FileOutputStream fos = new FileOutputStream(tmpFile);
    ZipOutputStream zos = new ZipOutputStream(fos);
    ZipEntry ze;
    while ((ze = zis.getNextEntry()) != null) {
        // the cipher output stream pads the data, therefore we can't reuse the ZipEntry with set sizes
        // as those will be validated upon close()
        ZipEntry zeNew = new ZipEntry(ze.getName());
        zeNew.setComment(ze.getComment());
        zeNew.setExtra(ze.getExtra());
        zeNew.setTime(ze.getTime());
        // zeNew.setMethod(ze.getMethod());
        zos.putNextEntry(zeNew);
        FilterOutputStream fos2 = new FilterOutputStream(zos) {

            // don't close underlying ZipOutputStream
            @Override
            public void close() {
            }
        };
        CipherOutputStream cos = new CipherOutputStream(fos2, ciEnc);
        IOUtils.copy(zis, cos);
        cos.close();
        fos2.close();
        zos.closeEntry();
        zis.closeEntry();
    }
    zos.close();
    fos.close();
    zis.close();
}
Also used : ZipInputStream(java.util.zip.ZipInputStream) CipherOutputStream(javax.crypto.CipherOutputStream) SecretKeySpec(javax.crypto.spec.SecretKeySpec) ZipOutputStream(java.util.zip.ZipOutputStream) FileOutputStream(java.io.FileOutputStream) ZipEntry(java.util.zip.ZipEntry) Cipher(javax.crypto.Cipher) FilterOutputStream(java.io.FilterOutputStream)

Aggregations

Cipher (javax.crypto.Cipher)1531 SecretKeySpec (javax.crypto.spec.SecretKeySpec)516 SecretKey (javax.crypto.SecretKey)377 IvParameterSpec (javax.crypto.spec.IvParameterSpec)368 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)349 InvalidKeyException (java.security.InvalidKeyException)257 IOException (java.io.IOException)202 NoSuchPaddingException (javax.crypto.NoSuchPaddingException)202 IllegalBlockSizeException (javax.crypto.IllegalBlockSizeException)196 BadPaddingException (javax.crypto.BadPaddingException)183 GeneralSecurityException (java.security.GeneralSecurityException)161 SecretKeyFactory (javax.crypto.SecretKeyFactory)149 Key (java.security.Key)148 InvalidAlgorithmParameterException (java.security.InvalidAlgorithmParameterException)134 SecureRandom (java.security.SecureRandom)105 PrivateKey (java.security.PrivateKey)93 PublicKey (java.security.PublicKey)86 UnsupportedEncodingException (java.io.UnsupportedEncodingException)84 PBEKeySpec (javax.crypto.spec.PBEKeySpec)82 KeyGenerator (javax.crypto.KeyGenerator)78