Last active
February 27, 2024 21:12
-
-
Save narze/985712e46d33be3613e395388b549c2d to your computer and use it in GitHub Desktop.
Cuid2 implementation in Ruby, converted from cuid2.js via ChatGPT 4 with modified fingerprint creation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "digest" | |
# Cuid2 in Ruby, converted from cuid2.js via ChatGPT 4 | |
# https://github.com/paralleldrive/cuid2/blob/main/src/index.js | |
# Example usage | |
# cuid_instance = Cuid2.new | |
# puts cuid_instance.generate | |
# cuid_singleton = Cuid2.generate | |
# puts cuid_singleton | |
class Cuid2 | |
DEFAULT_LENGTH = 24 | |
BIG_LENGTH = 32 | |
def initialize(length = DEFAULT_LENGTH, fingerprint_string = "") | |
@counter = self.class.create_counter | |
@fingerprint = self.class.create_fingerprint(fingerprint_string) | |
@length = length | |
end | |
def generate | |
first_letter = SecureRandom.rand(97..122).chr | |
time = (Time.now.to_f * 1000).to_i.to_s(36) | |
count = @counter.call.to_s(36) | |
salt = self.class.create_entropy(@length) | |
hash_input = "#{time}#{salt}#{count}#{@fingerprint}" | |
"#{first_letter}#{self.class.hash(hash_input)[1, @length - 1]}" | |
end | |
alias_method :call, :generate | |
# Singleton generate method | |
def self.generate | |
new.generate | |
end | |
# Create entropy | |
def self.create_entropy(length = 4) | |
entropy = "" | |
while entropy.length < length | |
entropy += SecureRandom.rand(36).to_s(36) | |
end | |
entropy | |
end | |
# Hash function using Digest::SHA512 | |
def self.hash(input = "") | |
Digest::SHA512.hexdigest(input).to_i(16).to_s(36)[1..] | |
end | |
# Create fingerprint of the host environment | |
def self.create_fingerprint(fingerprint_string = "") | |
constants_string = Object.constants.map(&:to_s).join(",") | |
hostname = defined?(Socket) ? Socket.gethostname : "" | |
pid = defined?(Process) ? Process.pid.to_s : "" | |
source_string = "#{fingerprint_string}#{hostname}#{pid}#{constants_string}#{create_entropy(BIG_LENGTH)}" | |
hash(source_string)[1..BIG_LENGTH] | |
end | |
# Counter function | |
def self.create_counter | |
count = SecureRandom.rand(476782367) | |
proc { count += 1 } | |
end | |
# Check if a string is a valid CUID | |
def self.is_cuid?(id, min_length: 2, max_length: BIG_LENGTH) | |
regex = /^[a-z][0-9a-z]+$/ | |
id.is_a?(String) && id.length.between?(min_length, max_length) && regex.match?(id) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment