garydgregory commented on code in PR #332:
URL: https://github.com/apache/commons-compress/pull/332#discussion_r1038170771


##########
src/main/java/org/apache/commons/compress/archivers/sevenz/AES256SHA256Decoder.java:
##########
@@ -126,4 +115,109 @@ public void close() throws IOException {
             }
         };
     }
+
+    @Override
+    OutputStream encode(OutputStream out, Object options) throws IOException {
+        final AES256Options opts = (AES256Options) options;
+
+        return new OutputStream() {
+            private final CipherOutputStream cipherOutputStream = new 
CipherOutputStream(out, opts.getCipher());
+
+            // 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
+            private final int cipherBlockSize = 
opts.getCipher().getBlockSize();
+            private 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();
+            }
+        };
+    }
+
+    static byte[] sha256Password(final byte[] password, final int 
numCyclesPower, final byte[] salt) {
+        final MessageDigest digest;
+        try {
+            digest = MessageDigest.getInstance("SHA-256");
+        } catch (final NoSuchAlgorithmException noSuchAlgorithmException) {
+            throw new IllegalStateException("SHA-256 is unsupported by your 
Java implementation", noSuchAlgorithmException);
+        }
+        final byte[] extra = new byte[8];
+        for (long j = 0; j < (1L << numCyclesPower); j++) {
+            digest.update(salt);
+            digest.update(password);
+            digest.update(extra);
+            for (int k = 0; k < extra.length; k++) {
+                ++extra[k];
+                if (extra[k] != 0) {
+                    break;
+                }
+            }
+        }
+        return digest.digest();
+    }
+
+    @Override
+    byte[] getOptionsAsProperties(Object options) throws IOException {
+        AES256Options opts = (AES256Options) options;

Review Comment:
   Use final where you can.



-- 
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]

Reply via email to