Compare commits
No commits in common. "master" and "v0.2.0" have entirely different histories.
10
.drone.yml
10
.drone.yml
@ -3,7 +3,11 @@ type: docker
|
|||||||
name: main
|
name: main
|
||||||
|
|
||||||
trigger:
|
trigger:
|
||||||
event: tag
|
branch:
|
||||||
|
- master
|
||||||
|
event:
|
||||||
|
- push
|
||||||
|
- tag
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: build-windows
|
- name: build-windows
|
||||||
@ -21,11 +25,13 @@ steps:
|
|||||||
|
|
||||||
- name: release
|
- name: release
|
||||||
image: plugins/gitea-release
|
image: plugins/gitea-release
|
||||||
|
when:
|
||||||
|
event: tag
|
||||||
depends_on:
|
depends_on:
|
||||||
- build-windows
|
- build-windows
|
||||||
- build-linux
|
- build-linux
|
||||||
settings:
|
settings:
|
||||||
base_url: 'https://git.jfmonty2.com'
|
base_url: 'https://git.jfmonty2.com/jfmonty2/passphrase.git'
|
||||||
files:
|
files:
|
||||||
- passphrase_linux
|
- passphrase_linux
|
||||||
- passphrase.exe
|
- passphrase.exe
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,4 +1,2 @@
|
|||||||
*.exe
|
*.exe
|
||||||
data/BNC/*
|
data/BNC/*
|
||||||
data/dictionary*
|
|
||||||
!data/dictionary.txt
|
|
@ -1,6 +1,6 @@
|
|||||||
# Package
|
# Package
|
||||||
|
|
||||||
version = "0.3.1"
|
version = "0.2.0"
|
||||||
author = "Joseph Montanaro"
|
author = "Joseph Montanaro"
|
||||||
description = "Passphrase generator and dictionary builder"
|
description = "Passphrase generator and dictionary builder"
|
||||||
license = "none"
|
license = "none"
|
||||||
@ -12,7 +12,6 @@ bin = @["passphrase"]
|
|||||||
|
|
||||||
requires "nim >= 1.0"
|
requires "nim >= 1.0"
|
||||||
requires "nimcrypto >= 0.4.8"
|
requires "nimcrypto >= 0.4.8"
|
||||||
requires "zippy >= 0.7.3"
|
|
||||||
|
|
||||||
|
|
||||||
# Tasks n scripts
|
# Tasks n scripts
|
||||||
@ -33,13 +32,6 @@ task(dictionary, "Generate dictionary from BNC XML files"):
|
|||||||
echo output.strip().splitlines()[^1]
|
echo output.strip().splitlines()[^1]
|
||||||
|
|
||||||
|
|
||||||
task(pack, "Compress dictionary file"):
|
|
||||||
echo "Packing dictionary"
|
|
||||||
echo runCmd("nim c --run src/dictionary.nim data/dictionary.txt data/dictionary.pack")
|
|
||||||
|
|
||||||
|
|
||||||
before(build):
|
before(build):
|
||||||
if not fileExists("data/dictionary.txt"):
|
if not fileExists("data/dictionary.txt"):
|
||||||
dictionaryTask()
|
dictionaryTask()
|
||||||
if not fileExists("data/dictionary.pack"):
|
|
||||||
packTask()
|
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
import std/strutils
|
|
||||||
import zippy
|
|
||||||
|
|
||||||
|
|
||||||
type
|
|
||||||
Dictionary* = object
|
|
||||||
words: string
|
|
||||||
width: uint32
|
|
||||||
|
|
||||||
|
|
||||||
proc `[]`*(d: Dictionary, i: Natural): string =
|
|
||||||
let start = i.uint32 * d.width
|
|
||||||
d.words[start ..< start + d.width]
|
|
||||||
|
|
||||||
|
|
||||||
proc len*(d: Dictionary): int =
|
|
||||||
result = d.words.len div d.width.int
|
|
||||||
|
|
||||||
|
|
||||||
proc addU32(s: var string, i: uint32) =
|
|
||||||
for offset in 0..3:
|
|
||||||
let b = cast[char](i shr (offset * 8))
|
|
||||||
s.add(b)
|
|
||||||
|
|
||||||
|
|
||||||
proc getU32(s: string): uint32 =
|
|
||||||
for offset in 0..3:
|
|
||||||
result = result or (cast[uint32](s[offset]) shl (offset * 8))
|
|
||||||
|
|
||||||
|
|
||||||
proc pack*(d: Dictionary): string =
|
|
||||||
var data: string
|
|
||||||
data.addU32(d.width)
|
|
||||||
data.add(d.words)
|
|
||||||
data.compress(dataFormat = dfGzip)
|
|
||||||
|
|
||||||
|
|
||||||
proc unpack*(p: string): Dictionary =
|
|
||||||
let data = p.uncompress(dataFormat = dfGzip)
|
|
||||||
result.width = data.getU32()
|
|
||||||
result.words = data[4..^1]
|
|
||||||
|
|
||||||
|
|
||||||
proc loadWords*(path: string): Dictionary =
|
|
||||||
result.width = 25
|
|
||||||
for word in readFile(path).strip().splitLines():
|
|
||||||
if word.len > 25:
|
|
||||||
continue
|
|
||||||
|
|
||||||
result.words.add(word)
|
|
||||||
for _ in 0 ..< (25 - word.len):
|
|
||||||
result.words.add(' ')
|
|
||||||
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
import std/os
|
|
||||||
echo "Loading words..."
|
|
||||||
let dictionary = loadWords(paramStr(1))
|
|
||||||
echo "Packing dictionary..."
|
|
||||||
let packed = dictionary.pack()
|
|
||||||
writeFile(paramStr(2), packed)
|
|
||||||
echo "Dictionary packed."
|
|
@ -1,19 +1,48 @@
|
|||||||
import std/[os, strutils]
|
import std/[os, strutils]
|
||||||
import nimcrypto/sysrand
|
import nimcrypto/sysrand
|
||||||
import dictionary
|
|
||||||
|
|
||||||
|
|
||||||
const packed = staticRead("../data/dictionary.pack")
|
type Dictionary = object
|
||||||
|
words: string
|
||||||
|
offsets: seq[uint32]
|
||||||
|
|
||||||
|
|
||||||
proc genPassphrase(dict: Dictionary, length, dictSize: int): string =
|
proc `[]`(d: Dictionary, i: Natural): string =
|
||||||
|
# last word has no following start index, so we have to fake it
|
||||||
|
# also strings are indexed with ints
|
||||||
|
let slice = if i == d.offsets.high:
|
||||||
|
d.offsets[i].int .. d.words.high
|
||||||
|
else:
|
||||||
|
d.offsets[i].int ..< d.offsets[i + 1].int
|
||||||
|
|
||||||
|
result = d.words[slice]
|
||||||
|
|
||||||
|
|
||||||
|
proc len(d: Dictionary): int =
|
||||||
|
result = d.offsets.len
|
||||||
|
|
||||||
|
|
||||||
|
proc loadWords(): Dictionary =
|
||||||
|
for word in staticRead("../data/dictionary.txt").strip().splitLines():
|
||||||
|
let startIdx = result.words.len.uint32
|
||||||
|
result.offsets.add(startIdx)
|
||||||
|
result.words.add(word)
|
||||||
|
|
||||||
|
|
||||||
|
const dict = loadWords()
|
||||||
|
|
||||||
|
|
||||||
|
proc genPassphrase(length, dictSize: int): string =
|
||||||
|
if dictSize < 100 or dictSize > dict.len:
|
||||||
|
quit("Dictionary size must be between 100 and " & $dict.len, 1)
|
||||||
|
|
||||||
var rands = newSeq[uint64](length)
|
var rands = newSeq[uint64](length)
|
||||||
discard randomBytes(rands)
|
discard randomBytes(rands)
|
||||||
|
|
||||||
var words: seq[string]
|
var words: seq[string]
|
||||||
for r in rands:
|
for r in rands:
|
||||||
let i = r mod dictSize.uint64
|
let i = r mod dictSize.uint64
|
||||||
words.add(dict[i].strip())
|
words.add(dict[i])
|
||||||
result = words.join(" ")
|
result = words.join(" ")
|
||||||
|
|
||||||
|
|
||||||
@ -22,8 +51,7 @@ const help = """Usage:
|
|||||||
|
|
||||||
Defaults to length of 4 and dictionary size of 25,000."""
|
Defaults to length of 4 and dictionary size of 25,000."""
|
||||||
|
|
||||||
|
proc parseInput(): (int, int) =
|
||||||
proc parseInput(dictLen: int): (int, int) =
|
|
||||||
let params = commandLineParams()
|
let params = commandLineParams()
|
||||||
if "-h" in params or "--help" in params:
|
if "-h" in params or "--help" in params:
|
||||||
echo help
|
echo help
|
||||||
@ -37,20 +65,19 @@ proc parseInput(dictLen: int): (int, int) =
|
|||||||
try:
|
try:
|
||||||
length = parseInt(params[0])
|
length = parseInt(params[0])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
quit('"' & params[0] & "\" is not a valid passphrase length.", 1)
|
quit(params[0] & " is not a valid passphrase length.", 1)
|
||||||
|
|
||||||
if params.len > 1:
|
if params.len > 1:
|
||||||
try:
|
try:
|
||||||
dictSize = parseInt(params[1])
|
dictSize = parseInt(params[1])
|
||||||
if dictSize < 100 or dictSize > dictLen:
|
if dictSize < 100 or dictSize > dict.len:
|
||||||
quit("Dictionary size must be between 100 and " & $dictLen, 1)
|
quit("Dictionary size must be between 100 and " & $dict.len, 1)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
quit('"' & params[1] & "\" is not a valid dictionary size.", 1)
|
quit(params[1] & " is not a valid dictionary size.", 1)
|
||||||
|
|
||||||
result = (length, dictSize)
|
result = (length, dictSize)
|
||||||
|
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
let dict = packed.unpack()
|
let (length, dictSize) = parseInput()
|
||||||
let (length, dictSize) = parseInput(dict.len)
|
echo genPassphrase(length, dictSize)
|
||||||
echo genPassphrase(dict, length, dictSize)
|
|
||||||
|
@ -67,7 +67,7 @@ iterator iterWords*(filename: string): string =
|
|||||||
|
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
let path = r"C:\Users\Joe\Documents\Code\passphrase\data\BNC\2554\download\Texts\A\A0\A00.xml"
|
let path = r"C:\Users\Joe\Documents\Code\words\BNC\2554\download\Texts\A\A0\A00.xml"
|
||||||
var count = 0
|
var count = 0
|
||||||
for word in iterWords(path):
|
for word in iterWords(path):
|
||||||
inc count
|
inc count
|
||||||
|
Loading…
x
Reference in New Issue
Block a user