Skip to content

Instantly share code, notes, and snippets.

@ceving
Created April 25, 2024 12:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ceving/cb68c8f2392255c5ed4ea65a6a1993e1 to your computer and use it in GitHub Desktop.
Save ceving/cb68c8f2392255c5ed4ea65a6a1993e1 to your computer and use it in GitHub Desktop.
Registration Code

Registration Code Generation

This function creates a registration code with 8 ASCII characters. The aim is to send a user a secret, which can be easily copied by the user into a registration dialog. The secret uses a reduced alphabet of 32 letters and digits. Characters known to be commonly confused by users are removed. The secret is not a password. It is just a personal token to enable the registration in order to prevent annonymous registration attempts.

Requirements

  • pgcrypto: gen_random_bytes

Description

The secret alphabeth has 32 characters. Each character requires 5 bit. A secret with 8 characters reqires 40 bit or 5 byte. The number of different secrets is 2⁴⁰ = 1099511627776.

RND 7 6 5 4 3 2 1 0
0 h4 g4 f4 e4 d4 c4 b4 a4
1 h3 b3 f3 e3 d3 c3 b3 a3
2 h2 g2 f2 e2 d2 c2 b2 a2
3 h1 g1 f1 e1 d1 c1 b1 a1
4 h0 g0 f0 e0 d0 c0 b0 a0

The bits of the characters of the secret are:

CHR
1 a4 a3 a2 a1 a0
2 b4 b3 b2 b1 b0
3 c4 c3 c2 c1 c0
4 d4 d3 d2 d1 d0
5 e4 e3 e2 e1 e0
6 f4 f3 f2 f1 f0
7 g4 g3 g2 g1 g0
8 h4 h3 h2 h1 h0
-- -*- mode: sql; sql-product: postgres; -*-
DROP FUNCTION IF EXISTS registration_code();
CREATE FUNCTION registration_code() RETURNS text
LANGUAGE plpgsql
AS $$
DECLARE
rnd bytea := gen_random_bytes(5); -- 5 random bytes
alpha bytea := 'abcdefghikmnopqrstuvwxyz23456789'::bytea; -- alphabeth
code text := ''; -- code
r integer; -- iterate random bytes
i integer; -- iterate bits of random bytes and code characters
b integer; -- current random byte
a integer[]; -- alphabeth indexes of code characters
BEGIN
FOR i IN 0..7 LOOP
a[i] := 0;
END LOOP;
FOR r IN 0..4 LOOP
b := get_byte(rnd, r);
FOR i IN 0..7 LOOP
a[i] := (a[i] << 1) | (b & 1);
b := b >> 1;
END LOOP;
END LOOP;
FOR i IN 0..7 LOOP
code := code || chr(get_byte(alpha, a[i]));
END LOOP;
RETURN code;
END
$$;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment