Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solution: Encryption code is obsolete and supports only Blowfish/SHA1 #339

Merged
merged 3 commits into from
Nov 28, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 49 additions & 42 deletions odfdom/src/main/java/org/odftoolkit/odfdom/pkg/OdfPackage.java
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ public class OdfPackage implements Closeable {
private OdfManifestDom mManifestDom;
private String mOldPwd;
private String mNewPwd;
private boolean isAES = true;

/* Commonly used files within the ODF Package */
public enum OdfFile {
Expand Down Expand Up @@ -1913,17 +1914,18 @@ private byte[] encryptData(byte[] data, OdfFileEntry fileEntry) {

// 3. The start key is generated: the byte sequence
// representing the password in UTF-8 is used to
// generate a 20-byte SHA1 digest.
byte[] passBytes = mNewPwd.getBytes("UTF-8");
MessageDigest md = MessageDigest.getInstance("SHA1");
// generate a 20-byte SHA-1 or a 32-byte SHA-256 digest.
byte[] passBytes = mNewPwd.getBytes(StandardCharsets.UTF_8);
MessageDigest md = MessageDigest.getInstance(isAES ? "SHA-256" : "SHA-1");
passBytes = md.digest(passBytes);

// 4. Checksum specifies a digest in BASE64 encoding
// that can be used to detect password correctness. The
// digest is build from the compressed unencrypted file.
md.reset();
md.update(compressedData, 0, (compressedDataLength > 1024 ? 1024 : compressedDataLength));
byte[] checksumBytes = new byte[20];
md.digest(checksumBytes, 0, 20);
md.update(compressedData, 0, (Math.min(compressedDataLength, 1024)));
byte[] checksumBytes = new byte[isAES ? 32 : 20];
md.digest(checksumBytes, 0, checksumBytes.length);

// 5. For each file, a 16-byte salt is generated by a random
// generator.
Expand All @@ -1932,39 +1934,36 @@ private byte[] encryptData(byte[] data, OdfFileEntry fileEntry) {
byte[] salt = new byte[16];
secureRandom.nextBytes(salt);

// char passChars[] = new String(passBytes, "UTF-8").toCharArray();
/*
* char passChars[] = new char[20]; for (int i = 0; i <
* passBytes.length; i++) { passChars[i] = (char)
* ((passBytes[i]+256)%256);
* //System.out.println("passChars[i]:"+passChars
* [i]+", passBytes[i]"+passBytes[i]); } //char passChars[] =
* getChars(passBytes); // 6. The PBKDF2 algorithm based on the
* HMAC-SHA-1 function is used for the key derivation.
* SecretKeyFactory factory =
* SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); // 7. The
* salt is used together with the start key to derive a unique
* 128-bit key for each file. // The default iteration count for the
* algorithm is 1024. KeySpec spec = new PBEKeySpec(passChars, salt,
* 1024, 128); SecretKey skey = factory.generateSecret(spec); byte[]
* raw = skey.getEncoded(); // algorithm-name="Blowfish CFB"
* SecretKeySpec skeySpec = new SecretKeySpec(raw, "Blowfish");
*/
byte[] dk = derivePBKDF2Key(passBytes, salt, 1024, 16);
SecretKeySpec key = new SecretKeySpec(dk, "Blowfish");
// 8.The files are encrypted: The random number
// generator is used to generate the 8-byte initialization vector
// for the
// algorithm. The derived key is used together with the
// initialization
// vector to encrypt the file using the Blowfish algorithm in cipher
// feedback
// CFB mode.
Cipher cipher = Cipher.getInstance("Blowfish/CFB/NoPadding");
// 6-7. Key derivation:
// The PBKDF2 algorithm based on the HMAC-SHA-1 function is used for the key derivation.
SecretKeySpec key;
if (isAES) {
// The salt is used together with the start key to derive a unique 2048-bit key for each
// file.
// The default iteration count for the algorithm is 100000.
PBEParametersGenerator generator = new PKCS5S2ParametersGenerator(new SHA1Digest());
generator.init(passBytes, salt, 100000);
KeyParameter keyParam = (KeyParameter) generator.generateDerivedParameters(256);
key = new SecretKeySpec(keyParam.getKey(), "AES");
} else {
// The salt is used together with the start key to derive a unique 128-bit key for each
// file.
// The default iteration count for the algorithm is 1024.
byte[] dk = derivePBKDF2Key(passBytes, salt, 1024, 16);
key = new SecretKeySpec(dk, "Blowfish");
}

// 8. The files are encrypted:
// The random number generator is used to generate the 8-byte initialization vector
// for the algorithm. The derived key is used together with the initialization
// vector to encrypt the file using the Blowfish algorithm in cipher feedback
// CFB/CBC mode.
Cipher cipher =
Cipher.getInstance(isAES ? "AES/CBC/ISO10126Padding" : "Blowfish/CFB/NoPadding");
// initialisation-vector specifies the byte-sequence used
// as an initialization vector to a encryption algorithm. The
// initialization vector is a BASE64 encoded binary sequence.
byte[] iv = new byte[8];
byte[] iv = new byte[isAES ? 16 : 8];
secureRandom.nextBytes(iv);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);
Expand All @@ -1978,28 +1977,36 @@ private byte[] encryptData(byte[] data, OdfFileEntry fileEntry) {
if (encryptionDataElement != null) {
fileEntryElement.removeChild(encryptionDataElement);
}
encryptionDataElement = fileEntryElement.newEncryptionDataElement(checksum, "SHA1/1K");
encryptionDataElement =
fileEntryElement.newEncryptionDataElement(
checksum,
isAES ? "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0#sha256-1k" : "SHA1/1K");
String initialisationVector = new Base64Binary(iv).toString();
AlgorithmElement algorithmElement =
OdfElement.findFirstChildNode(AlgorithmElement.class, encryptionDataElement);
if (algorithmElement != null) {
encryptionDataElement.removeChild(algorithmElement);
}
algorithmElement =
encryptionDataElement.newAlgorithmElement("Blowfish CFB", initialisationVector);
encryptionDataElement.newAlgorithmElement(
isAES ? "http://www.w3.org/2001/04/xmlenc#aes256-cbc" : "Blowfish CFB",
initialisationVector);
String saltStr = new Base64Binary(salt).toString();
KeyDerivationElement keyDerivationElement =
OdfElement.findFirstChildNode(KeyDerivationElement.class, encryptionDataElement);
if (keyDerivationElement != null) {
encryptionDataElement.removeChild(keyDerivationElement);
}
keyDerivationElement = encryptionDataElement.newKeyDerivationElement(1024, "PBKDF2", saltStr);
keyDerivationElement =
encryptionDataElement.newKeyDerivationElement(isAES ? 100000 : 1024, "PBKDF2", saltStr);
StartKeyGenerationElement startKeyGenerationElement =
OdfElement.findFirstChildNode(StartKeyGenerationElement.class, encryptionDataElement);
if (startKeyGenerationElement != null) {
encryptionDataElement.removeChild(startKeyGenerationElement);
}
encryptionDataElement.newStartKeyGenerationElement("SHA1").setKeySizeAttribute(20);
encryptionDataElement
.newStartKeyGenerationElement(isAES ? "http://www.w3.org/2000/09/xmldsig#sha256" : "SHA1")
.setKeySizeAttribute(isAES ? 32 : 20);

// System.out.println("full-path=\""+ path +"\"");
// System.out.println("size=\""+ data.length +"\"");
Expand Down Expand Up @@ -2033,7 +2040,7 @@ private byte[] decryptData(
byte[] passBytes = mOldPwd.getBytes(StandardCharsets.UTF_8);

String algorithm = algorithmElement.getAlgorithmNameAttribute();
boolean isAES = algorithm.contains("aes256-cbc") || algorithm.contains("AES-256-CBC");
isAES = algorithm.contains("aes256-cbc") || algorithm.contains("AES-256-CBC");

SecretKeySpec key;
Cipher cipher;
Expand All @@ -2047,7 +2054,7 @@ private byte[] decryptData(
generator.init(passBytes, salt, 100000);
KeyParameter keyParam = (KeyParameter) generator.generateDerivedParameters(256);
key = new SecretKeySpec(keyParam.getKey(), "AES");
cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher = Cipher.getInstance("AES/CBC/ISO10126Padding");
md.reset();
} else {
// Blowfish
Expand Down