garydgregory commented on code in PR #332:
URL: https://github.com/apache/commons-compress/pull/332#discussion_r1037737611
##########
src/main/java/org/apache/commons/compress/archivers/sevenz/AES256SHA256Decoder.java:
##########
@@ -126,4 +115,121 @@ public void close() throws IOException {
}
};
}
+
+ @Override
+ OutputStream encode(OutputStream out, Object options) throws IOException {
+ AES256Options opts = (AES256Options) options;
+ final byte[] aesKeyBytes = sha256Password(opts.password,
opts.numCyclesPower, opts.salt);
+ final SecretKey aesKey = new SecretKeySpec(aesKeyBytes, "AES");
+
+ final Cipher cipher;
+ try {
+ cipher = Cipher.getInstance("AES/CBC/NoPadding");
+ cipher.init(Cipher.ENCRYPT_MODE, aesKey, new
IvParameterSpec(opts.iv));
+ } catch (final GeneralSecurityException generalSecurityException) {
+ throw new IOException(
+ "Encryption error " + "(do you have the JCE Unlimited Strength
Jurisdiction Policy Files installed?)",
+ generalSecurityException
+ );
+ }
+ return new OutputStream() {
+ final CipherOutputStream cipherOutputStream = new
CipherOutputStream(out, cipher);
+
+ // Ensures that data are encrypt in respect of cipher block size
and pad with '0' if smaller
+ // NOTE: As "AES/CBC/PKCS5Padding" is weak and should not be used,
we use "AES/CBC/NoPadding" with this
+ // manual implementation for padding possible thanks to the size
of the file stored separately
+ final int cipherBlockSize = cipher.getBlockSize();
+ final byte[] cipherBlockBuffer = new byte[cipherBlockSize];
+ private int count = 0;
+
+ @Override
+ public void write(int b) throws IOException {
+ cipherBlockBuffer[count++] = (byte) b;
+ if (count == cipherBlockSize) {
+ flushBuffer();
+ }
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) throws IOException {
+ int gap = len + count > cipherBlockSize ? cipherBlockSize -
count : len;
+ System.arraycopy(b, off, cipherBlockBuffer, count, gap);
+ count += gap;
+
+ if (count == cipherBlockSize) {
+ flushBuffer();
+
+ if (len - gap >= cipherBlockSize) {
+ // skip buffer to encrypt data chunks big enought to
fit cipher block size
+ int multipleCipherBlockSizeLen = (len - gap) /
cipherBlockSize * cipherBlockSize;
+ cipherOutputStream.write(b, off + gap,
multipleCipherBlockSizeLen);
+ gap += multipleCipherBlockSizeLen;
+ }
+ System.arraycopy(b, off + gap, cipherBlockBuffer, 0, len -
gap);
+ count = len - gap;
+ }
+ }
+
+ private void flushBuffer() throws IOException {
+ cipherOutputStream.write(cipherBlockBuffer);
+ count = 0;
+ Arrays.fill(cipherBlockBuffer, (byte) 0);
+ }
+
+ @Override
+ public void flush() throws IOException {
+ cipherOutputStream.flush();
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (count > 0) {
+ cipherOutputStream.write(cipherBlockBuffer);
+ }
+ cipherOutputStream.close();
+ }
+ };
+ }
+
+ private byte[] sha256Password(final byte[] password, final int
numCyclesPower, final byte[] salt) throws IOException {
+ final MessageDigest digest;
+ try {
+ digest = MessageDigest.getInstance("SHA-256");
+ } catch (final NoSuchAlgorithmException noSuchAlgorithmException) {
+ throw new IOException("SHA-256 is unsupported by your Java
implementation", noSuchAlgorithmException);
Review Comment:
This is not possible since SHA-256 is required by the JRE specification, see
https://docs.oracle.com/javase/8/docs/api/java/security/MessageDigest.html,
therefore this could be an `IllegalStateException`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]