Need help with password regenerator

Pages: 12
Yeah, that seems right. But, why would it accept an infinitely large input?
Here's a first version, written in D, and following Script Coder's suggestion.
Unfortunately the D library developers have yet to implement SHA-2 so I had to use SHA-1.

What else can I say? It seems to be working. Let me know if you spot something wrong.

And if you actually want to use this utility, I suggest generating a custom Mode (containing no more than 256 characters for obvious reasons) and to always chain the program at least twice, as in:

$ echo MyPassword | passregen 20 | passregen 24


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import std.array;
import std.conv;
import std.digest.sha;
import std.stdio;

alias SHA1 HashFunction;

version = Mode1;

void main(string[] args)
{
    version (Mode0)
    {
        immutable string mode =
            "abcdefghijklmnopqrstuvwxyz"
            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            "0123456789";
    }

    version (Mode1)
    {
        immutable string mode =
            "abcdefghijklmnopqrstuvwxyz"
            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            "0123456789"
            "_";
    }

    version (Mode2)
    {
        immutable string mode =
            "abcdefghijklmnopqrstuvwxyz"
            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            "0123456789"
            "~`!@#$%^&*()_-+=|\\{[}]:;\"'<,>.?/";
    }

    /*
        Here you can add custom modes, with the obvious caveat
        that if you lose your program, you will no longer be
        able to regenerate your passwords.
    */
    /+
    version (CustomMode)
    {
        immutable string mode = "";
    }
    +/

    void printUsage(string errorMessage = "")
    {
        stderr.writeln("\nPassReGen usage:");
        stderr.writeln("\n\t", args[0], " length [filename]\n");
        stderr.writeln("Where:\n\t`length' is an unsigned integer, representing");
        stderr.writeln("\tthe generated password's length in characters, and\n");
        stderr.writeln("\t`filename' is an optional parameter representing the input file.");
        stderr.writeln("\tIf it is missing, the program reads a line from Standard Input.\n");
        stderr.writeln("Usage examples:");
        stderr.writeln('\t', args[0], " 20 readme.txt");
        stderr.writeln("\techo MyPassword| ", args[0], " 20\n");

        if (!errorMessage.empty)
            stderr.writeln(errorMessage);

        stderr.writeln();
    }

    ubyte[digestLength!HashFunction] indices;

    if (args.length == 2)
    {
        indices = digest!HashFunction(readln());
    }
    else
    if (args.length == 3)
    {
        indices = digest!HashFunction(File(args[2]).byChunk(4096));
    }
    else
    {
        printUsage();
        return;
    }

    char[] password;

    password.length = parse!size_t(args[1]);

    foreach (i, ref c; password)
    {
        if (i != 0 && i % indices.length == 0)
            indices = digest!HashFunction(indices);

        c = mode[indices[i % indices.length] % mode.length];
    }

    writeln(password);
}

D looks alot like C#.
closed account (S6k9GNh0)
It's inspired by it quite a bit. That and Java syntax. And you'll find hints of various other languages here and there.
Last edited on
@Catfish666 That looks quite cool. I do not have a D compiler, but I might convert it to c++ if I find the time. Also, if you really wanted to you could self implement a SHA-2 library in D. I am sure the D community would be grateful.

It's inspired by it quite a bit. That and Java syntax. And you'll find hints of various other languages here and there.

True most of the code is readable, but would someone mind explaining the following pieces of syntax do:
version

/+ +/
Guessing this is a type of comment.
digestLength!HashFunction
This looks like a type of member reference, similar to C++'s ->

EDIT: Made it look better
Last edited on
closed account (Dy7SLyTq)
i remember in an earlier post that ! is for templates. i could be wrong though
http://dlang.org/template.html
http://dlang.org/ddoc.html for the /+ +/
idk what version is
Thank you.
The ! operator refers to a template namespace. version still confuses me.
Script Coder wrote:
That looks quite cool. I do not have a D compiler, but I might convert it to c++ if I find the time.

Would be interesting to see its C++ doppelganger. Perhaps using this library could help a little:
http://www.cryptopp.com/

As for not having a D compiler, I'll just leave this link here, just in case:
http://dlang.org/download.html

Script Coder wrote:
The ! operator refers to a template namespace.

It's for single template parameters. For instance (made up code):

1
2
std::vector<int> vi;
std::pair<int, char> pic;
std::vector!int vi;
std::pair!(int, char) pic;


Script Coder wrote:
version still confuses me.

You can think of it like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
#define Mode1

#ifdef Mode0
    // ...
#endif

#ifdef Mode1
    // ...
#endif

#ifdef Mode2
    // ...
#endif 


So if you do something funky like...

1
2
3
version = Mode0;
version = Mode1;
version = Mode2;


... you'll get a compilation error because the mode string is redefined. I think.
Would be interesting to see its C++ doppelganger.

Well I tried my best, let me know what you guys think. Also, thanks for the link, it a wonderful and easy library to use.

As for not having a D compiler

As much as I really want to learn other languages, I have to stay focused on C++ for the IOI next year.
Also, thank you for the D explanations.

As seen I ran the digest through len+1 times to ensure that things like:
cheese 14

and
cheese 17

Would not have the same prefix.

Here is the code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cryptopp/sha.h>
#include <cstdlib>

void SHA256(std::string data, byte* digest) {
	
	CryptoPP::SHA256().CalculateDigest(digest, (byte*) data.data(), data.length());
} 

int main(int argc, char** argv) {
	int len;
	std::string input, password;
	byte digest[CryptoPP::SHA256::DIGESTSIZE];
	std::string const mode="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~`!@#$%^&*()_-+=|\\{[}]:;\"'<,>.?/";
	
	if(argc!=3) return(1);
	input=argv[1];
	len=atoi(argv[2]);
	
	SHA256(input, digest);
	for(int i=0; i<len; ++i)
		SHA256(std::string((char*)digest), digest);
	
	for(int i=0; i<len; ++i) {
		std::cout<<mode[digest[i]%mode.length()];
	}
	std::cout<<'\n';
}
@ Script Coder: to be honest I don't like how you mix std::string and C-style byte arrays. You even included vector and then never used it.

Those C-style casts hint that there's room for improvement.

Also from what I see your program can't be piped, quitting immediately if there aren't exactly three arguments. Then again, perhaps piping doesn't really help that much.

Finally, I'm curious why you chose SHA-256 instead of SHA-384 or SHA-512.
Catfish666 wrote:
to be honest I don't like how you mix std::string and C-style byte arrays

I do not like it either, but I either have to use solely C-style byte arrays, or I have to mix them. I cannot think of another alternative.

Catfish666 wrote:
You even included vector and then never used it.

Allow me to explain. I compete in many programming competitions and the first four include's are automatically placed there for speed.

Catfish666 wrote:
Also from what I see your program can't be piped

I do not know how to pipe, but I'll look it up, if it is really necessary. Which as far as I understand just confuses your end user, especially if they are not tech savy.

Catfish666 wrote:
Finally, I'm curious why you chose SHA-256 instead of SHA-384 or SHA-512.

256/8=32. Where are you ever allowed to enter a password longer than this? Is that amount of security needed?
It is easily fixable, one could even allow for multiple options if one develops the program further.
closed account (Dy7SLyTq)
I do not like it either, but I either have to use solely C-style byte arrays, or I have to mix them. I cannot think of another alternative.

use c++ and write a wrapper in the form of a class.

could someone explain piping? because i thought its just mapping input from output.

Allow me to explain. I compete in many programming competitions and the first four include's are automatically placed there for speed.

what competitions are these? ive been looking to get into a few
DTSCode wrote:
use c++

Was I not using c++?

DTSCode wrote:
write a wrapper in the form of a class.

Please give more detail, I do not understand this concept fully, and thus do not understand how it solves anything.

DTSCode wrote:
what competitions are these? ive been looking to get into a few

These are the ones I compete and practice on regularly:
USACO - 13 December is the next one. Has a training site, probably the best.
COCI - 7 December is the next one
CodeForces - continuously has competitions. Has timed past papers.

You can also practice on past papers with all of these. Also, the above are only algorithmic contests. Good luck.
closed account (Dy7SLyTq)
never mind... i didnt read your code properly. i thought it was more c than c++. forget i said that
Script Coder wrote:
I do not like it either, but I either have to use solely C-style byte arrays, or I have to mix them. I cannot think of another alternative.
std::vector<byte> followed by digest.data() or &digest.front()?
Last edited on
Wow, okay thank you Catfish666
Topic archived. No new replies allowed.
Pages: 12