From a0f264e1afa3c0a00a5af0db362f884b122d978d Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Wed, 14 Sep 2011 09:57:27 -0700 Subject: [PATCH] Be more forgiving in parsing verifier IDs RFC 4648's Base32 is made to be forgiving for users doing manual entry of the digits. For this reason we want to be able to parse lowercase letters as uppercase and number 0 (zero) as letter O along with number 1 (one) as letter I. Change-Id: Ide760aff84f97c3e06af8bf8d006f36c74033a41 --- .../content/pm/VerifierDeviceIdentity.java | 9 +++++ .../pm/VerifierDeviceIdentityTest.java | 37 +++++++++++++++++-- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/core/java/android/content/pm/VerifierDeviceIdentity.java b/core/java/android/content/pm/VerifierDeviceIdentity.java index bfebe0f8bfca7..a8cdb6ae8af6c 100644 --- a/core/java/android/content/pm/VerifierDeviceIdentity.java +++ b/core/java/android/content/pm/VerifierDeviceIdentity.java @@ -153,6 +153,15 @@ public class VerifierDeviceIdentity implements Parcelable { value = group - ('2' - 26); } else if (group == SEPARATOR) { continue; + } else if ('a' <= group && group <= 'z') { + /* Lowercase letters should be the same as uppercase for Base32 */ + value = group - 'a'; + } else if (group == '0') { + /* Be nice to users that mistake O (letter) for 0 (zero) */ + value = 'O' - 'A'; + } else if (group == '1') { + /* Be nice to users that mistake I (letter) for 1 (one) */ + value = 'I' - 'A'; } else { throw new IllegalArgumentException("base base-32 character: " + group); } diff --git a/core/tests/coretests/src/android/content/pm/VerifierDeviceIdentityTest.java b/core/tests/coretests/src/android/content/pm/VerifierDeviceIdentityTest.java index e6a6a2658ca49..cb13eb7c846ed 100644 --- a/core/tests/coretests/src/android/content/pm/VerifierDeviceIdentityTest.java +++ b/core/tests/coretests/src/android/content/pm/VerifierDeviceIdentityTest.java @@ -25,6 +25,8 @@ public class VerifierDeviceIdentityTest extends android.test.AndroidTestCase { private static final String TEST_1_ENCODED = "HUXY-A75N-FLKV-F"; + private static final String TEST_1_ENCODED_LOWERCASE = "huxy-a75n-flkv-f"; + private static final long TEST_2 = 0x5A05FF5A05F0A555L; private static final long TEST_MAXVALUE = Long.MAX_VALUE; @@ -45,6 +47,10 @@ public class VerifierDeviceIdentityTest extends android.test.AndroidTestCase { private static final String TEST_OVERFLOW_ENCODED = "QAAA-AAAA-AAAA-A"; + private static final String TEST_SUBSTITUTION_CORRECTED = "OIIO-IIOO-IOOI-I"; + + private static final String TEST_SUBSTITUTION_UNCORRECTED = "0110-1100-1001-1"; + public void testVerifierDeviceIdentity_Equals_Success() { VerifierDeviceIdentity id1 = new VerifierDeviceIdentity(TEST_1); VerifierDeviceIdentity id2 = new VerifierDeviceIdentity(TEST_1); @@ -125,6 +131,7 @@ public class VerifierDeviceIdentityTest extends android.test.AndroidTestCase { assertEquals("Original identity and parceled identity should be the same", id1, id2); } + @SuppressWarnings("serial") private static class MockRandom extends Random { private long mNextLong; @@ -181,7 +188,7 @@ public class VerifierDeviceIdentityTest extends android.test.AndroidTestCase { public void testVerifierDeviceIdentity_Parse_TooShort() { try { - VerifierDeviceIdentity id = VerifierDeviceIdentity.parse("AAAA-AAAA-AAAA-"); + VerifierDeviceIdentity.parse("AAAA-AAAA-AAAA-"); fail("Parsing should fail when device identifier is too short"); } catch (IllegalArgumentException e) { // success @@ -190,7 +197,7 @@ public class VerifierDeviceIdentityTest extends android.test.AndroidTestCase { public void testVerifierDeviceIdentity_Parse_WayTooShort() { try { - VerifierDeviceIdentity id = VerifierDeviceIdentity.parse("----------------"); + VerifierDeviceIdentity.parse("----------------"); fail("Parsing should fail when device identifier is too short"); } catch (IllegalArgumentException e) { // success @@ -199,7 +206,7 @@ public class VerifierDeviceIdentityTest extends android.test.AndroidTestCase { public void testVerifierDeviceIdentity_Parse_TooLong() { try { - VerifierDeviceIdentity id = VerifierDeviceIdentity.parse("AAAA-AAAA-AAAA-AA"); + VerifierDeviceIdentity.parse("AAAA-AAAA-AAAA-AA"); fail("Parsing should fail when device identifier is too long"); } catch (IllegalArgumentException e) { // success @@ -208,10 +215,32 @@ public class VerifierDeviceIdentityTest extends android.test.AndroidTestCase { public void testVerifierDeviceIdentity_Parse_Overflow() { try { - VerifierDeviceIdentity id = VerifierDeviceIdentity.parse(TEST_OVERFLOW_ENCODED); + VerifierDeviceIdentity.parse(TEST_OVERFLOW_ENCODED); fail("Parsing should fail when the value will overflow"); } catch (IllegalArgumentException e) { // success } } + + public void testVerifierDeviceIdentity_Parse_SquashToUppercase() { + VerifierDeviceIdentity id1 = new VerifierDeviceIdentity(TEST_1); + + VerifierDeviceIdentity id2 = VerifierDeviceIdentity.parse(TEST_1_ENCODED_LOWERCASE); + + assertEquals("Lowercase should parse to be the same as uppercase", id1, id2); + + assertEquals("Substituted identity should render to the same string", + id1.toString(), id2.toString()); + } + + public void testVerifierDeviceIdentity_Parse_1I_And_0O_Substitution() { + VerifierDeviceIdentity id1 = VerifierDeviceIdentity.parse(TEST_SUBSTITUTION_CORRECTED); + + VerifierDeviceIdentity id2 = VerifierDeviceIdentity.parse(TEST_SUBSTITUTION_UNCORRECTED); + + assertEquals("Substitution should replace 0 with O and 1 with I", id1, id2); + + assertEquals("Substituted identity should render to the same string", + id1.toString(), id2.toString()); + } }