aboutsummaryrefslogtreecommitdiff
path: root/passgen
diff options
context:
space:
mode:
authorHarsh Shandilya <me@msfjarvis.dev>2021-12-10 13:59:32 +0530
committerHarsh Shandilya <me@msfjarvis.dev>2021-12-21 13:01:40 +0530
commitc5436b543df466657a1d0dc3af40d4707fca9b9d (patch)
treea5b04250886153f0e9d4e1bba0867fbb8332fe04 /passgen
parentab8f6a43eefab012900edd1ad9dbefd9a49b7429 (diff)
diceware: add passphrase generator
Diffstat (limited to 'passgen')
-rw-r--r--passgen/diceware/api/diceware.api6
-rw-r--r--passgen/diceware/src/main/kotlin/dev/msfjarvis/aps/passgen/diceware/DicewarePassphraseGenerator.kt42
-rw-r--r--passgen/diceware/src/test/kotlin/dev/msfjarvis/aps/passgen/diceware/DicewarePassphraseGeneratorTest.kt29
3 files changed, 77 insertions, 0 deletions
diff --git a/passgen/diceware/api/diceware.api b/passgen/diceware/api/diceware.api
index 8d16ae8f..925d6739 100644
--- a/passgen/diceware/api/diceware.api
+++ b/passgen/diceware/api/diceware.api
@@ -1,3 +1,9 @@
+public final class dev/msfjarvis/aps/passgen/diceware/DicewarePassphraseGenerator {
+ public static final field DIGITS I
+ public fun <init> (Ldev/msfjarvis/aps/passgen/diceware/Die;Ljava/io/InputStream;)V
+ public final fun generatePassphrase (IC)Ljava/lang/String;
+}
+
public final class dev/msfjarvis/aps/passgen/diceware/Die {
public fun <init> (ILdev/msfjarvis/aps/passgen/diceware/RandomIntGenerator;)V
public final fun roll ()I
diff --git a/passgen/diceware/src/main/kotlin/dev/msfjarvis/aps/passgen/diceware/DicewarePassphraseGenerator.kt b/passgen/diceware/src/main/kotlin/dev/msfjarvis/aps/passgen/diceware/DicewarePassphraseGenerator.kt
new file mode 100644
index 00000000..ee18352e
--- /dev/null
+++ b/passgen/diceware/src/main/kotlin/dev/msfjarvis/aps/passgen/diceware/DicewarePassphraseGenerator.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved.
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+package dev.msfjarvis.aps.passgen.diceware
+
+import java.io.InputStream
+import javax.inject.Inject
+
+/**
+ * Password generator implementing the Diceware passphrase generation mechanism. For detailed
+ * information on how this works, see https://theworld.com/~reinhold/diceware.html.
+ */
+public class DicewarePassphraseGenerator
+@Inject
+constructor(
+ private val die: Die,
+ wordList: InputStream,
+) {
+
+ private val wordMap = WordListParser.parse(wordList)
+
+ /** Generates a passphrase with [wordCount] words. */
+ public fun generatePassphrase(wordCount: Int, separator: Char): String {
+ return StringBuilder()
+ .apply {
+ repeat(wordCount) { idx ->
+ append(wordMap[die.rollMultiple(DIGITS)])
+ if (idx < wordCount - 1) append(separator)
+ }
+ }
+ .toString()
+ .trimEnd()
+ }
+
+ private companion object {
+
+ /** Number of digits used by indices in the default wordlist. */
+ const val DIGITS: Int = 5
+ }
+}
diff --git a/passgen/diceware/src/test/kotlin/dev/msfjarvis/aps/passgen/diceware/DicewarePassphraseGeneratorTest.kt b/passgen/diceware/src/test/kotlin/dev/msfjarvis/aps/passgen/diceware/DicewarePassphraseGeneratorTest.kt
new file mode 100644
index 00000000..7f22fdcc
--- /dev/null
+++ b/passgen/diceware/src/test/kotlin/dev/msfjarvis/aps/passgen/diceware/DicewarePassphraseGeneratorTest.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved.
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+package dev.msfjarvis.aps.passgen.diceware
+
+import kotlin.random.Random
+import kotlin.test.assertEquals
+import org.junit.Test
+
+class DicewarePassphraseGeneratorTest {
+ /** Pre-seeded [Random] instance to ensure tests are deterministic. */
+ private val random = Random(1_00_000)
+
+ private val intGenerator = RandomIntGenerator { it.random(random) }
+ @Test
+ fun generate_passphrase() {
+ val die = Die(6, intGenerator)
+
+ val generator =
+ DicewarePassphraseGenerator(
+ die,
+ WordListParserTest.getDefaultWordList(),
+ )
+
+ assertEquals("salvation_cozily_croon_trustee_fidgety", generator.generatePassphrase(5, '_'))
+ }
+}