Skip to content
This repository has been archived by the owner on Nov 22, 2022. It is now read-only.

Iv hex encoding #51

Merged
merged 4 commits into from
Oct 20, 2017
Merged

Iv hex encoding #51

merged 4 commits into from
Oct 20, 2017

Conversation

Raniz85
Copy link
Contributor

@Raniz85 Raniz85 commented Aug 2, 2017

Fix for #50

Daniel Raniz Raneland added 3 commits August 2, 2017 11:48
Because WriteUtil.writeHexadecimal used Integer.toHexString which
converts each byte into an integer and then writes that integer using
the minimum required number of hexadecimal digits results would vary
and negative bytes would be written using 8 hexadecimal digits with
the first 6 being ffffff and positive bytes between 0 and 15 would
only be written using 1 hexadecimal digit. This would cause the IV
in EXT-X-KEY tags to be corrupted.

Using String.format("%02x", b) instead means all bytes will be written
correctly. They won't take up more than 2 characters since no
integer-conversion is performed and if only 1 digit is required they
will be zero-padded.
@@ -54,17 +54,20 @@ public static float parseFloat(String string, String tag) throws ParseException

if (matcher.matches()) {
String valueString = matcher.group(1);
if (valueString.length() % 2 != 0) {
throw ParseException.create(ParseExceptionType.INVALID_HEXADECIMAL_STRING, tag, hexString);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parseHexadecimal doesn't know what it's parsing, so it shouldn't assume the length of the string is a multiple of 2. If you want to validate the IV (is the IV required to have an even length?), then that validation probably belongs in PlaylistValidation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since each byte maps to 2 hexadecimal digits it has to be a multiple of 2 - unless you want to assume the last half byte is all zeroes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense, let's keep it like you implemented.

for (char c : valueString.toCharArray()) {
bytes.add(hexCharToByte(c));
for (int i = 0; i < valueString.length(); i += 2) {
bytes.add((byte)(Short.parseShort(valueString.substring(i, i+2), 16) & 0xFF));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bug description seems to be affecting the writing, not the parsing. Is there a problem with hexCharToByte?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, the issue is 2 hex chars fit within 1 byte. I don't work with low level very often. :( I think I'm okay with this implementation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed issues with parsing after I created the issue and updated the PR, I can open up another issue if you want

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need, this is fine.

@Wopple
Copy link
Contributor

Wopple commented Oct 9, 2017

Unfortunately, not all the tests pass because of the faulty implementation. Can you please make the following changes?
MediaPlaylistLineParserTest.java:

// from
        assertEquals(
                Arrays.asList((byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 10, (byte) 11, (byte) 12, (byte) 13,
                              (byte) 5, (byte) 6, (byte) 7, (byte) 8, (byte) 14, (byte) 15, (byte) 9, (byte) 0),
                encryptionData.getInitializationVector());
// to
        assertEquals(
                Arrays.asList((byte) 0x12, (byte) 0x34, (byte) 0xAB, (byte) 0xCD,
                              (byte) 0x56, (byte) 0x78, (byte) 0xEF, (byte) 0x90),
                encryptionData.getInitializationVector());

Constants.java:

// from
    public static final int IV_SIZE = 16;
    //Against the spec but used by Adobe
    public static final int IV_SIZE_ALTERNATIVE = 32;
// to
    public static final int IV_SIZE = 8;
    //Against the spec but used by Adobe
    public static final int IV_SIZE_ALTERNATIVE = 16;

The rest looks good.

@sunglee413 this is good to go once the changes above are made to fix the tests.

@Raniz85
Copy link
Contributor Author

Raniz85 commented Oct 10, 2017

The IV sizes shouldn't be changed - an IV in AES is 128 bits, so 16 bytes is correct - so I'll just increase the length of the IV in the test.

The IV was too short and the expected value was wrong
@Raniz85
Copy link
Contributor Author

Raniz85 commented Oct 10, 2017

Done. ./gradlew check now finishes without errors.

@Wopple
Copy link
Contributor

Wopple commented Oct 10, 2017

Yeah, I can't maths. LGTM!

@sunglee413 sunglee413 merged commit 7665c2a into iheartradio:master Oct 20, 2017
@Raniz85 Raniz85 deleted the IV-hex-encoding branch November 13, 2018 09:08
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants