summaryrefslogtreecommitdiff
path: root/app/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/test')
-rw-r--r--app/src/test/java/dev/msfjarvis/aps/data/password/PasswordEntryTest.kt326
-rw-r--r--app/src/test/java/dev/msfjarvis/aps/util/crypto/GpgIdentifierTest.kt52
-rw-r--r--app/src/test/java/dev/msfjarvis/aps/util/totp/OtpTest.kt97
3 files changed, 251 insertions, 224 deletions
diff --git a/app/src/test/java/dev/msfjarvis/aps/data/password/PasswordEntryTest.kt b/app/src/test/java/dev/msfjarvis/aps/data/password/PasswordEntryTest.kt
index 22ccb8ea..afbe9289 100644
--- a/app/src/test/java/dev/msfjarvis/aps/data/password/PasswordEntryTest.kt
+++ b/app/src/test/java/dev/msfjarvis/aps/data/password/PasswordEntryTest.kt
@@ -17,169 +17,179 @@ import org.junit.Test
class PasswordEntryTest {
- private fun makeEntry(content: String) = PasswordEntry(content, testFinder)
-
- @Test fun testGetPassword() {
- assertEquals("fooooo", makeEntry("fooooo\nbla\n").password)
- assertEquals("fooooo", makeEntry("fooooo\nbla").password)
- assertEquals("fooooo", makeEntry("fooooo\n").password)
- assertEquals("fooooo", makeEntry("fooooo").password)
- assertEquals("", makeEntry("\nblubb\n").password)
- assertEquals("", makeEntry("\nblubb").password)
- assertEquals("", makeEntry("\n").password)
- assertEquals("", makeEntry("").password)
- for (field in PasswordEntry.PASSWORD_FIELDS) {
- assertEquals("fooooo", makeEntry("\n$field fooooo").password)
- assertEquals("fooooo", makeEntry("\n${field.toUpperCase()} fooooo").password)
- assertEquals("fooooo", makeEntry("GOPASS-SECRET-1.0\n$field fooooo").password)
- assertEquals("fooooo", makeEntry("someFirstLine\nUsername: bar\n$field fooooo").password)
- }
- }
-
- @Test fun testGetExtraContent() {
- assertEquals("bla\n", makeEntry("fooooo\nbla\n").extraContent)
- assertEquals("bla", makeEntry("fooooo\nbla").extraContent)
- assertEquals("", makeEntry("fooooo\n").extraContent)
- assertEquals("", makeEntry("fooooo").extraContent)
- assertEquals("blubb\n", makeEntry("\nblubb\n").extraContent)
- assertEquals("blubb", makeEntry("\nblubb").extraContent)
- assertEquals("blubb", makeEntry("blubb\npassword: foo").extraContent)
- assertEquals("blubb", makeEntry("password: foo\nblubb").extraContent)
- assertEquals("blubb\nusername: bar", makeEntry("blubb\npassword: foo\nusername: bar").extraContent)
- assertEquals("", makeEntry("\n").extraContent)
- assertEquals("", makeEntry("").extraContent)
+ private fun makeEntry(content: String) = PasswordEntry(content, testFinder)
+
+ @Test
+ fun testGetPassword() {
+ assertEquals("fooooo", makeEntry("fooooo\nbla\n").password)
+ assertEquals("fooooo", makeEntry("fooooo\nbla").password)
+ assertEquals("fooooo", makeEntry("fooooo\n").password)
+ assertEquals("fooooo", makeEntry("fooooo").password)
+ assertEquals("", makeEntry("\nblubb\n").password)
+ assertEquals("", makeEntry("\nblubb").password)
+ assertEquals("", makeEntry("\n").password)
+ assertEquals("", makeEntry("").password)
+ for (field in PasswordEntry.PASSWORD_FIELDS) {
+ assertEquals("fooooo", makeEntry("\n$field fooooo").password)
+ assertEquals("fooooo", makeEntry("\n${field.toUpperCase()} fooooo").password)
+ assertEquals("fooooo", makeEntry("GOPASS-SECRET-1.0\n$field fooooo").password)
+ assertEquals("fooooo", makeEntry("someFirstLine\nUsername: bar\n$field fooooo").password)
}
-
- @Test fun parseExtraContentWithoutAuth() {
- var entry = makeEntry("username: abc\npassword: abc\ntest: abcdef")
- assertEquals(1, entry.extraContentMap.size)
- assertTrue(entry.extraContentMap.containsKey("test"))
- assertEquals("abcdef", entry.extraContentMap["test"])
-
- entry = makeEntry("username: abc\npassword: abc\ntest: :abcdef:")
- assertEquals(1, entry.extraContentMap.size)
- assertTrue(entry.extraContentMap.containsKey("test"))
- assertEquals(":abcdef:", entry.extraContentMap["test"])
-
- entry = makeEntry("username: abc\npassword: abc\ntest : ::abc:def::")
- assertEquals(1, entry.extraContentMap.size)
- assertTrue(entry.extraContentMap.containsKey("test"))
- assertEquals("::abc:def::", entry.extraContentMap["test"])
-
- entry = makeEntry("username: abc\npassword: abc\ntest: abcdef\ntest2: ghijkl")
- assertEquals(2, entry.extraContentMap.size)
- assertTrue(entry.extraContentMap.containsKey("test2"))
- assertEquals("ghijkl", entry.extraContentMap["test2"])
-
- entry = makeEntry("username: abc\npassword: abc\ntest: abcdef\n: ghijkl\n mnopqr:")
- assertEquals(2, entry.extraContentMap.size)
- assertTrue(entry.extraContentMap.containsKey("Extra Content"))
- assertEquals(": ghijkl\n mnopqr:", entry.extraContentMap["Extra Content"])
-
- entry = makeEntry("username: abc\npassword: abc\n:\n\n")
- assertEquals(1, entry.extraContentMap.size)
- assertTrue(entry.extraContentMap.containsKey("Extra Content"))
- assertEquals(":", entry.extraContentMap["Extra Content"])
+ }
+
+ @Test
+ fun testGetExtraContent() {
+ assertEquals("bla\n", makeEntry("fooooo\nbla\n").extraContent)
+ assertEquals("bla", makeEntry("fooooo\nbla").extraContent)
+ assertEquals("", makeEntry("fooooo\n").extraContent)
+ assertEquals("", makeEntry("fooooo").extraContent)
+ assertEquals("blubb\n", makeEntry("\nblubb\n").extraContent)
+ assertEquals("blubb", makeEntry("\nblubb").extraContent)
+ assertEquals("blubb", makeEntry("blubb\npassword: foo").extraContent)
+ assertEquals("blubb", makeEntry("password: foo\nblubb").extraContent)
+ assertEquals("blubb\nusername: bar", makeEntry("blubb\npassword: foo\nusername: bar").extraContent)
+ assertEquals("", makeEntry("\n").extraContent)
+ assertEquals("", makeEntry("").extraContent)
+ }
+
+ @Test
+ fun parseExtraContentWithoutAuth() {
+ var entry = makeEntry("username: abc\npassword: abc\ntest: abcdef")
+ assertEquals(1, entry.extraContentMap.size)
+ assertTrue(entry.extraContentMap.containsKey("test"))
+ assertEquals("abcdef", entry.extraContentMap["test"])
+
+ entry = makeEntry("username: abc\npassword: abc\ntest: :abcdef:")
+ assertEquals(1, entry.extraContentMap.size)
+ assertTrue(entry.extraContentMap.containsKey("test"))
+ assertEquals(":abcdef:", entry.extraContentMap["test"])
+
+ entry = makeEntry("username: abc\npassword: abc\ntest : ::abc:def::")
+ assertEquals(1, entry.extraContentMap.size)
+ assertTrue(entry.extraContentMap.containsKey("test"))
+ assertEquals("::abc:def::", entry.extraContentMap["test"])
+
+ entry = makeEntry("username: abc\npassword: abc\ntest: abcdef\ntest2: ghijkl")
+ assertEquals(2, entry.extraContentMap.size)
+ assertTrue(entry.extraContentMap.containsKey("test2"))
+ assertEquals("ghijkl", entry.extraContentMap["test2"])
+
+ entry = makeEntry("username: abc\npassword: abc\ntest: abcdef\n: ghijkl\n mnopqr:")
+ assertEquals(2, entry.extraContentMap.size)
+ assertTrue(entry.extraContentMap.containsKey("Extra Content"))
+ assertEquals(": ghijkl\n mnopqr:", entry.extraContentMap["Extra Content"])
+
+ entry = makeEntry("username: abc\npassword: abc\n:\n\n")
+ assertEquals(1, entry.extraContentMap.size)
+ assertTrue(entry.extraContentMap.containsKey("Extra Content"))
+ assertEquals(":", entry.extraContentMap["Extra Content"])
+ }
+
+ @Test
+ fun testGetUsername() {
+ for (field in PasswordEntry.USERNAME_FIELDS) {
+ assertEquals("username", makeEntry("\n$field username").username)
+ assertEquals("username", makeEntry("\n${field.toUpperCase()} username").username)
}
-
- @Test fun testGetUsername() {
- for (field in PasswordEntry.USERNAME_FIELDS) {
- assertEquals("username", makeEntry("\n$field username").username)
- assertEquals("username", makeEntry("\n${field.toUpperCase()} username").username)
+ assertEquals("username", makeEntry("secret\nextra\nlogin: username\ncontent\n").username)
+ assertEquals("username", makeEntry("\nextra\nusername: username\ncontent\n").username)
+ assertEquals("username", makeEntry("\nUSERNaMe: username\ncontent\n").username)
+ assertEquals("username", makeEntry("\nlogin: username").username)
+ assertEquals("foo@example.com", makeEntry("\nemail: foo@example.com").username)
+ assertEquals("username", makeEntry("\nidentity: username\nlogin: another_username").username)
+ assertEquals("username", makeEntry("\nLOGiN:username").username)
+ assertNull(makeEntry("secret\nextra\ncontent\n").username)
+ }
+
+ @Test
+ fun testHasUsername() {
+ assertTrue(makeEntry("secret\nextra\nlogin: username\ncontent\n").hasUsername())
+ assertFalse(makeEntry("secret\nextra\ncontent\n").hasUsername())
+ assertFalse(makeEntry("secret\nlogin failed\n").hasUsername())
+ assertFalse(makeEntry("\n").hasUsername())
+ assertFalse(makeEntry("").hasUsername())
+ }
+
+ @Test
+ fun testGeneratesOtpFromTotpUri() {
+ val entry = makeEntry("secret\nextra\n$TOTP_URI")
+ assertTrue(entry.hasTotp())
+ val code =
+ Otp.calculateCode(
+ entry.totpSecret!!,
+ // The hardcoded date value allows this test to stay reproducible.
+ Date(8640000).time / (1000 * entry.totpPeriod),
+ entry.totpAlgorithm,
+ entry.digits
+ )
+ .get()
+ assertNotNull(code) { "Generated OTP cannot be null" }
+ assertEquals(entry.digits.toInt(), code.length)
+ assertEquals("545293", code)
+ }
+
+ @Test
+ fun testGeneratesOtpWithOnlyUriInFile() {
+ val entry = makeEntry(TOTP_URI)
+ assertTrue(entry.password.isEmpty())
+ assertTrue(entry.hasTotp())
+ val code =
+ Otp.calculateCode(
+ entry.totpSecret!!,
+ // The hardcoded date value allows this test to stay reproducible.
+ Date(8640000).time / (1000 * entry.totpPeriod),
+ entry.totpAlgorithm,
+ entry.digits
+ )
+ .get()
+ assertNotNull(code) { "Generated OTP cannot be null" }
+ assertEquals(entry.digits.toInt(), code.length)
+ assertEquals("545293", code)
+ }
+
+ @Test
+ fun testOnlyLooksForUriInFirstLine() {
+ val entry = makeEntry("id:\n$TOTP_URI")
+ assertTrue(entry.password.isNotEmpty())
+ assertTrue(entry.hasTotp())
+ assertFalse(entry.hasUsername())
+ }
+
+ // https://github.com/android-password-store/Android-Password-Store/issues/1190
+ @Test
+ fun extraContentWithMultipleUsernameFields() {
+ val entry = makeEntry("pass\nuser: user\nid: id\n$TOTP_URI")
+ assertTrue(entry.hasExtraContent())
+ assertTrue(entry.hasTotp())
+ assertTrue(entry.hasUsername())
+ assertEquals("pass", entry.password)
+ assertEquals("user", entry.username)
+ assertEquals("id: id", entry.extraContentWithoutAuthData)
+ }
+
+ companion object {
+
+ const val TOTP_URI =
+ "otpauth://totp/ACME%20Co:john@example.com?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co&algorithm=SHA1&digits=6&period=30"
+
+ // This implementation is hardcoded for the URI above.
+ val testFinder =
+ object : TotpFinder {
+ override fun findSecret(content: String): String {
+ return "HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ"
}
- assertEquals(
- "username",
- makeEntry("secret\nextra\nlogin: username\ncontent\n").username)
- assertEquals(
- "username",
- makeEntry("\nextra\nusername: username\ncontent\n").username)
- assertEquals(
- "username", makeEntry("\nUSERNaMe: username\ncontent\n").username)
- assertEquals("username", makeEntry("\nlogin: username").username)
- assertEquals("foo@example.com", makeEntry("\nemail: foo@example.com").username)
- assertEquals("username", makeEntry("\nidentity: username\nlogin: another_username").username)
- assertEquals("username", makeEntry("\nLOGiN:username").username)
- assertNull(makeEntry("secret\nextra\ncontent\n").username)
- }
-
- @Test fun testHasUsername() {
- assertTrue(makeEntry("secret\nextra\nlogin: username\ncontent\n").hasUsername())
- assertFalse(makeEntry("secret\nextra\ncontent\n").hasUsername())
- assertFalse(makeEntry("secret\nlogin failed\n").hasUsername())
- assertFalse(makeEntry("\n").hasUsername())
- assertFalse(makeEntry("").hasUsername())
- }
-
- @Test fun testGeneratesOtpFromTotpUri() {
- val entry = makeEntry("secret\nextra\n$TOTP_URI")
- assertTrue(entry.hasTotp())
- val code = Otp.calculateCode(
- entry.totpSecret!!,
- // The hardcoded date value allows this test to stay reproducible.
- Date(8640000).time / (1000 * entry.totpPeriod),
- entry.totpAlgorithm,
- entry.digits
- ).get()
- assertNotNull(code) { "Generated OTP cannot be null" }
- assertEquals(entry.digits.toInt(), code.length)
- assertEquals("545293", code)
- }
-
- @Test fun testGeneratesOtpWithOnlyUriInFile() {
- val entry = makeEntry(TOTP_URI)
- assertTrue(entry.password.isEmpty())
- assertTrue(entry.hasTotp())
- val code = Otp.calculateCode(
- entry.totpSecret!!,
- // The hardcoded date value allows this test to stay reproducible.
- Date(8640000).time / (1000 * entry.totpPeriod),
- entry.totpAlgorithm,
- entry.digits
- ).get()
- assertNotNull(code) { "Generated OTP cannot be null" }
- assertEquals(entry.digits.toInt(), code.length)
- assertEquals("545293", code)
- }
-
- @Test fun testOnlyLooksForUriInFirstLine() {
- val entry = makeEntry("id:\n$TOTP_URI")
- assertTrue(entry.password.isNotEmpty())
- assertTrue(entry.hasTotp())
- assertFalse(entry.hasUsername())
- }
-
- // https://github.com/android-password-store/Android-Password-Store/issues/1190
- @Test fun extraContentWithMultipleUsernameFields() {
- val entry = makeEntry("pass\nuser: user\nid: id\n$TOTP_URI")
- assertTrue(entry.hasExtraContent())
- assertTrue(entry.hasTotp())
- assertTrue(entry.hasUsername())
- assertEquals("pass", entry.password)
- assertEquals("user", entry.username)
- assertEquals("id: id", entry.extraContentWithoutAuthData)
- }
-
- companion object {
- const val TOTP_URI = "otpauth://totp/ACME%20Co:john@example.com?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co&algorithm=SHA1&digits=6&period=30"
-
- // This implementation is hardcoded for the URI above.
- val testFinder = object : TotpFinder {
- override fun findSecret(content: String): String {
- return "HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ"
- }
-
- override fun findDigits(content: String): String {
- return "6"
- }
+ override fun findDigits(content: String): String {
+ return "6"
+ }
- override fun findPeriod(content: String): Long {
- return 30
- }
+ override fun findPeriod(content: String): Long {
+ return 30
+ }
- override fun findAlgorithm(content: String): String {
- return "SHA1"
- }
+ override fun findAlgorithm(content: String): String {
+ return "SHA1"
}
- }
+ }
+ }
}
diff --git a/app/src/test/java/dev/msfjarvis/aps/util/crypto/GpgIdentifierTest.kt b/app/src/test/java/dev/msfjarvis/aps/util/crypto/GpgIdentifierTest.kt
index fb2a528e..9c36afc1 100644
--- a/app/src/test/java/dev/msfjarvis/aps/util/crypto/GpgIdentifierTest.kt
+++ b/app/src/test/java/dev/msfjarvis/aps/util/crypto/GpgIdentifierTest.kt
@@ -6,38 +6,38 @@
package dev.msfjarvis.aps.util.crypto
import kotlin.test.Ignore
+import kotlin.test.Test
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
-import kotlin.test.Test
class GpgIdentifierTest {
- @Test
- fun `parses hexadecimal key id without leading 0x`() {
- val identifier = GpgIdentifier.fromString("79E8208280490C77")
- assertNotNull(identifier)
- assertTrue { identifier is GpgIdentifier.KeyId }
- }
+ @Test
+ fun `parses hexadecimal key id without leading 0x`() {
+ val identifier = GpgIdentifier.fromString("79E8208280490C77")
+ assertNotNull(identifier)
+ assertTrue { identifier is GpgIdentifier.KeyId }
+ }
- @Test
- fun `parses hexadecimal key id`() {
- val identifier = GpgIdentifier.fromString("0x79E8208280490C77")
- assertNotNull(identifier)
- assertTrue { identifier is GpgIdentifier.KeyId }
- }
+ @Test
+ fun `parses hexadecimal key id`() {
+ val identifier = GpgIdentifier.fromString("0x79E8208280490C77")
+ assertNotNull(identifier)
+ assertTrue { identifier is GpgIdentifier.KeyId }
+ }
- @Test
- fun `parses email as user id`() {
- val identifier = GpgIdentifier.fromString("aps@msfjarvis.dev")
- assertNotNull(identifier)
- assertTrue { identifier is GpgIdentifier.UserId }
- }
+ @Test
+ fun `parses email as user id`() {
+ val identifier = GpgIdentifier.fromString("aps@msfjarvis.dev")
+ assertNotNull(identifier)
+ assertTrue { identifier is GpgIdentifier.UserId }
+ }
- @Test
- @Ignore("OpenKeychain can't yet handle these so we don't either")
- fun `parses non-email user id`() {
- val identifier = GpgIdentifier.fromString("john.doe")
- assertNotNull(identifier)
- assertTrue { identifier is GpgIdentifier.UserId }
- }
+ @Test
+ @Ignore("OpenKeychain can't yet handle these so we don't either")
+ fun `parses non-email user id`() {
+ val identifier = GpgIdentifier.fromString("john.doe")
+ assertNotNull(identifier)
+ assertTrue { identifier is GpgIdentifier.UserId }
+ }
}
diff --git a/app/src/test/java/dev/msfjarvis/aps/util/totp/OtpTest.kt b/app/src/test/java/dev/msfjarvis/aps/util/totp/OtpTest.kt
index b3ebc6af..d41c3be9 100644
--- a/app/src/test/java/dev/msfjarvis/aps/util/totp/OtpTest.kt
+++ b/app/src/test/java/dev/msfjarvis/aps/util/totp/OtpTest.kt
@@ -13,44 +13,61 @@ import org.junit.Test
class OtpTest {
- @Test
- fun testOtpGeneration6Digits() {
- assertEquals("953550", Otp.calculateCode("JBSWY3DPEHPK3PXP", 1593333298159 / (1000 * 30), "SHA1", "6").get())
- assertEquals("275379", Otp.calculateCode("JBSWY3DPEHPK3PXP", 1593333571918 / (1000 * 30), "SHA1", "6").get())
- assertEquals("867507", Otp.calculateCode("JBSWY3DPEHPK3PXP", 1593333600517 / (1000 * 57), "SHA1", "6").get())
- }
-
- @Test
- fun testOtpGeneration10Digits() {
- assertEquals("0740900914", Otp.calculateCode("JBSWY3DPEHPK3PXP", 1593333655044 / (1000 * 30), "SHA1", "10").get())
- assertEquals("0070632029", Otp.calculateCode("JBSWY3DPEHPK3PXP", 1593333691405 / (1000 * 30), "SHA1", "10").get())
- assertEquals("1017265882", Otp.calculateCode("JBSWY3DPEHPK3PXP", 1593333728893 / (1000 * 83), "SHA1", "10").get())
- }
-
- @Test
- fun testOtpGenerationIllegalInput() {
- assertNull(Otp.calculateCode("JBSWY3DPEHPK3PXP", 10000, "SHA0", "10").get())
- assertNull(Otp.calculateCode("JBSWY3DPEHPK3PXP", 10000, "SHA1", "a").get())
- assertNull(Otp.calculateCode("JBSWY3DPEHPK3PXP", 10000, "SHA1", "5").get())
- assertNull(Otp.calculateCode("JBSWY3DPEHPK3PXP", 10000, "SHA1", "11").get())
- assertNull(Otp.calculateCode("JBSWY3DPEHPK3PXPAAAAB", 10000, "SHA1", "6").get())
- }
-
- @Test
- fun testOtpGenerationUnusualSecrets() {
- assertEquals("127764", Otp.calculateCode("JBSWY3DPEHPK3PXPAAAAAAAA", 1593367111963 / (1000 * 30), "SHA1", "6").get())
- assertEquals("047515", Otp.calculateCode("JBSWY3DPEHPK3PXPAAAAA", 1593367171420 / (1000 * 30), "SHA1", "6").get())
- }
-
- @Test
- fun testOtpGenerationUnpaddedSecrets() {
- // Secret was generated with `echo 'string with some padding needed' | base32`
- // We don't care for the resultant OTP's actual value, we just want both the padded and
- // unpadded variant to generate the same one.
- val unpaddedOtp = Otp.calculateCode("ON2HE2LOM4QHO2LUNAQHG33NMUQHAYLEMRUW4ZZANZSWKZDFMQFA", 1593367171420 / (1000 * 30), "SHA1", "6").get()
- val paddedOtp = Otp.calculateCode("ON2HE2LOM4QHO2LUNAQHG33NMUQHAYLEMRUW4ZZANZSWKZDFMQFA====", 1593367171420 / (1000 * 30), "SHA1", "6").get()
- assertNotNull(unpaddedOtp)
- assertNotNull(paddedOtp)
- assertEquals(unpaddedOtp, paddedOtp)
- }
+ @Test
+ fun testOtpGeneration6Digits() {
+ assertEquals("953550", Otp.calculateCode("JBSWY3DPEHPK3PXP", 1593333298159 / (1000 * 30), "SHA1", "6").get())
+ assertEquals("275379", Otp.calculateCode("JBSWY3DPEHPK3PXP", 1593333571918 / (1000 * 30), "SHA1", "6").get())
+ assertEquals("867507", Otp.calculateCode("JBSWY3DPEHPK3PXP", 1593333600517 / (1000 * 57), "SHA1", "6").get())
+ }
+
+ @Test
+ fun testOtpGeneration10Digits() {
+ assertEquals("0740900914", Otp.calculateCode("JBSWY3DPEHPK3PXP", 1593333655044 / (1000 * 30), "SHA1", "10").get())
+ assertEquals("0070632029", Otp.calculateCode("JBSWY3DPEHPK3PXP", 1593333691405 / (1000 * 30), "SHA1", "10").get())
+ assertEquals("1017265882", Otp.calculateCode("JBSWY3DPEHPK3PXP", 1593333728893 / (1000 * 83), "SHA1", "10").get())
+ }
+
+ @Test
+ fun testOtpGenerationIllegalInput() {
+ assertNull(Otp.calculateCode("JBSWY3DPEHPK3PXP", 10000, "SHA0", "10").get())
+ assertNull(Otp.calculateCode("JBSWY3DPEHPK3PXP", 10000, "SHA1", "a").get())
+ assertNull(Otp.calculateCode("JBSWY3DPEHPK3PXP", 10000, "SHA1", "5").get())
+ assertNull(Otp.calculateCode("JBSWY3DPEHPK3PXP", 10000, "SHA1", "11").get())
+ assertNull(Otp.calculateCode("JBSWY3DPEHPK3PXPAAAAB", 10000, "SHA1", "6").get())
+ }
+
+ @Test
+ fun testOtpGenerationUnusualSecrets() {
+ assertEquals(
+ "127764",
+ Otp.calculateCode("JBSWY3DPEHPK3PXPAAAAAAAA", 1593367111963 / (1000 * 30), "SHA1", "6").get()
+ )
+ assertEquals("047515", Otp.calculateCode("JBSWY3DPEHPK3PXPAAAAA", 1593367171420 / (1000 * 30), "SHA1", "6").get())
+ }
+
+ @Test
+ fun testOtpGenerationUnpaddedSecrets() {
+ // Secret was generated with `echo 'string with some padding needed' | base32`
+ // We don't care for the resultant OTP's actual value, we just want both the padded and
+ // unpadded variant to generate the same one.
+ val unpaddedOtp =
+ Otp.calculateCode(
+ "ON2HE2LOM4QHO2LUNAQHG33NMUQHAYLEMRUW4ZZANZSWKZDFMQFA",
+ 1593367171420 / (1000 * 30),
+ "SHA1",
+ "6"
+ )
+ .get()
+ val paddedOtp =
+ Otp.calculateCode(
+ "ON2HE2LOM4QHO2LUNAQHG33NMUQHAYLEMRUW4ZZANZSWKZDFMQFA====",
+ 1593367171420 / (1000 * 30),
+ "SHA1",
+ "6"
+ )
+ .get()
+ assertNotNull(unpaddedOtp)
+ assertNotNull(paddedOtp)
+ assertEquals(unpaddedOtp, paddedOtp)
+ }
}