Skip to content

Commit

Permalink
#30 Fix bug with invalid padding bytes
Browse files Browse the repository at this point in the history
  • Loading branch information
sadv1r committed May 19, 2020
1 parent afa5dbb commit 03e9a6a
Show file tree
Hide file tree
Showing 7 changed files with 33 additions and 53 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ Usage
Changelog
---------

### [v1.3](https://github.com/sadv1r/ansible-vault-editor-idea-plugin/tree/v1.3) (2020-05-19)

* Fixed critical bug with invalid padding bytes

### [v1.2](https://github.com/sadv1r/ansible-vault-editor-idea-plugin/tree/v1.2) (2020-05-14)

* Possibility to remember vault [password](https://www.jetbrains.com/help/idea/reference-ide-settings-password-safe.html)
Expand Down
9 changes: 8 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ plugins {
}

group 'ru.sadv1r'
version '1.2'
version '1.3'

repositories {
mavenCentral()
}

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
compile 'bouncycastle:bcprov-jdk16:136'
compile('de.rtner:PBKDF2:1.1.0') {
exclude group: 'org.picketbox', module: 'picketbox'
exclude group: 'org.jboss.logging', module: 'jboss-logging'
Expand Down Expand Up @@ -54,6 +55,12 @@ Helps you create and edit Ansible Vaults
"""

changeNotes """
<a href="https://github.com/sadv1r/ansible-vault-editor-idea-plugin/tree/v1.3"><b>v1.3</b></a> (2020-05-19)
<br/>
<ul>
<li>Fixed critical bug with invalid padding bytes</li>
</ul>
<br/>
<a href="https://github.com/sadv1r/ansible-vault-editor-idea-plugin/tree/v1.2"><b>v1.2</b></a> (2020-05-14)
<br/>
<ul>
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/ru/sadv1r/ansible/vault/VaultHandler.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ru.sadv1r.ansible.vault;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.jetbrains.annotations.NotNull;
import ru.sadv1r.ansible.vault.crypto.CypherFactory;
import ru.sadv1r.ansible.vault.crypto.Util;
Expand All @@ -8,11 +9,16 @@
import ru.sadv1r.ansible.vault.crypto.decoders.impl.CypherAES256;

import java.io.IOException;
import java.security.Security;
import java.util.Arrays;
import java.util.Optional;

public class VaultHandler {

static {
Security.addProvider(new BouncyCastleProvider());
}

private static final String DEFAULT_CYPHER = CypherAES256.CYPHER_ID;
private static final String LINE_BREAK = "\n";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class CypherAES256 implements Cypher {
private static final String CHAR_ENCODING = "UTF-8";
private static final String KEYGEN_ALGO = "HmacSHA256";
private static final String CYPHER_KEY_ALGO = "AES";
private static final String CYPHER_ALGO = "AES/CTR/NoPadding";
private static final String CYPHER_ALGO = "AES/CTR/PKCS7Padding";
private static final int KEYLEN = 32;
private static final int IVLEN = 16;
private static final int ITERATIONS = 10000;
Expand Down Expand Up @@ -67,50 +67,14 @@ public boolean verifyHMAC(byte[] hmac, byte[] key, byte[] data) throws IOExcepti
return Arrays.equals(hmac, calculated);
}

public int paddingLength(byte[] decrypted) {
if (decrypted.length == 0) {
logger.debug("Empty decoded text has no padding.");
return 0;
}

logger.debug("Padding length: {}", decrypted[decrypted.length - 1]);
return decrypted[decrypted.length - 1];
}

public byte[] unpad(byte[] decrypted) {
int length = decrypted.length - paddingLength(decrypted);
return Arrays.copyOfRange(decrypted, 0, length);
}

public byte[] pad(byte[] cleartext) throws IOException {
byte[] padded;

try {
int blockSize = Cipher.getInstance(CYPHER_ALGO).getBlockSize();
logger.debug("Padding to block size: {}", blockSize);
int padding_length = (blockSize - (cleartext.length % blockSize));
if (padding_length == 0) {
padding_length = blockSize;
}
padded = Arrays.copyOf(cleartext, cleartext.length + padding_length);
padded[padded.length - 1] = (byte) padding_length;

} catch (Exception ex) {
throw new IOException("Error calculating padding for " + CYPHER_ALGO + ": " + ex.getMessage());
}

return padded;
}

public byte[] decryptAES(byte[] cypher, byte[] key, byte[] iv) throws IOException {

SecretKeySpec keySpec = new SecretKeySpec(key, CYPHER_KEY_ALGO);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
try {
Cipher cipher = Cipher.getInstance(CYPHER_ALGO);
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] decrypted = cipher.doFinal(cypher);
return unpad(decrypted);
return cipher.doFinal(cypher);
} catch (Exception ex) {
throw new IOException("Failed to decrypt data: " + ex.getMessage());
}
Expand Down Expand Up @@ -178,9 +142,7 @@ public byte[] encrypt(byte[] data, String password) throws IOException {
logger.debug("Key 2: {} - {}", hmacKey.length, Util.hexit(hmacKey, 100));
byte[] iv = keys.getIv();
logger.debug("IV: {} - {}", iv.length, Util.hexit(iv, 100));
logger.debug("Original data length: {}", data.length);
data = pad(data);
logger.debug("Padded data length: {}", data.length);
logger.debug("Data length: {}", data.length);
byte[] encrypted = encryptAES(data, keys.getEncryptionKey(), keys.getIv());
byte[] hmacHash = calculateHMAC(keys.getHmacKey(), encrypted);
VaultContent vaultContent = new VaultContent(keys.getSalt(), hmacHash, encrypted);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class VaultEditorDialog(
val editorFactory = EditorFactory.getInstance()

decryptedDocument = editorFactory.createDocument(
decryptedDocumentData.toString(Charsets.UTF_8).replace("\r\n|\r".toRegex(), "\n")
decryptedDocumentData.toString(Charsets.UTF_8).trim().replace("\r\n|\r".toRegex(), "\n")
)
decryptedDocument.setReadOnly(false)
val editor: EditorEx = editorFactory.createEditor(decryptedDocument) as EditorEx
Expand Down
6 changes: 3 additions & 3 deletions src/test/java/ru/sadv1r/ansible/vault/VaultHandlerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ public class VaultHandlerTest {
public final ExpectedException exceptionRule = ExpectedException.none();

@Test
public void testStreamValidVault() throws IOException {
public void decrypt() throws IOException {
InputStream encodedStream = getClass().getClassLoader().getResourceAsStream("test-vault.yml");
String encryptedValue = IOUtils.toString(encodedStream, StandardCharsets.UTF_8);
byte[] decrypt = VaultHandler.decrypt(encryptedValue, TEST_PASSWORD);
assertEquals(DECODED_VAULT, new String(decrypt));
assertEquals(DECODED_VAULT, new String(decrypt).trim());
}

@Test
public void testStreamInvalidVault() throws IOException {
public void decryptInvalidVault() throws IOException {
exceptionRule.expect(IOException.class);
exceptionRule.expectMessage("HMAC Digest doesn't match - possibly it's the wrong password.");
InputStream encodedStream = getClass().getClassLoader().getResourceAsStream("test-vault.yml");
Expand Down
15 changes: 8 additions & 7 deletions src/test/resources/test-vault.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
$ANSIBLE_VAULT;1.1;AES256
38336666343431323530333165386238626138336532396265303238316163363338316666616664
6638316337366231323563303937373638626535343166650a616230646665316538653530343530
64363535656634636437613364306634366331616335313461653835373432356564356339323866
6466346231313933630a313939323563363734653430633432393638613936336430336136303565
34363837333130303835303439333364623437643939306535616662363335353862353937343538
37363134306464336435623134383230323234626131343231336331303435653439323965316632
306265663335353036666534306663393563
32393137633637633138343534646439623964653835373837373036306235313465353634333234
3336396161623564636564376532343036303239616265390a333830393563333063343537643531
37616432386235373566346333303864656637346665656162383935376663636631316135336562
3865613038613862610a356165616334386165396531313364326563303933356331616532306137
32376330353365356566303132316261623235623566356566346438306432616665663735346230
39333262313034663063306164613661646439653833333765633263336438656430353431633736
63623137383763303762323062313738633433356431383435313764616663323935653635653465
62613336616231666332

0 comments on commit 03e9a6a

Please sign in to comment.