Class: SimpleStructuredSecrets
- Inherits:
-
Object
- Object
- SimpleStructuredSecrets
- Includes:
- Base62
- Defined in:
- lib/sssecrets.rb
Overview
Simple Structured Secrets aims to implement GitHub’s authentication token format as faithfully as possible. You can learn more about the design and properties of these tokens at the following link: github.blog/2021-04-05-behind-githubs-new-authentication-token-formats/
Defined Under Namespace
Classes: Error
Constant Summary
Constants included from Base62
Base62::BASE, Base62::KEYS, Base62::KEYS_HASH
Instance Attribute Summary collapse
-
#org ⇒ Object
Returns the value of attribute org.
-
#type ⇒ Object
Returns the value of attribute type.
Instance Method Summary collapse
-
#calc_checksum(secret) ⇒ Object
Calculate the base62-encoded CRC32 checksum for a given input string.
-
#generate ⇒ Object
Generate a Simple Structured Secret token.
-
#generate_header(str) ⇒ Object
Append a Simple Structured Secret header to a provided string.
-
#initialize(org, type) ⇒ SimpleStructuredSecrets
constructor
A new instance of SimpleStructuredSecrets.
-
#validate(secret) ⇒ Object
Validate a given Simple Structured Secret token.
-
#validate_header(str) ⇒ Object
Validate a Simple Structured Secret header for a given string.
Methods included from Base62
#base62_decode, #base62_encode
Constructor Details
#initialize(org, type) ⇒ SimpleStructuredSecrets
Returns a new instance of SimpleStructuredSecrets.
53 54 55 56 57 58 |
# File 'lib/sssecrets.rb', line 53 def initialize(org, type) raise "Prefix is too long." if org.length + type.length > 10 @org = org @type = type end |
Instance Attribute Details
#org ⇒ Object
Returns the value of attribute org.
51 52 53 |
# File 'lib/sssecrets.rb', line 51 def org @org end |
#type ⇒ Object
Returns the value of attribute type.
51 52 53 |
# File 'lib/sssecrets.rb', line 51 def type @type end |
Instance Method Details
#calc_checksum(secret) ⇒ Object
Calculate the base62-encoded CRC32 checksum for a given input string. When necessary, this value will be left-padded with 0 to ensure it’s always 6 characters long.
Example:
>> SimpleStructuredSecrets.calc_checksum("GUkLdIZV8xnQQZobkuynSyyPkcweVm")
=> "14nosQ"
Arguments:
secret: (String)
80 81 82 |
# File 'lib/sssecrets.rb', line 80 def calc_checksum(secret) base62_encode(Zlib.crc32(secret)).ljust(6, "0") end |
#generate ⇒ Object
Generate a Simple Structured Secret token.
Example:
>> SimpleStructuredSecret.generate
=> "tk_GUkLdIZV8xnQQZobkuynSyyPkcweVm14nosQ"
65 66 67 68 |
# File 'lib/sssecrets.rb', line 65 def generate random = base62_encode(SecureRandom.rand(10**60)).to_s[0...30] "#{@org}#{@type}_#{random}#{calc_checksum(random)}" end |
#generate_header(str) ⇒ Object
Append a Simple Structured Secret header to a provided string. This is useful in cases where you’d like to realize the secret scanning benefits of SSS with other token formats.
Example:
>> SimpleStructuredSecrets.generate_header("5be426ee126b88f9587bbbe767a7592c")
=> "tk_1e6YXE_5be426ee126b88f9587bbbe767a7592c"
Arguments:
str: (String)
110 111 112 |
# File 'lib/sssecrets.rb', line 110 def generate_header(str) "#{@org}#{@type}_#{calc_checksum(str)}_#{str}" end |
#validate(secret) ⇒ Object
Validate a given Simple Structured Secret token. Note that this only indicates whether a given token is in the correct form and has a valid checksum. You will still need to implement your own logic for checking the validity of tokens you’ve issued.
Example:
>> SimpleStructuredSecrets.validate("tk_GUkLdIZV8xnQQZobkuynSyyPkcweVm14nosQ")
=> true
Arguments:
secret: (String)
95 96 97 98 |
# File 'lib/sssecrets.rb', line 95 def validate(secret) random = /(?<=_)[A-Za-z0-9]{30}/.match(secret).to_s calc_checksum(random) == secret.chars.last(6).join end |
#validate_header(str) ⇒ Object
Validate a Simple Structured Secret header for a given string.
Example:
>> SimpleStructuredSecrets.validate_header("tk_1e6YXE_5be426ee126b88f9587bbbe767a7592c")
=> true
Arguments:
str: (String)
122 123 124 125 |
# File 'lib/sssecrets.rb', line 122 def validate_header(str) matches = /(?<prefix>.*)_(?<checksum>[A-Za-z0-9]{6})_(?<string>.*)/.match(str) calc_checksum(matches["string"]) == matches["checksum"] end |