All Projects → taskcluster → slugid-go

taskcluster / slugid-go

Licence: MPL-2.0 license
A go (golang) port of https://github.com/taskcluster/slugid

Programming Languages

go
31211 projects - #10 most used programming language
shell
77523 projects

slugid-go - Compressed UUIDs for go (golang)

GoDoc Build Status Coverage Status License

slugid-go provides:

  • A go (golang) module for generating v4 UUIDs and encoding them into 22 character URL-safe base64 slug representation (see RFC 4648 sec. 5).
  • A command line tool to provides the same functions

Slugs are url-safe base64 encoded v4 uuids, stripped of base64 = padding.

There are two methods for generating slugs - slugid.V4() and slugid.Nice().

  • The slugid.V4() method returns a slug from a randomly generated v4 uuid.
  • The slugid.Nice() method returns a v4 slug which conforms to a set of "nice" properties. At the moment the only "nice" property is that the slug starts with [A-Za-f], which in turn implies that the first (most significant) bit of its associated uuid is set to 0.

The purpose of the slugid.Nice() method is to support having slugids which can be used in more contexts safely. Regular slugids can safely be used in urls, and for example in AMQP routing keys. However, slugs beginning with - may cause problems when used as command line parameters.

In contrast, slugids generated by the slugid.Nice() method can safely be used as command line parameters. This comes at a cost to entropy (121 bits vs 122 bits for regular v4 slugs).

Slug consumers should consider carefully which of these two slug generation methods to call. Is it more important to have maximum entropy, or to have slugids that do not need special treatment when used as command line parameters? This is especially important if you are providing a service which supplies slugs to unexpecting tool developers downstream, who may not realise the risks of using your regular v4 slugs as command line parameters, especially since this would arise only as an intermittent issue (one time in 64).

Generated slugs take the form [A-Za-z0-9_-]{22}, or more precisely:

  • slugid.V4() slugs conform to [A-Za-z0-9_-]{8}[Q-T][A-Za-z0-9_-][CGKOSWaeimquy26-][A-Za-z0-9_-]{10}[AQgw]

  • slugid.Nice() slugs conform to [A-Za-f][A-Za-z0-9_-]{7}[Q-T][A-Za-z0-9_-][CGKOSWaeimquy26-][A-Za-z0-9_-]{10}[AQgw]

RFC 4122 defines the setting of 6 bits of the v4 UUID which implies v4 slugs provide 128 - 6 = 122 bits entropy. Due to the (un)setting of the first bit of "nice" slugs, nice slugs provide therefore 121 bits entropy.

These are the fixed six bits:

  • bit 48: 0
  • bit 49: 1
  • bit 50: 0
  • bit 51: 0
  • bit 64: 1
  • bit 65: 0

Splitting the 128 bits into groups of six to see the base64 character boundaries, we get:

position:                                                                                                                 11 111111 111111 111111 111111 11
                 11 111111 112222 222222 333333 333344 444444 445555 555555 666666 666677 777777 778888 888888 999999 999900 000000 001111 111111 222222 22
      012345 678901 234567 890123 456789 012345 678901 234567 890123 456789 012345 678901 234567 890123 456789 012345 678901 234567 890123 456789 012345 67
bin: |......|......|......|......|......|......|......|......|0100..|......|....10|......|......|......|......|......|......|......|......|......|......|..0000|
b64: |   α  |   α  |   α  |   α  |   α  |   α  |   α  |   α  |   β  |   α  |   γ  |   α  |   α  |   α  |   α  |   α  |   α  |   α  |   α  |   α  |   α  |   δ  |

Using the base64url encoding scheme, we can see which characters are allowed at each of the 22 positions.

  • α = 0b...... ∈ {
000000 A
000001 B
000010 C
000011 D
000100 E
000101 F
000110 G
000111 H
001000 I
001001 J
001010 K
001011 L
001100 M
001101 N
001110 O
001111 P
010000 Q
010001 R
010010 S
010011 T
010100 U
010101 V
010110 W
010111 X
011000 Y
011001 Z
011010 a
011011 b
011100 c
011101 d
011110 e
011111 f
100000 g
100001 h
100010 i
100011 j
100100 k
100101 l
100110 m
100111 n
101000 o
101001 p
101010 q
101011 r
101100 s
101101 t
101110 u
101111 v
110000 w
110001 x
110010 y
110011 z
110100 0
110101 1
110110 2
110111 3
111000 4
111001 5
111010 6
111011 7
111100 8
111101 9
111110 -
111111 _

}

  • β = 0b0100.. ∈ {
010000 Q
010001 R
010010 S
010011 T

}

  • γ = 0b....10 ∈ {
000010 C
000110 G
001010 K
001110 O
010010 S
010110 W
011010 a
011110 e
100010 i
100110 m
101010 q
101110 u
110010 y
110110 2
111010 6
111110 -

}

  • δ = 0b..0000 ∈ {
000000 A
010000 Q
100000 g
110000 w

}

Thus we reach a 22 character encoding of:

  • α{8}βαγα{10}δ

which denormalised becomes:

  • ^[A-Za-z0-9_-]{8}[Q-T][A-Za-z0-9_-][CGKOSWaeimquy26-][A-Za-z0-9_-]{10}[AQgw]$

Go library usage

import "github.com/taskcluster/slugid-go/slugid"

...

// Generate "nice" URL-safe base64 encoded UUID version 4 (random)
slug := slugid.Nice()  // a8_YezW8T7e1jLxG7evy-A

// Alternative, if slugs will not be used as command line parameters
slug := slugid.V4()    // -9OpXaCORAaFh4sJRk7PUA

// Get [UUID](https://godoc.org/github.com/pborman/uuid#UUID) from slug
uuid := slugid.Decode(slug)

// Get slug from [UUID](https://godoc.org/github.com/pborman/uuid#UUID)
slug := slugid.Encode(uuid)

Installing command line tool

Binary installation

Download the slug command line tool for your platform from here.

Source installation

Requirements:

  • go (golang) v1.11 or higher
  • ${GOPATH}/bin is in your path

Run:

go get github.com/taskcluster/slugid-go/cmd/slug

Command line usage

Usage:
  slug [-n|--nice|-r|--v4] [COUNT]
  slug encode [UUID...|-]
  slug decode [SLUGID...|-]
  slug -h|--help
  slug -v|--version

  slug [-n|--nice|-r|--v4] [COUNT]  Generates new slug(s). If -r or --v4 is
                                    provided, regular v4 UUID are used for
                                    generating the slug(s). In all other cases
                                    (-n, --nice, or *no* option) "nice" slugs
                                    are generated. COUNT specifies how many
                                    slugs to generate, default is one. Slugs
                                    are output on separate lines.

  slug decode (-|[SLUGID...])       Outputs the v4 UUID(s) represented by the
                                    given SLUGID(s), or slugid(s) passed via
                                    standard in (one per line) if '-' is
                                    provided. UUID(s) are output one per line,
                                    in the order they were specified. If no
                                    slugids are provided as command line options
                                    or via '-' option, slug generates no output
                                    and exits successfully.

  slug encode (-|[UUID...])         Outputs the SLUGID(s) represented by the
                                    given UUID(s), or UUID(s) passed via
                                    standard in (one per line) if '-' is
                                    provided. SLUGIDs are output one per line,
                                    in the order they were specified. If no
                                    UUIDs are provided as command line options
                                    or via '-' option, slug generates no output
                                    and exits successfully.

  slug -h|--help                    Displays this help page.

  slug -v|--version                 Displays the version of the slug command
                                    line tool.


Exit Codes:

   0: Success
   1: Unrecognised command line options
  64: Cannot decode invalid slug into a UUID
  65: Problem reading standard input during slug decoding
  66: Cannot encode invalid uuid into a slug
  67: Problem reading standard input during slug encoding
  68: Invalid value passed in for command line option COUNT

Examples

  $ slug 10
  RDBdHcXuTUq5ghG1wMTArQ
  BwwjV68MS3aQpkJynFZg9w
  QjbIAaOlSK-in5Hveh0T4w
  YGw68ONSR76wruU85RnvjA
  M0eS8zm5RE2qKKURM_1q9g
  ET23t51DSS2c57PA24QQGg
  cu9mg-T6Rem9LuXBdHd9Ig
  OxghknAoS9ORYPocd9HFUg
  Yg6Yei4QQl-iqdZ3udJlLw
  Ek924JDBRGeA6t6PiNz6UQ

  $ slug --v4 2
  -0eS8zm5RE2qKKURM_1q9g
  OxghknAoS9ORYPocd9HFUg

  $ slug decode OxghknAoS9ORYPocd9HFUg SJZbHUBSQLaichv2auLqGQ EChNNJAyS0SeUMlRWCnJ1A
  3b182192-7028-4bd3-9160-fa1c77d1c552
  48965b1d-4052-40b6-a272-1bf66ae2ea19
  10284d34-9032-4b44-9e50-c9515829c9d4

  $ echo 'f47ac10b-58cc-4372-a567-0e02b2c3d479 81d6bb7e-985c-409b-af6c-4721b4a38ec6' \
              | tr ' ' '\n' | slug encode -
  9HrBC1jMQ3KlZw4CssPUeQ
  gda7fphcQJuvbEchtKOOxg

  $ slug 5 | slug decode -
  3405ed8e-e39f-4a3c-a0ea-e107950757f5
  1df41b41-18a2-4d85-bdde-8a73f02a5014
  5fe568dd-6bfd-4f58-8740-17bea665c2ac
  2464a287-7f82-42ad-9b7d-1e26639d569a
  1c936d1b-104c-4abf-97b4-f586371e8742

  $ slug 5 | slug decode - | slug encode -
  WLjW7XpJQ5ePycx6zWF8mw
  dEOJgGpARrWBm9HX9MPBSA
  fBIwjdHdRyGIk5WITyqxqA
  bYuEpq-SQSaZimBDmTe4Kg
  LLY3KZ05QWm0cBS4rfdTaQ

RNG Characteristics

UUID generation is performed by the github.com/pborman/uuid library which in turn uses the crypto/rand standard library for generating entropy. This library declares:

Reader is a global, shared instance of a cryptographically strong pseudo-random generator.

On Unix-like systems, Reader reads from /dev/urandom. On Linux, Reader uses getrandom(2) if available, /dev/urandom otherwise. On Windows systems, Reader uses the CryptGenRandom API.

The slugid library inherits these RNG characteristics.

License

The slugid library is released on the MPL 2.0 license, see file LICENSE for the complete license.

Testing

go test ./...
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].