Webwide is the inclusive discussion community for web designers, developers & makers.

Whether you're an enthusiast, in training, or a seasoned pro – you'll fit right in at Webwide. Creating an account is fast, easy and completely free so you can start participating right away.

Read our Code of Conduct

Free Membership Benefits

  • Participate in hundreds of interesting discussions
  • Network with industry peers and make new connections
  • Show off your own projects and relevant content
  • Get help and feedback for your coding and designs
  • Buy and sell services and resources in the marketplace
  • Participate in our friendly community challenges
  • Earn trophies and work your way up our leaderboards
  • Enjoy exclusive Webwide member discounts and offers
  • ...and so much more!

Entries Closed ⛳️ [Programming, Code Golf] Password Generator

Adam

Mr. Webwide
Administrator
Joined
Sep 24, 2019
Messages
622
Reaction score
581
Points
665
Location
United Kingdom
Local Time
Today, 13:57
Pronouns
he/him
Close date: 3rd December 2019 12:00pm UTC

Code golf is a competition where the aim is to complete a task using the shortest possible source code. This challenge may be completed using vanilla JavaScript, PHP, Python or Ruby. 3rd-party dependencies are not allowed, standard libs are.

Submit your code below to solve the following problem:
  • Create a password generator
  • The password must contain exactly 16 characters, and the characters are limited to the following character classes: a-z, A-Z, 0-9, and !#$%&()*+,-./:;<=>? @[]^_{|}~ (note there is a space character in this class).
  • The password must contain a character from each character class.
  • Each character from all the character classes must have an equal chance of being picked.
  • The password cannot have predictable patterns and must generate a new one each time it is run.
  • The script must run from start to finish without any additional user input.
The shortest entry will receive a first place position and all working entries will receive points on our community challenge leaderboard.

If anybody stumbles on this thread after we're done, please don't use any of these in real applications... 😆
 
Last edited:
  • Haha
  • Like
Reactions: ek1 and Gummibeer

kylejrp

Member
Joined
Nov 20, 2019
Messages
2
Reaction score
3
Points
5
Location
Canada
Local Time
Today, 05:57
Here's a WIP attempt in Javascript (217 characters), I'm going to refine this later after reading up on some code golf tips.

JavaScript:
var z='x'
while(!(z.match(/[a-z]/)&&z.match(/[A-Z]/)&&z.match(/\d/)&&z.match(/\W/)))
z=[...Array(95)].map((_,i)=>String.fromCharCode(32+i)).map((_,__,a)=>a[Math.floor((Math.random()*a.length))]).slice(0,16).join('')
z
 

Gummibeer

Well-known member
Joined
Oct 5, 2019
Messages
664
Reaction score
517
Points
635
Age
26
Location
Hamburg, Germany
Local Time
Today, 14:57
Website
gummibeer.de
@Adam I want and have to soften two rules.
Each character from all the character classes must have an equal chance of being picked.
Without a ton of code or external libraries/hardware it's impossible to guarantee this. The most common solution would be

a=[...]
b=a[round(random(0, 1) * (a.length()-1))]

But this won't have equal chances for all. At least the first and last elements will only have half the chance.

random(0,1) * (3-1)
will result in all numbers between 0-2 which will get rounded. By applying normal rounding this will result in.
0 = x<0.5 | 25%
1 = 0.5<=x<1.5 |50%
2 = 1.5<=x | 25%

So at least I would like to soften it to allow this implementation.

The password cannot have predictable patterns and must generate a new one each time it is run.
Most default random algorithms are predictable if you know the machine and/or timestamp of generation. Because most or time or garbage based, use low level code randomness and so on to be fast but cryptographic unsecure.
So this rule should also get softened.
 
Last edited:

Adam

Mr. Webwide
Administrator
Joined
Sep 24, 2019
Messages
622
Reaction score
581
Points
665
Location
United Kingdom
Local Time
Today, 13:57
Pronouns
he/him
@Adam I want and have to soften two rules.

Without a ton of code or external libraries/hardware it's impossible to guarantee this. The most common solution would be

a=[...]
b=a[round(random(0, 1) * (a.length()-1))]

But this won't have equal chances for all. At least the first and last elements will only have half the chance.

random(0,1) * (3-1)
will result in all numbers between 0-2 which will get rounded. By applying normal rounding this will result in.
0 = x<0.5 | 25%
1 = 0.5<=x<1.5 |50%
2 = 1.5<=x | 25%

So at least I would like to soften it to allow this implementation.


Most default random algorithms are predictable if you know the machine and/or timestamp of generation. Because most or time or garbage based, use low level code randomness and so on to be fast but cryptographic unsecure.
So this rule should also get softened.
That’s fine. 👍
 

Gummibeer

Well-known member
Joined
Oct 5, 2019
Messages
664
Reaction score
517
Points
635
Age
26
Location
Hamburg, Germany
Local Time
Today, 14:57
Website
gummibeer.de
And now I'm an asshole!
@kylejrp solution is wrong. 🙈

That's the code generating the possible character pool:
JavaScript:
var z = {};
[...Array(95)]
    .map((_, i) => String.fromCharCode(32 + i))
    .forEach(a => z[a] = /[a-zA-Z0-9!#\$%&\(\)\*\+,\-\.\/:;<=>\? @\[\]\^_{\|}~]/.test(a));
z;
And that's the result/value of z:
JSON:
{"0":true,"1":true,"2":true,"3":true,"4":true,"5":true,"6":true,"7":true,"8":true,"9":true," ":true,"!":true,"\"":false,"#":true,"$":true,"%":true,"&":true,"'":false,"(":true,")":true,"*":true,"+":true,",":true,"-":true,".":true,"/":true,":":true,";":true,"<":true,"=":true,">":true,"?":true,"@":true,"A":true,"B":true,"C":true,"D":true,"E":true,"F":true,"G":true,"H":true,"I":true,"J":true,"K":true,"L":true,"M":true,"N":true,"O":true,"P":true,"Q":true,"R":true,"S":true,"T":true,"U":true,"V":true,"W":true,"X":true,"Y":true,"Z":true,"[":true,"\\":false,"]":true,"^":true,"_":true,"`":false,"a":true,"b":true,"c":true,"d":true,"e":true,"f":true,"g":true,"h":true,"i":true,"j":true,"k":true,"l":true,"m":true,"n":true,"o":true,"p":true,"q":true,"r":true,"s":true,"t":true,"u":true,"v":true,"w":true,"x":true,"y":true,"z":true,"{":true,"|":true,"}":true,"~":true}
There are multiple false values like " ' \ ` and all of them pass the too broad \W regex which matches anything other than a letter, digit or underscore. Which introduces the next problem that aB0xxxxxxxxxxxx_ won't pass the while condition but it is a valid password because it contains all required character sets.
JavaScript:
var z = 'aB0xxxxxxxxxxxx_'; !(z.match(/[a-z]/)&&z.match(/[A-Z]/)&&z.match(/\d/)&&z.match(/\W/));
// z = true
But I like the idea behind this solution! :)
 
  • Like
Reactions: kylejrp and Adam

Gummibeer

Well-known member
Joined
Oct 5, 2019
Messages
664
Reaction score
517
Points
635
Age
26
Location
Hamburg, Germany
Local Time
Today, 14:57
Website
gummibeer.de
I would say that this is a fixed version with 243 chars
JavaScript:
for(var z='';!(/[a-z]/.test(z)&&/[A-Z]/.test(z)&&/[\d]/.test(z)&&/[!#$%&()*+,\-.\/:;<=>? @\[\]^_{|}~]/.test(z));)z=[...Array(95)].map((t,a)=>String.fromCharCode(32+a)).map((t,a,e)=>e[Math.floor(Math.random()*e.length)]).slice(0,16).join('')
z
It passes my quick mocha test-suite.

JavaScript:
require('should');
const mocha = require('mocha');
const describe = mocha.describe;
const it = mocha.it;

const kylejrp = require('../src/kylejrp');
const gummibeer = require('../src/gummibeer');

const test = function(user) {
    [...Array(10000)].forEach((_, i) => {
        it(i + ') will generate valid password', function () {
            const password = user();

            password.should.be.a.String().and.have.length(16);
            /[a-z]/.test(password).should.be.true(password + ' should contain [a-z]');
            /[A-Z]/.test(password).should.be.true(password + ' should contain [A-Z]]');
            /[0-9]/.test(password).should.be.true(password + ' should contain [0-9]');
            /[!#$%&()*+,\-.\/:;<=>? @\[\]^_{|}~]/.test(password).should.be.true(password + ' should contain [!#$%&()*+,-./:;<=>? @[]^_{|}~]');
        });
    });
};

describe('kylejrp', function () {
    test(kylejrp);
});

describe('gummibeer', function () {
    test(gummibeer);
});
GIT: Gummibeer/webwide-challenge-2019-11
 
Last edited:
  • Like
Reactions: Adam

Gummibeer

Well-known member
Joined
Oct 5, 2019
Messages
664
Reaction score
517
Points
635
Age
26
Location
Hamburg, Germany
Local Time
Today, 14:57
Website
gummibeer.de
And here is my PHP solution:

PHP:
<?php $s=array_values(array_filter(array_map('chr',range(32,126)),fn($c)=>strpos('\'"`\\',$c)===false));do{for($p='';strlen($p)<16;str_shuffle($p)){$p.=$s[random_int(0,count($s)-1)];}}while(!(preg_match('/[a-z]/',$p)&&preg_match('/[A-Z]/',$p)&&preg_match('/[\d]/',$p)&&preg_match('/[\!\#\$\%\&\(\)\*\+\,\-\.\/\:\;\<\=\>\? \@\[\]\^\_\{\|\}\~]/',$p)));return $p;
Including the opening tag it's 360 characters. 🎉 Most characters are used by all the function prefixes array_ preg_ str_ ...

I've also added the solution to TravisCI including the required tests to prove a solution (10000 runs each).

 
  • Hot
Reactions: Adam