예제 #1
0
def test_mkpassphrase_entropy_provided_insufficient_words(tmpdir):
    words = ["true", "false"]
    tmpfile = tmpdir.join("words.txt")
    with tmpfile.open("w") as f:
        for word in words:
            six.print_(word, file=f)
    path = str(tmpfile)
    with pytest.raises(ValueError) as err:
        api.mkpassphrase(num_words=1, word_file=path, random_case=False, entropy=2)
    assert "entropy bits (1) for 1 words is less than 2" == str(err.value)
예제 #2
0
def test_mkpassphrase_delim(word_file):
    delim = "^"
    num_words = 10
    passphrase, _ = api.mkpassphrase(
        word_file=word_file, delimiter=delim, num_words=num_words
    )
    assert delim in passphrase
    assert len(passphrase.split(delim)) == num_words
예제 #3
0
def test_mkpassword_defaults(word_file):
    assert internal.load_words_from_file(word_file)
    passphrase, entropy = api.mkpassphrase(word_file=word_file)
    assert entropy > 0
    passphrase_words = passphrase.split(internal.DELIMITER)
    assert len(passphrase_words) > 1
    for word in passphrase_words:
        assert passphrase.startswith(internal.PAD)
        assert passphrase.endswith(internal.PAD)
예제 #4
0
def test_mkpassphrase_entropy_provided_exactly_enough(tmpdir):
    words = [str(i) for i in range(4)]
    assert len(words) == 4
    tmpfile = tmpdir.join("words.txt")
    entropy = 2
    with tmpfile.open("w") as f:
        for word in words:
            six.print_(word, file=f)
    path = str(tmpfile)
    result, security_level = api.mkpassphrase(
        num_words=1, word_file=path, random_case=False, entropy=entropy
    )
    assert result in words
    assert security_level == entropy
예제 #5
0
def test_mkpassphrase_count_multiple(word_file, count):
    passphrases, _ = api.mkpassphrase(word_file=word_file, count=count)
    assert isinstance(passphrases, list)
    assert isinstance(passphrases[0], six.text_type)
    assert len(set(passphrases)) == len(passphrases)
예제 #6
0
def test_mkpassphrase_count_default(word_file):
    result, _ = api.mkpassphrase(word_file=word_file)
    assert isinstance(result, six.text_type)
    result, _ = api.mkpassphrase(word_file=word_file, count=1)
    assert isinstance(result, six.text_type)
예제 #7
0
def test_mkpassword_pad(word_file):
    pad = "//"
    passphrase, _ = api.mkpassphrase(word_file=word_file, pad=pad)
    assert passphrase.startswith(pad)
    assert passphrase.endswith(pad)
예제 #8
0
def test_mkpassphrase_count_must_be_positive_int(word_file, count):
    with pytest.raises(ValueError) as err:
        api.mkpassphrase(num_words=3, word_file=word_file, count=count)
    assert "must be a positive integer" in str(err.value)
    assert "'count'" in str(err.value)
예제 #9
0
def test_mkpassword_must_be_positive_int(word_file, num_words):
    with pytest.raises(ValueError) as err:
        api.mkpassphrase(num_words=num_words, word_file=word_file)
    assert "must be a positive integer" in str(err.value)
    assert "'num_words'" in str(err.value)
예제 #10
0
def test_mkpassword_not_file_and_list(word_file):
    with pytest.raises(ValueError) as err:
        api.mkpassphrase(word_file=word_file, word_list=internal.WORD_LIST_DEFAULT)
    assert "exactly one of" in str(err.value)
예제 #11
0
def main():
    """Command-line entry point."""
    import mkpassphrase as MP
    from mkpassphrase import api, internal

    wordlists = sorted(internal.WORD_LISTS)
    parser = argparse.ArgumentParser(description="Generate a passphrase.")
    parser.add_argument(
        "-n",
        "--num-words",
        type=int,
        metavar="NUM_WORDS",
        help="Number of words in passphrase "
        "(the default is enough words to reach a security level of {} bits)".
        format(internal.ENTROPY_DEFAULT),
    )
    parser.add_argument(
        "-s",
        "--entropy",
        type=int,
        metavar="ENTROPY",
        help="Target entropy bits "
        "(the default is {} bits)".format(internal.ENTROPY_DEFAULT),
    )
    parser.add_argument(
        "-w",
        "--word-list",
        type=str,
        metavar="WORD_LIST",
        choices=wordlists,
        help="Use built-in wordlist (eff-large [default], eff1, or eff2)",
    )
    parser.add_argument(
        "-f",
        "--word-file",
        type=str,
        metavar="WORD_FILE",
        help="Word file path (one word per line)",
    )
    parser.add_argument(
        "-l",
        "--lowercase",
        action="store_false",
        dest="random_case",
        default=True,
        help="Lowercase words (the default is to capitalize the first letter"
        "of each word with probability 0.5 and use lowercase "
        "for all other letters)",
    )
    parser.add_argument(
        "-p",
        "--pad",
        metavar="PAD",
        default="",
        help="Pad passphrase using PAD as prefix and suffix "
        "(the default is no padding)",
    )
    parser.add_argument(
        "-d",
        "--delimiter",
        dest="delimiter",
        default=" ",
        metavar="DELIMITER",
        help="Use DELIMITER to separate words in passphrase "
        "(the default is a space character)",
    )
    parser.add_argument(
        "-t",
        "--times",
        dest="times",
        type=int,
        default=1,
        metavar="TIMES",
        help="Generate TIMES different passphrases "
        "(the default is to generate 1 passphrase)",
    )
    parser.add_argument("-V",
                        "--version",
                        action="store_true",
                        help="Show version")
    parser.add_argument(
        "-q",
        "--quiet",
        action="store_true",
        help="Print just the passphrase (the default "
        "is to also show the security-level of the generated passphrase(s))",
    )

    args = parser.parse_args()
    if args.version:
        print("%s %s" % (MP.__name__, MP.__version__))
        sys.exit(0)
    if args.num_words is not None and args.num_words < 1:
        parser.exit("--num-words must be positive if provided")
    if args.times < 1:
        parser.exit("--times must be positive if provided")
    if args.word_list and args.word_file:
        parser.exit("only one of --word-list and --word-file is allowed")
    if args.word_file and not os.access(args.word_file, os.R_OK):
        parser.exit("word file does not exist or is not readable: %s" %
                    args.word_file)

    params = vars(args)
    quiet = params.pop("quiet", False)
    times = params.pop("times", 1)
    params.pop("version", None)

    # use the default wordlist if no list or file was provided
    if not args.word_file and not args.word_list:
        params["word_list"] = internal.WORD_LIST_DEFAULT

    passphrases, entropy = api.mkpassphrase(count=times, **params)
    if times == 1:
        passphrases = [passphrases]
    for passphrase in passphrases:
        print(passphrase)

    if not quiet:
        print()
        print("{}-bit security level".format(int(math.floor(entropy))))