ASF Bugzilla – Attachment 24106 Details for
Bug 47652
[PATCH] Initial support for encrypted workbooks
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
src/java/org/apache/poi/hssf/record/RC4Header.java
RC4Header.java (text/x-java), 4.01 KB, created by
Maxim Valyanskiy
on 2009-08-06 02:58:22 UTC
(
hide
)
Description:
src/java/org/apache/poi/hssf/record/RC4Header.java
Filename:
MIME Type:
Creator:
Maxim Valyanskiy
Created:
2009-08-06 02:58:22 UTC
Size:
4.01 KB
patch
obsolete
>package org.apache.poi.hssf.record; > >import javax.crypto.Cipher; >import javax.crypto.SecretKey; >import javax.crypto.spec.SecretKeySpec; >import java.io.UnsupportedEncodingException; >import java.security.GeneralSecurityException; >import java.security.InvalidKeyException; >import java.security.MessageDigest; >import java.util.Arrays; > >/* >Implementation based on >[MS-OFFCRYPTO] â v20090708 >Office Document Cryptography Structure Specification > */ >public class RC4Header { > private final byte[] salt = new byte[16]; > private final byte[] encryptedVerifier = new byte[16]; > private final byte[] encryptedVerifierHash = new byte[16]; > > private final Cipher rc4; > private final MessageDigest md5; > > /* > Excel uses encryption when you choose certain "protection" settings even without > a password. In this case the password used is "VelvetSweatshop", but Excel will > try that automatically instead of prompting for a password. > */ > private static final String FIXED_PASSWORD = "VelvetSweatshop"; > private static String password = FIXED_PASSWORD; > > public static final int BLOCK_SIZE = 1024; > > public RC4Header(RecordInputStream in) { > int minor = in.readShort(); > > if (minor!=1) { > throw new RecordFormatException("Unexpected VersionInfo number for RC4Header"); > } > > in.readFully(salt, 0, 16); > in.readFully(encryptedVerifier, 0, 16); > in.readFully(encryptedVerifierHash, 0, 16); > > try { > rc4 = Cipher.getInstance("RC4"); > md5 = MessageDigest.getInstance("MD5"); > > SecretKey key = getKey(password, 0); > > if (!verifyKey(key)) { > throw new RecordFormatException("Document encrypted, need password"); > } > } catch (GeneralSecurityException e) { > throw new RecordFormatException("Can't create RC4 cipher", e); > } > } > > private SecretKey getKey(String password, int blockNumber) { > try { > byte[] h0 = md5.digest(password.getBytes("UTF-16LE")); > > byte[] truncatedHash = Arrays.copyOf(h0, 5); > byte[] intermediateBuffer = new byte[336]; > > for (int i=0; i<16; i++) { > System.arraycopy(truncatedHash, 0, intermediateBuffer, i*21, 5); > System.arraycopy(salt, 0, intermediateBuffer, i*21+5, 16); > } > > byte[] h1 = md5.digest(intermediateBuffer); > > byte[] key = Arrays.copyOf(h1, 5); > > byte[] finalData = new byte[5+4]; > > System.arraycopy(key, 0, finalData, 0, 5); > > byte[] block = new byte[4]; > block[0] = (byte) (blockNumber & 0xFF); > block[1] = (byte) ((blockNumber >> 8) & 0xFF); > block[2] = (byte) ((blockNumber >> 16) & 0xFF); > block[3] = (byte) ((blockNumber >> 24) & 0xFF); > > System.arraycopy(block, 0, finalData, 5, 4); > > byte[] hFinal = md5.digest(finalData); > > byte[] encryptionKey = Arrays.copyOf(hFinal, 16); > > return new SecretKeySpec(encryptionKey, "RC4"); > } catch (UnsupportedEncodingException e) { > throw new RuntimeException(e); // can't happen > } > } > > private boolean verifyKey(SecretKey key) throws InvalidKeyException { > rc4.init(Cipher.DECRYPT_MODE, key); > byte[] verifier = rc4.update(encryptedVerifier); > byte[] verifierHash = rc4.update(encryptedVerifierHash); > > byte[] expectedVerifierHash = md5.digest(verifier); > > return Arrays.equals(expectedVerifierHash, verifierHash); > } > > public Cipher createCypher(int blockNumber) { > SecretKey key = getKey(password, blockNumber); > try { > rc4.init(Cipher.DECRYPT_MODE, key); > } catch (InvalidKeyException e) { > throw new RuntimeException(e); > } > > return rc4; > } > > public static void setPassword(String password) { > if (password==null) { > RC4Header.password = FIXED_PASSWORD; > } else { > RC4Header.password = password; > } > } >}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 47652
:
24105
| 24106 |
24107
|
24108
|
24136