@Override protected Cipher initCipherForBlock(Cipher cipher, int block, boolean lastChunk) throws IOException, GeneralSecurityException { flush(); EncryptionInfo ei = getEncryptionInfo(); SecretKey sk = getSecretKey(); return CryptoAPIDecryptor.initCipherForBlock(cipher, block, ei, sk, Cipher.ENCRYPT_MODE); }
/** * Initializes a cipher object for a given block index for encryption * * @param cipher may be null, otherwise the given instance is reset to the new block index * @param block the block index, e.g. the persist/slide id (hslf) * @return a new cipher object, if cipher was null, otherwise the reinitialized cipher * @throws GeneralSecurityException when the cipher can't be initialized */ public Cipher initCipherForBlock(Cipher cipher, int block) throws GeneralSecurityException { return CryptoAPIDecryptor.initCipherForBlock(cipher, block, getEncryptionInfo(), getSecretKey(), Cipher.ENCRYPT_MODE); }
@Override public Cipher initCipherForBlock(Cipher cipher, int block) throws GeneralSecurityException { EncryptionInfo ei = getEncryptionInfo(); SecretKey sk = getSecretKey(); return initCipherForBlock(cipher, block, ei, sk, Cipher.DECRYPT_MODE); }
@Override public void confirmPassword(String password, byte keySpec[], byte keySalt[], byte verifier[], byte verifierSalt[], byte integritySalt[]) { assert(verifier != null && verifierSalt != null); CryptoAPIEncryptionVerifier ver = (CryptoAPIEncryptionVerifier)getEncryptionInfo().getVerifier(); ver.setSalt(verifierSalt); SecretKey skey = CryptoAPIDecryptor.generateSecretKey(password, ver); setSecretKey(skey); try { Cipher cipher = initCipherForBlock(null, 0); byte encryptedVerifier[] = new byte[verifier.length]; cipher.update(verifier, 0, verifier.length, encryptedVerifier); ver.setEncryptedVerifier(encryptedVerifier); HashAlgorithm hashAlgo = ver.getHashAlgorithm(); MessageDigest hashAlg = CryptoFunctions.getMessageDigest(hashAlgo); byte calcVerifierHash[] = hashAlg.digest(verifier); byte encryptedVerifierHash[] = cipher.doFinal(calcVerifierHash); ver.setEncryptedVerifierHash(encryptedVerifierHash); } catch (GeneralSecurityException e) { throw new EncryptedDocumentException("Password confirmation failed", e); } }
/** * initialize the builder from a stream */ @Override public void initialize(EncryptionInfo info, LittleEndianInput dis) throws IOException { /* int hSize = */ dis.readInt(); CryptoAPIEncryptionHeader header = new CryptoAPIEncryptionHeader(dis); info.setHeader(header); info.setVerifier(new CryptoAPIEncryptionVerifier(dis, header)); CryptoAPIDecryptor dec = new CryptoAPIDecryptor(); dec.setEncryptionInfo(info); info.setDecryptor(dec); CryptoAPIEncryptor enc = new CryptoAPIEncryptor(); enc.setEncryptionInfo(info); info.setEncryptor(enc); }
CryptoAPIDocumentOutputStream bos = new CryptoAPIDocumentOutputStream(this); // NOSONAR byte buf[] = new byte[8]; bos.write(buf, 0, 8); // skip header List<StreamDescriptorEntry> descList = new ArrayList<>(); StreamDescriptorEntry descEntry = new StreamDescriptorEntry(); descEntry.block = block; descEntry.streamOffset = bos.size(); descEntry.streamName = entry.getName(); descEntry.flags = StreamDescriptorEntry.flagStream.setValue(0, 1); descEntry.reserved2 = 0; bos.setBlock(block); DocumentInputStream dis = dir.createDocumentInputStream(entry); IOUtils.copy(dis, bos); dis.close(); descEntry.streamSize = bos.size() - descEntry.streamOffset; descList.add(descEntry); int streamDescriptorArrayOffset = bos.size(); bos.setBlock(0); LittleEndian.putUInt(buf, 0, descList.size()); bos.write(buf, 0, 4); bos.write(buf, 0, 4); LittleEndian.putUInt(buf, 0, sde.streamSize);
@Override public boolean verifyPassword(String password) { EncryptionVerifier ver = getEncryptionInfo().getVerifier(); SecretKey skey = generateSecretKey(password, ver); try { Cipher cipher = initCipherForBlock(null, 0, getEncryptionInfo(), skey, Cipher.DECRYPT_MODE); byte encryptedVerifier[] = ver.getEncryptedVerifier(); byte verifier[] = new byte[encryptedVerifier.length]; cipher.update(encryptedVerifier, 0, encryptedVerifier.length, verifier); setVerifier(verifier); byte encryptedVerifierHash[] = ver.getEncryptedVerifierHash(); byte verifierHash[] = cipher.doFinal(encryptedVerifierHash); HashAlgorithm hashAlgo = ver.getHashAlgorithm(); MessageDigest hashAlg = CryptoFunctions.getMessageDigest(hashAlgo); byte calcVerifierHash[] = hashAlg.digest(verifier); if (Arrays.equals(calcVerifierHash, verifierHash)) { setSecretKey(skey); return true; } } catch (GeneralSecurityException e) { throw new EncryptedDocumentException(e); } return false; }
IOUtils.copy(dis, bos); dis.close(); CryptoAPIDocumentInputStream sbis = new CryptoAPIDocumentInputStream(this, bos.toByteArray()); LittleEndianInputStream leis = new LittleEndianInputStream(sbis); POIFSFileSystem fsOut = null; if (sbis.skip(skipN) < skipN) { throw new EOFException("buffer underrun"); sbis.setBlock(0); int encryptedStreamDescriptorCount = (int) leis.readUInt(); StreamDescriptorEntry entries[] = new StreamDescriptorEntry[encryptedStreamDescriptorCount]; for (int i = 0; i < encryptedStreamDescriptorCount; i++) { StreamDescriptorEntry entry = new StreamDescriptorEntry(); entries[i] = entry; entry.streamOffset = (int) leis.readUInt(); sbis.seek(entry.streamOffset); sbis.setBlock(entry.block); InputStream is = new BoundedInputStream(sbis, entry.streamSize); fsOut.createDocument(is, entry.streamName);
@Override public void setKeySize(int keyBits) { // Microsoft Base Cryptographic Provider is limited up to 40 bits // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375599(v=vs.85).aspx boolean found = false; for (int size : getCipherAlgorithm().allowedKeySize) { if (size == keyBits) { found = true; break; } } if (!found) { throw new EncryptedDocumentException("invalid keysize "+keyBits+" for cipher algorithm "+getCipherAlgorithm()); } super.setKeySize(keyBits); if (keyBits > 40) { setCspName("Microsoft Enhanced Cryptographic Provider v1.0"); } else { setCspName(CipherProvider.rc4.cipherProviderName); } }
@SuppressWarnings("resource") @Override public void serialize(LittleEndianOutput out) { out.writeShort(encryptionType); byte data[] = new byte[1024]; LittleEndianByteArrayOutputStream bos = new LittleEndianByteArrayOutputStream(data, 0); // NOSONAR switch (encryptionInfo.getEncryptionMode()) { case xor: ((XOREncryptionHeader)encryptionInfo.getHeader()).write(bos); ((XOREncryptionVerifier)encryptionInfo.getVerifier()).write(bos); break; case binaryRC4: out.writeShort(encryptionInfo.getVersionMajor()); out.writeShort(encryptionInfo.getVersionMinor()); ((BinaryRC4EncryptionHeader)encryptionInfo.getHeader()).write(bos); ((BinaryRC4EncryptionVerifier)encryptionInfo.getVerifier()).write(bos); break; case cryptoAPI: out.writeShort(encryptionInfo.getVersionMajor()); out.writeShort(encryptionInfo.getVersionMinor()); out.writeInt(encryptionInfo.getEncryptionFlags()); ((CryptoAPIEncryptionHeader)encryptionInfo.getHeader()).write(bos); ((CryptoAPIEncryptionVerifier)encryptionInfo.getVerifier()).write(bos); break; default: throw new EncryptedDocumentException("not supported"); } out.write(data, 0, bos.getWriteIndex()); }
public CryptoAPIDocumentInputStream(CryptoAPIDecryptor decryptor, byte buf[]) throws GeneralSecurityException { super(buf); this.decryptor = decryptor; cipher = decryptor.initCipherForBlock(null, 0); } }
public CryptoAPIDocumentOutputStream(CryptoAPIEncryptor encryptor) throws GeneralSecurityException { this.encryptor = encryptor; cipher = encryptor.initCipherForBlock(null, 0); }
@Override public ChunkedCipherInputStream getDataStream(InputStream stream, int size, int initialPos) throws IOException, GeneralSecurityException { return new CryptoAPICipherInputStream(stream, size, initialPos); }
@Override public CryptoAPICipherOutputStream getDataStream(OutputStream stream, int initialOffset) throws IOException, GeneralSecurityException { return new CryptoAPICipherOutputStream(stream); }
@Override public void confirmPassword(String password) { Random r = new SecureRandom(); byte salt[] = new byte[16]; byte verifier[] = new byte[16]; r.nextBytes(salt); r.nextBytes(verifier); confirmPassword(password, null, null, verifier, salt, null); }
@Override public void flush() throws IOException { writeChunk(false); super.flush(); } }
/** * initialize the builder from scratch */ @Override public void initialize(EncryptionInfo info, CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) { if (cipherAlgorithm == null) { cipherAlgorithm = CipherAlgorithm.rc4; } if (hashAlgorithm == null) { hashAlgorithm = HashAlgorithm.sha1; } if (keyBits == -1) { keyBits = 0x28; } assert(cipherAlgorithm == CipherAlgorithm.rc4 && hashAlgorithm == HashAlgorithm.sha1); info.setHeader(new CryptoAPIEncryptionHeader(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode)); info.setVerifier(new CryptoAPIEncryptionVerifier(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode)); CryptoAPIDecryptor dec = new CryptoAPIDecryptor(); dec.setEncryptionInfo(info); info.setDecryptor(dec); CryptoAPIEncryptor enc = new CryptoAPIEncryptor(); enc.setEncryptionInfo(info); info.setEncryptor(enc); } }
@Override protected Cipher initCipherForBlock(Cipher existing, int block) throws GeneralSecurityException { return CryptoAPIDecryptor.this.initCipherForBlock(existing, block); }
public void setBlock(int block) throws GeneralSecurityException { encryptor.initCipherForBlock(cipher, block); }
public void setBlock(int block) throws GeneralSecurityException { cipher = decryptor.initCipherForBlock(cipher, block); }