Skip to content
This repository was archived by the owner on Apr 22, 2025. It is now read-only.

Commit 45509bb

Browse files
committed
feat: Add SecureRAndom.base58/1
Based originally on patricksrobertson#12, but modified to prevent namespace pollution of the Base58 translation module.
1 parent 0fd109a commit 45509bb

File tree

3 files changed

+106
-0
lines changed

3 files changed

+106
-0
lines changed

lib/secure_random.ex

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,25 @@ defmodule SecureRandom do
103103
:crypto.strong_rand_bytes(n)
104104
end
105105

106+
@doc """
107+
Returns random Base58 encoded string.
108+
109+
## Examples
110+
111+
iex> SecureRandom.base58
112+
"Y5oZt858wSQbnGrxAZTyrY"
113+
114+
iex> SecureRandom.base58(8)
115+
"4xxSsC4PKq5"
116+
117+
"""
118+
def base58(n \\ @default_length) do
119+
n
120+
|> random_bytes()
121+
|> :binary.bin_to_list()
122+
|> charlist_to_base58()
123+
end
124+
106125
defp bigenerate do
107126
<<u0::48, _::4, u1::12, _::2, u2::62>> = random_bytes(16)
108127
<<u0::48, 4::4, u1::12, 2::2, u2::62>>
@@ -128,4 +147,17 @@ defmodule SecureRandom do
128147
defp lower(<<h, t::binary>>, acc) when h in ?A..?F, do: lower(t, acc <> <<h + 32>>)
129148
defp lower(<<h, t::binary>>, acc), do: lower(t, acc <> <<h>>)
130149
defp lower(<<>>, acc), do: acc
150+
151+
defp int_to_base58(x) when x >= 58,
152+
do: SecureRandom.Base58.b58char(:rand.uniform(57))
153+
154+
defp int_to_base58(x),
155+
do: SecureRandom.Base58.b58char(x)
156+
157+
defp charlist_to_base58(chars) do
158+
chars
159+
|> Enum.map(&rem(&1, 64))
160+
|> Enum.map(&int_to_base58(&1))
161+
|> List.to_string()
162+
end
131163
end

lib/secure_random/base58.ex

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
defmodule SecureRandom.Base58 do
2+
@moduledoc false
3+
4+
def b58char(0), do: ?1
5+
def b58char(1), do: ?2
6+
def b58char(2), do: ?3
7+
def b58char(3), do: ?4
8+
def b58char(4), do: ?5
9+
def b58char(5), do: ?6
10+
def b58char(6), do: ?7
11+
def b58char(7), do: ?8
12+
def b58char(8), do: ?9
13+
def b58char(9), do: ?A
14+
def b58char(10), do: ?B
15+
def b58char(11), do: ?C
16+
def b58char(12), do: ?D
17+
def b58char(13), do: ?E
18+
def b58char(14), do: ?F
19+
def b58char(15), do: ?G
20+
def b58char(16), do: ?H
21+
def b58char(17), do: ?J
22+
def b58char(18), do: ?K
23+
def b58char(19), do: ?L
24+
def b58char(20), do: ?M
25+
def b58char(21), do: ?N
26+
def b58char(22), do: ?P
27+
def b58char(23), do: ?Q
28+
def b58char(24), do: ?R
29+
def b58char(25), do: ?S
30+
def b58char(26), do: ?T
31+
def b58char(27), do: ?U
32+
def b58char(28), do: ?V
33+
def b58char(29), do: ?W
34+
def b58char(30), do: ?X
35+
def b58char(31), do: ?Y
36+
def b58char(32), do: ?Z
37+
def b58char(33), do: ?a
38+
def b58char(34), do: ?b
39+
def b58char(35), do: ?c
40+
def b58char(36), do: ?d
41+
def b58char(37), do: ?e
42+
def b58char(38), do: ?f
43+
def b58char(39), do: ?g
44+
def b58char(40), do: ?h
45+
def b58char(41), do: ?i
46+
def b58char(42), do: ?j
47+
def b58char(43), do: ?k
48+
def b58char(44), do: ?m
49+
def b58char(45), do: ?n
50+
def b58char(46), do: ?o
51+
def b58char(47), do: ?p
52+
def b58char(48), do: ?q
53+
def b58char(49), do: ?r
54+
def b58char(50), do: ?s
55+
def b58char(51), do: ?t
56+
def b58char(52), do: ?u
57+
def b58char(53), do: ?v
58+
def b58char(54), do: ?w
59+
def b58char(55), do: ?x
60+
def b58char(56), do: ?y
61+
def b58char(57), do: ?z
62+
end

test/secure_random_test.exs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,16 @@ defmodule SecureRandomTest do
4343
# that standard is 128 bit string 4byte-2byte-2byte-2byte-6byte
4444
assert Regex.match?(~r/\A\w{8}-\w{4}-4\w{3}-(8|9|a|b)\w{3}-\w{12}\z/, SecureRandom.uuid())
4545
end
46+
47+
test "base58/1 returns a Binary string" do
48+
assert is_binary(SecureRandom.base58())
49+
end
50+
51+
test "base58/1 defaults to a byte size of 16" do
52+
assert 16 == byte_size(SecureRandom.base58())
53+
end
54+
55+
test "base58/1 successfully takes a byte_length" do
56+
assert 24 == byte_size(SecureRandom.base58(24))
57+
end
4658
end

0 commit comments

Comments
 (0)