/* ==================================================================== | |
Licensed to the Apache Software Foundation (ASF) under one or more | |
contributor license agreements. See the NOTICE file distributed with | |
this work for additional information regarding copyright ownership. | |
The ASF licenses this file to You under the Apache License, Version 2.0 | |
(the "License"); you may not use this file except in compliance with | |
the License. You may obtain a copy of the License at | |
http://www.apache.org/licenses/LICENSE-2.0 | |
Unless required by applicable law or agreed to in writing, software | |
distributed under the License is distributed on an "AS IS" BASIS, | |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
See the License for the specific language governing permissions and | |
limitations under the License. | |
==================================================================== */ | |
package org.apache.poi.poifs.crypt.agile; | |
import org.apache.poi.EncryptedDocumentException; | |
import org.apache.poi.poifs.crypt.ChainingMode; | |
import org.apache.poi.poifs.crypt.CipherAlgorithm; | |
import org.apache.poi.poifs.crypt.EncryptionHeader; | |
import org.apache.poi.poifs.crypt.HashAlgorithm; | |
import com.microsoft.schemas.office.x2006.encryption.CTDataIntegrity; | |
import com.microsoft.schemas.office.x2006.encryption.CTKeyData; | |
import com.microsoft.schemas.office.x2006.encryption.EncryptionDocument; | |
import com.microsoft.schemas.office.x2006.encryption.STCipherChaining; | |
public class AgileEncryptionHeader extends EncryptionHeader implements Cloneable { | |
private byte encryptedHmacKey[], encryptedHmacValue[]; | |
public AgileEncryptionHeader(String descriptor) { | |
this(AgileEncryptionInfoBuilder.parseDescriptor(descriptor)); | |
} | |
protected AgileEncryptionHeader(EncryptionDocument ed) { | |
CTKeyData keyData; | |
try { | |
keyData = ed.getEncryption().getKeyData(); | |
if (keyData == null) { | |
throw new NullPointerException("keyData not set"); | |
} | |
} catch (Exception e) { | |
throw new EncryptedDocumentException("Unable to parse keyData"); | |
} | |
int keyBits = (int)keyData.getKeyBits(); | |
CipherAlgorithm ca = CipherAlgorithm.fromXmlId(keyData.getCipherAlgorithm().toString(), keyBits); | |
setCipherAlgorithm(ca); | |
setCipherProvider(ca.provider); | |
setKeySize(keyBits); | |
setFlags(0); | |
setSizeExtra(0); | |
setCspName(null); | |
setBlockSize(keyData.getBlockSize()); | |
switch (keyData.getCipherChaining().intValue()) { | |
case STCipherChaining.INT_CHAINING_MODE_CBC: | |
setChainingMode(ChainingMode.cbc); | |
break; | |
case STCipherChaining.INT_CHAINING_MODE_CFB: | |
setChainingMode(ChainingMode.cfb); | |
break; | |
default: | |
throw new EncryptedDocumentException("Unsupported chaining mode - "+keyData.getCipherChaining().toString()); | |
} | |
int hashSize = keyData.getHashSize(); | |
HashAlgorithm ha = HashAlgorithm.fromEcmaId(keyData.getHashAlgorithm().toString()); | |
setHashAlgorithm(ha); | |
if (getHashAlgorithm().hashSize != hashSize) { | |
throw new EncryptedDocumentException("Unsupported hash algorithm: " + | |
keyData.getHashAlgorithm() + " @ " + hashSize + " bytes"); | |
} | |
int saltLength = keyData.getSaltSize(); | |
setKeySalt(keyData.getSaltValue()); | |
if (getKeySalt().length != saltLength) { | |
throw new EncryptedDocumentException("Invalid salt length"); | |
} | |
CTDataIntegrity di = ed.getEncryption().getDataIntegrity(); | |
setEncryptedHmacKey(di.getEncryptedHmacKey()); | |
setEncryptedHmacValue(di.getEncryptedHmacValue()); | |
} | |
public AgileEncryptionHeader(CipherAlgorithm algorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) { | |
setCipherAlgorithm(algorithm); | |
setHashAlgorithm(hashAlgorithm); | |
setKeySize(keyBits); | |
setBlockSize(blockSize); | |
setChainingMode(chainingMode); | |
} | |
// make method visible for this package | |
@Override | |
protected void setKeySalt(byte salt[]) { | |
if (salt == null || salt.length != getBlockSize()) { | |
throw new EncryptedDocumentException("invalid verifier salt"); | |
} | |
super.setKeySalt(salt); | |
} | |
public byte[] getEncryptedHmacKey() { | |
return encryptedHmacKey; | |
} | |
protected void setEncryptedHmacKey(byte[] encryptedHmacKey) { | |
this.encryptedHmacKey = (encryptedHmacKey == null) ? null : encryptedHmacKey.clone(); | |
} | |
public byte[] getEncryptedHmacValue() { | |
return encryptedHmacValue; | |
} | |
protected void setEncryptedHmacValue(byte[] encryptedHmacValue) { | |
this.encryptedHmacValue = (encryptedHmacValue == null) ? null : encryptedHmacValue.clone(); | |
} | |
@Override | |
public AgileEncryptionHeader clone() throws CloneNotSupportedException { | |
AgileEncryptionHeader other = (AgileEncryptionHeader)super.clone(); | |
other.encryptedHmacKey = (encryptedHmacKey == null) ? null : encryptedHmacKey.clone(); | |
other.encryptedHmacValue = (encryptedHmacValue == null) ? null : encryptedHmacValue.clone(); | |
return other; | |
} | |
} |