Base58Check encoding: Difference between revisions
→{{header|RPL}}: improved processing of large binary integers
(Added Seed7 example) |
(→{{header|RPL}}: improved processing of large binary integers) |
||
(27 intermediate revisions by 17 users not shown) | |||
Line 1:
[[Category:Encodings]]
[[Category:Checksums]]
{{draft task}}
The popular encoding of small and medium-sized [[:Category:Checksums|checksums]] is [[wp:base16|base16]], that is more compact than usual base10 and is human readable... For checksums resulting in ''hash digests'' bigger than ~100 bits, the base16 is too long: [[wp:base58|base58]] is shorter and (when using good alphabet) preserves secure human readability. The most popular alphabet of base58 is the variant used in bitcoin address (see [[Bitcoin/address validation]]), so it is the "default base58 alphabet".
Line 15:
<br><br>
=={{header|
{{trans|Python}}
<syntaxhighlight lang="11l">V ALPHABET = ‘123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz’
F convertToBase58(=num)
V sb = ‘’
L num > 0
V r = Int(num % 58)
sb = sb‘’:ALPHABET[r]
num = num I/ 58
R reversed(sb)
V s = BigInt(‘25420294593250030202636073700053352635053786165627414518’)
V b = convertToBase58(s)
print(‘#. -> #.’.format(s, b))
V hash_arr = [‘61’, ‘626262’, ‘636363’, ‘73696d706c792061206c6f6e6720737472696e67’, ‘516b6fcd0f’, ‘bf4f89001e670274dd’, ‘572e4794’, ‘ecac89cad93923c02321’, ‘10c8511e’]
L(num) hash_arr
b = convertToBase58(BigInt(num, radix' 16))
print(‘0x#<54 -> #.’.format(num, b))</syntaxhighlight>
{{out}}
<pre>
25420294593250030202636073700053352635053786165627414518 -> 6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM
0x61 -> 2g
0x626262 -> a3gV
0x636363 -> aPEr
0x73696d706c792061206c6f6e6720737472696e67 -> 2cFupjhnEsSn59qHXstmK2ffpLv2
0x516b6fcd0f -> ABnLTmg
0xbf4f89001e670274dd -> 3SEo3LWLoPntC
0x572e4794 -> 3EFU7m
0xecac89cad93923c02321 -> EJDM8drfXA6uyA
0x10c8511e -> Rt5zm
</pre>
=={{header|C sharp|C#}}==
{{trans|Java}}
<
using System.Collections.Generic;
using System.Numerics;
Line 87 ⟶ 123:
}
}
}</
{{out}}
<pre>25420294593250030202636073700053352635053786165627414518 -> 6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM
Line 99 ⟶ 135:
0xecac89cad93923c02321 -> EJDM8drfXA6uyA
0x10c8511e -> Rt5zm</pre>
=={{header|D}}==
<syntaxhighlight lang="d">import std.bigint;
import std.stdio;
void main() {
report("25420294593250030202636073700053352635053786165627414518");
report(0x61);
report(0x626262);
report(0x636363);
report("0x73696d706c792061206c6f6e6720737472696e67");
report(0x516b6fcd0f);
report("0xbf4f89001e670274dd");
report(0x572e4794);
report("0xecac89cad93923c02321");
report(0x10c8511e);
}
void report(T)(T v) {
import std.traits;
static if (isIntegral!T) {
enum format = "%#56x -> %s";
} else {
enum format = "%56s -> %s";
}
writefln(format, v, v.toBase58);
}
string toBase58(T)(T input) {
import std.traits;
static if (isSomeString!T) {
return toBase58(BigInt(input));
} else {
import std.algorithm.mutation : reverse;
import std.array : appender;
enum ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
auto sb = appender!(char[]);
size_t mod;
do {
mod = cast(size_t) (input % ALPHABET.length);
sb.put(ALPHABET[mod]);
input /= ALPHABET.length;
} while (input);
sb.data.reverse;
return sb.data.idup;
}
}</syntaxhighlight>
{{out}}
<pre>25420294593250030202636073700053352635053786165627414518 -> 6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM
0x61 -> 2g
0x626262 -> a3gV
0x636363 -> aPEr
0x73696d706c792061206c6f6e6720737472696e67 -> 2cFupjhnEsSn59qHXstmK2ffpLv2
0x516b6fcd0f -> ABnLTmg
0xbf4f89001e670274dd -> 3SEo3LWLoPntC
0x572e4794 -> 3EFU7m
0xecac89cad93923c02321 -> EJDM8drfXA6uyA
0x10c8511e -> Rt5zm</pre>
=={{header|FreeBASIC}}==
{{libheader|GMP}}
<
' compile with: fbc -s console
' uses GMP
Line 161 ⟶ 259:
Print : Print "hit any key to end program"
Sleep
End</
{{out}}
<pre>OkobppXBkab(58) --> RosettaCode
Line 175 ⟶ 273:
0xecac89cad93923c02321 --> EJDM8drfXA6uyA
0x10c8511e --> Rt5zm</pre>
=={{header|Go}}==
{{trans|Kotlin}}
<
import (
Line 302 ⟶ 338:
fmt.Printf("%-56s -> %s\n", hash, b58)
}
}</
{{out}}
Line 317 ⟶ 353:
0x10c8511e -> Rt5zm
</pre>
=={{header|Groovy}}==
{{trans|Java}}
<syntaxhighlight lang="groovy">class Base58CheckEncoding {
private static final String ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
private static final BigInteger BIG0 = BigInteger.ZERO
private static final BigInteger BIG58 = BigInteger.valueOf(58)
private static String convertToBase58(String hash) {
return convertToBase58(hash, 16)
}
private static String convertToBase58(String hash, int base) {
BigInteger x
if (base == 16 && hash.substring(0, 2) == "0x") {
x = new BigInteger(hash.substring(2), 16)
} else {
x = new BigInteger(hash, base)
}
StringBuilder sb = new StringBuilder()
while (x > BIG0) {
int r = (x % BIG58).intValue()
sb.append(ALPHABET.charAt(r))
x = x.divide(BIG58)
}
return sb.reverse().toString()
}
static void main(String[] args) {
String s = "25420294593250030202636073700053352635053786165627414518"
String b = convertToBase58(s, 10)
System.out.printf("%s -> %s\n", s, b)
List<String> hashes = new ArrayList<>()
hashes.add("0x61")
hashes.add("0x626262")
hashes.add("0x636363")
hashes.add("0x73696d706c792061206c6f6e6720737472696e67")
hashes.add("0x516b6fcd0f")
hashes.add("0xbf4f89001e670274dd")
hashes.add("0x572e4794")
hashes.add("0xecac89cad93923c02321")
hashes.add("0x10c8511e")
for (String hash : hashes) {
String b58 = convertToBase58(hash)
System.out.printf("%-56s -> %s\n", hash, b58)
}
}
}</syntaxhighlight>
{{out}}
<pre>25420294593250030202636073700053352635053786165627414518 -> 6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM
0x61 -> 2g
0x626262 -> a3gV
0x636363 -> aPEr
0x73696d706c792061206c6f6e6720737472696e67 -> 2cFupjhnEsSn59qHXstmK2ffpLv2
0x516b6fcd0f -> ABnLTmg
0xbf4f89001e670274dd -> 3SEo3LWLoPntC
0x572e4794 -> 3EFU7m
0xecac89cad93923c02321 -> EJDM8drfXA6uyA
0x10c8511e -> Rt5zm</pre>
=={{header|Haskell}}==
<
chars = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
Line 337 ⟶ 436:
0x572e4794,
0xecac89cad93923c02321,
0x10c8511e]</
{{out}}
<pre>
Line 354 ⟶ 453:
and for bulk encoding, Array access would be one of various slightly faster alternatives to recursive subscripting of linked lists:
{{Trans|Python}}
<
import Numeric (showHex, showIntAtBase)
------------------- BASE58CHECK ENCODING -----------------
base58Encode ::
(Integral a, Show a) =>
a ->
String
base58Encode =
baseEncode $
listArray (0, 57) $
('A', 'H'),
('J', 'N'),
('P', 'Z'),
('a', 'k'),
('m', 'z')
]
>>= uncurry enumFromTo
baseEncode ::
a ->
String
baseEncode cs n =
showIntAtBase
(fromIntegral $ length cs)
(cs !)
n
[]
-
main :: IO ()
main =
putStrLn $
fTable
"Base 58 encoding:\n"
((
base58Encode
id
[ 25420294593250030202636073700053352635053786165627414518,
]
-
fTable ::
String ->
(a -> String) ->
(b -> String) ->
(a -> b) ->
[a] ->
String
fTable s xShow fxShow f xs =
let w = maximum $ fmap length (xShow <$> xs)
rjust n c
in unlines $
s :
fmap
( ((<>) . rjust w ' ' . xShow)
<*> ((" -> " <>) . fxShow . f)
)
xs</syntaxhighlight>
{{Out}}
<pre>Base 58 encoding:
Line 416 ⟶ 542:
{{trans|Kotlin}}
{{works with|Java|9}}
<
import java.util.List;
Line 467 ⟶ 593:
}
}
}</
{{out}}
<pre>25420294593250030202636073700053352635053786165627414518 -> 6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM
Line 479 ⟶ 605:
0xecac89cad93923c02321 -> EJDM8drfXA6uyA
0x10c8511e -> Rt5zm</pre>
=={{header|jq}}==
'''Works with gojq, the Go implementation of jq'''
WARNING: The program will also run using the C implementation of jq but the results for the very
large values will be inaccurate.
'''Generic utility functions'''
<syntaxhighlight lang=jq>
def lpad($len): tostring | ($len - length) as $l | (" " * $l)[:$l] + .;
# Input: a string in base $b (2 to 35 inclusive)
# Output: the decimal value
def frombase($b):
def decimalValue:
if 48 <= . and . <= 57 then . - 48
elif 65 <= . and . <= 90 then . - 55 # (10+.-65)
elif 97 <= . and . <= 122 then . - 87 # (10+.-97)
else "decimalValue" | error
end;
reduce (explode|reverse[]|decimalValue) as $x ({p:1};
.value += (.p * $x)
| .p *= $b)
| .value ;
</syntaxhighlight>
'''Base58Check'''
<syntaxhighlight lang=jq>
# The base58check alphabet, i.e. 0 => "1", etc
def alphabet: "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
# input: a string in the specified $base
def convertToBase58($base):
. as $hash
| {x: (if $base == 16 and ($hash|startswith("0x"))
then $hash[2:]|frombase(16)
else $hash|frombase($base)
end),
sb: [] }
| until (.x <= 0;
(.x % 58) as $r
| .sb += [alphabet[$r:$r+1]]
| .x |= (. - $r) / 58 )
| .sb | reverse | join("");
def hashes: [
"0x61",
"0x626262",
"0x636363",
"0x73696d706c792061206c6f6e6720737472696e67",
"0x516b6fcd0f",
"0xbf4f89001e670274dd",
"0x572e4794",
"0xecac89cad93923c02321",
"0x10c8511e"
];
def task:
def s: "25420294593250030202636073700053352635053786165627414518";
(s | "\(lpad(58))-> \(convertToBase58(10))" ),
(hashes[]
| [lpad(58), convertToBase58(16)] | join("-> ") ) ;
task
</syntaxhighlight>
{{output}}
<pre>
25420294593250030202636073700053352635053786165627414518-> 6UwLL9RisZVooooooooooooooooooooo
0x61-> 2g
0x626262-> a3gV
0x636363-> aPEr
0x73696d706c792061206c6f6e6720737472696e67-> 2cFupjhnEuPooooooooooooooooo
0x516b6fcd0f-> ABnLTmg
0xbf4f89001e670274dd-> 3SEo3LWLoMXoo
0x572e4794-> 3EFU7m
0xecac89cad93923c02321-> EJDM8drfX5mooo
0x10c8511e-> Rt5zm
</pre>
=={{header|Julia}}==
{{works with|Julia|0.6}}
<
function encodebase58(hsh::AbstractString, base::Integer=16)
Line 502 ⟶ 706:
"0x10c8511e"]
println("# $s\n -> ", encodebase58(s))
end</
{{out}}
Line 527 ⟶ 731:
=={{header|Kotlin}}==
<
import java.math.BigInteger
Line 566 ⟶ 770:
println("${hash.padEnd(56)} -> $b58")
}
}</
{{out}}
Line 581 ⟶ 785:
0x10c8511e -> Rt5zm
</pre>
=={{header|Nim}}==
{{libheader|bignum}}
This version takes in account the leading zeroes in hexadecimal representation. It accepts also arrays or sequences of bytes as input, taking in account the leading zero bytes as described in https://en.bitcoin.it/wiki/Base58Check_encoding#Base58_symbol_chart
<syntaxhighlight lang="nim">import sequtils, strutils
import bignum
const CodeString = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
proc toBase58*(hashValue: string): string =
## Convert a hash value provided as a string to its base 58 representation.
# Build a big integer from the string.
var hexval = ""
var val: Int
if hashValue.startsWith("0x"):
hexval = hashValue[2..^1]
val = newInt(hexval, 16)
else:
val = newInt(hashValue, 10)
# Convert to base 58.
while val > 0:
result.add CodeString[(val mod 58).toInt]
val = val div 58
# Add codes for leading zeroes.
for c in hexval:
if c == '0': result.add '1'
else: break
# Reverse string.
let h = result.high
for i in 0..(h div 2):
swap result[i], result[h - i]
proc toBase58*(hashValue: openArray[byte]): string =
## Convert an array or sequence of bytes to base 58.
toBase58("0x" & hashValue.join().toHex)
when isMainModule:
const Hashes = ["0x00010966776006953D5567439E5E39F86A0D273BEED61967F6",
"0x61",
"0x626262",
"0x636363",
"0x73696d706c792061206c6f6e6720737472696e67",
"0x516b6fcd0f",
"0xbf4f89001e670274dd",
"0x572e4794",
"0xecac89cad93923c02321",
"0x10c8511e"]
const MaxLength = max(Hashes.mapIt(it.len))
for h in Hashes:
echo h.alignLeft(MaxLength), " → ", h.toBase58</syntaxhighlight>
{{out}}
<pre>0x00010966776006953D5567439E5E39F86A0D273BEED61967F6 → 1116UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM
0x61 → 2g
0x626262 → a3gV
0x636363 → aPEr
0x73696d706c792061206c6f6e6720737472696e67 → 2cFupjhnEsSn59qHXstmK2ffpLv2
0x516b6fcd0f → ABnLTmg
0xbf4f89001e670274dd → 3SEo3LWLoPntC
0x572e4794 → 3EFU7m
0xecac89cad93923c02321 → EJDM8drfXA6uyA
0x10c8511e → Rt5zm</pre>
=={{header|Perl}}==
<
sub encode_base58 {
Line 615 ⟶ 891:
0xecac89cad93923c02321
0x10c8511e
);</
{{out}}
<pre>25420294593250030202636073700053352635053786165627414518 -> 6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM
Line 627 ⟶ 903:
0xecac89cad93923c02321 -> EJDM8drfXA6uyA
0x10c8511e -> Rt5zm</pre>
=={{header|Phix}}==
Slight variation from [[Bitcoin/public_point_to_address#Phix]] in that it accepts any length string (which can be binary or text).<br>
Includes leading zeroes, if you don't want that just comment out the three lines defining/using the integer lz.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">b58</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">base58</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">out</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">lz</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">trim_head</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\0'</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">out</span><span style="color: #0000FF;">=</span><span style="color: #008000;">""</span> <span style="color: #008080;">then</span> <span style="color: #000000;">lz</span> <span style="color: #0000FF;">-=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">*</span><span style="color: #000000;">256</span><span style="color: #0000FF;">+</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">/</span><span style="color: #000000;">58</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">58</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">out</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">b58</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #000000;">out</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'1'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lz</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">reverse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">out</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">base58</span><span style="color: #0000FF;">(</span><span style="color: #008000;">x"00010966776006953D5567439E5E39F86A0D273BEED61967F6"</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">base58</span><span style="color: #0000FF;">(</span><span style="color: #008000;">x"61"</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- == base58("a")</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">base58</span><span style="color: #0000FF;">(</span><span style="color: #008000;">x"626262"</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- == base58("bbb")</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">base58</span><span style="color: #0000FF;">(</span><span style="color: #008000;">x"636363"</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- == base58("ccc")</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">base58</span><span style="color: #0000FF;">(</span><span style="color: #008000;">x"73696d706c792061206c6f6e6720737472696e67"</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- ^ == base58("simply a long string")</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">base58</span><span style="color: #0000FF;">(</span><span style="color: #008000;">x"516b6fcd0f"</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">base58</span><span style="color: #0000FF;">(</span><span style="color: #008000;">x"bf4f89001e670274dd"</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">base58</span><span style="color: #0000FF;">(</span><span style="color: #008000;">x"572e4794"</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">base58</span><span style="color: #0000FF;">(</span><span style="color: #008000;">x"ecac89cad93923c02321"</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">base58</span><span style="color: #0000FF;">(</span><span style="color: #008000;">x"10c8511e"</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 704 ⟶ 954:
"EJDM8drfXA6uyA"
"Rt5zm"
</pre>
=={{header|Picat}}==
<syntaxhighlight lang="picat">main =>
Tests = [[25420294593250030202636073700053352635053786165627414518,"6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM"],
["0x61","2g"],
["0x626262", "a3gV"],
["0x636363", "aPEr"],
["0x73696d706c792061206c6f6e6720737472696e67", "2cFupjhnEsSn59qHXstmK2ffpLv2"],
["0x516b6fcd0f", "ABnLTmg"],
["0xbf4f89001e670274dd", "3SEo3LWLoPntC"],
["0x572e4794", "3EFU7m"],
["0xecac89cad93923c02321", "EJDM8drfXA6uyA"],
["0x10c8511e", "Rt5zm"]],
foreach([Test,Check] in Tests)
Res = base58Check(Test),
printf("%-56w -> %w (%s)\n", Test, Res, cond(Res==Check,"ok", "not ok"))
end,
nl.
base58Check(Hash) = Out.reverse =>
CodeS = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",
(string(Hash) -> X = Hash.to_int ; X = Hash),
Out = "",
while (X > 0)
Rem = X mod 58,
X := X // 58,
Out := Out ++ [CodeS[Rem+1]]
end.</syntaxhighlight>
{{out}}
<pre>25420294593250030202636073700053352635053786165627414518 -> 6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM (ok)
0x61 -> 2g (ok)
0x626262 -> a3gV (ok)
0x636363 -> aPEr (ok)
0x73696d706c792061206c6f6e6720737472696e67 -> 2cFupjhnEsSn59qHXstmK2ffpLv2 (ok)
0x516b6fcd0f -> ABnLTmg (ok)
0xbf4f89001e670274dd -> 3SEo3LWLoPntC (ok)
0x572e4794 -> 3EFU7m (ok)
0xecac89cad93923c02321 -> EJDM8drfXA6uyA (ok)
0x10c8511e -> Rt5zm (ok)</pre>
=={{header|PicoLisp}}==
<syntaxhighlight lang="picolisp">(setq *B58Alpha
(chop "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz") )
(de b58 (S)
(let N 0
(pack
(make
(if (pre? "0x" S)
(setq N (hex (cddr (chop S))))
(setq N (format S)) )
(while (gt0 N)
(yoke (get *B58Alpha (inc (% N 58))))
(setq N (/ N 58)) ) ) ) ) )
(println (b58 "25420294593250030202636073700053352635053786165627414518"))
(println (b58 "0x626262"))
(println (b58 "0x636363"))</syntaxhighlight>
{{out}}
<pre>
"6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM"
"a3gV"
"aPEr"
</pre>
=={{header|Python}}==
===Procedural===
===Works with Python 3.9
{{trans|C#}}
<
def convertToBase58(num):
Line 716 ⟶ 1,031:
r = num % 58
sb = sb + ALPHABET[r]
num = num // 58;
return sb[::-1]
s = 25420294593250030202636073700053352635053786165627414518
b = convertToBase58(s)
print
hash_arr = [0x61, 0x626262, 0x636363, 0x73696d706c792061206c6f6e6720737472696e67, 0x516b6fcd0f, 0xbf4f89001e670274dd, 0x572e4794, 0xecac89cad93923c02321, 0x10c8511e]
for num in hash_arr:
b = convertToBase58(num)
print
{{out}}
<pre>25420294593250030202636073700053352635053786165627414518 -> 6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM
Line 741 ⟶ 1,056:
===Composition of pure functions===
{{Works with|Python|3.7}}
<
from functools import reduce
Line 901 ⟶ 1,216:
# MAIN ---
if __name__ == '__main__':
main()</
{{Out}}
<pre>Base 58 check encoding:
Line 915 ⟶ 1,230:
0xecac89cad93923c02321 -> EJDM8drfXA6uyA
0x10c8511e -> Rt5zm</pre>
=={{header|Quackery}}==
<syntaxhighlight lang="quackery"> [ table ] is base58char ( n --> n )
$ "123456789ABCDEFGHJKLMNPQRSTUV"
$ "WXYZabcdefghijkmnopqrstuvwxyz"
join witheach
[ ' base58char put ]
[ [] swap
[ 58 /mod base58char
rot join swap
dup 0 = until ]
drop ] is base58$ ( n --> $ )
' [ 25420294593250030202636073700053352635053786165627414518
hex 61
hex 626262
hex 636363
hex 73696d706c792061206c6f6e6720737472696e67
hex 516b6fcd0f
hex bf4f89001e670274dd
hex 572e4794
hex ecac89cad93923c02321
hex 10c8511e ]
witheach [ base58$ echo$ cr ]
</syntaxhighlight>
{{out}}
<pre>6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM
2g
a3gV
aPEr
2cFupjhnEsSn59qHXstmK2ffpLv2
ABnLTmg
3SEo3LWLoPntC
3EFU7m
EJDM8drfXA6uyA
Rt5zm
</pre>
=={{header|Racket}}==
(Examples from some other task)
<
(define ((base-n-alphabet-encode alphabet) hash-string (in-base 16))
Line 944 ⟶ 1,304:
"0x572e4794"
"0xecac89cad93923c02321"
"0x10c8511e")))</
{{out}}
<pre>"6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM"
'("2g" "a3gV" "aPEr" "2cFupjhnEsSn59qHXstmK2ffpLv2" "ABnLTmg" "3SEo3LWLoPntC" "3EFU7m" "EJDM8drfXA6uyA" "Rt5zm")</pre>
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku" line>sub encode_Base58 ( Int $x ) {
constant @codes = <
1 2 3 4 5 6 7 8 9
A B C D E F G H J K L M N P Q R S T U V W X Y Z
a b c d e f g h i j k m n o p q r s t u v w x y z
>;
return @codes[ $x.polymod( 58 xx * ) ].join.flip;
}
my @tests =
25420294593250030202636073700053352635053786165627414518 => '6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM',
0x61 => '2g',
0x626262 => 'a3gV',
0x636363 => 'aPEr',
0x73696d706c792061206c6f6e6720737472696e67 => '2cFupjhnEsSn59qHXstmK2ffpLv2',
0x516b6fcd0f => 'ABnLTmg',
0xbf4f89001e670274dd => '3SEo3LWLoPntC',
0x572e4794 => '3EFU7m',
0xecac89cad93923c02321 => 'EJDM8drfXA6uyA',
0x10c8511e => 'Rt5zm',
;
use Test;
for @tests {
is encode_Base58(.key), .value, "{.key} encodes to {.value}";
}
</syntaxhighlight>
=={{header|REXX}}==
Line 955 ⟶ 1,345:
I get the result expected there.
Apart for the leading 1 the program works also for the inputs shown above.
<
s="123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
Numeric Digits 100
Line 967 ⟶ 1,357:
End
o=o||substr(s,1,1)
Say reverse(o)</
{{out}}
<pre>16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM</pre>
===version 2===
does what the others do
<
s="123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
Numeric Digits 1000
Line 1,007 ⟶ 1,397:
Say 'found :' o
End
Return</
{{out}}
<pre>expected: check_error_handlimng
Line 1,019 ⟶ 1,409:
The algorithm used doesn't need to ''reverse'' the residual string (it uses ''prepend'' instead of ''append'').
<
/* 0─────────────────I─────O────────────────────l──────────────── ◄───omit.*/
@= space(" 123456789ABCDEFGH JKLMN PQRSTUVWXYZabcdefghi jkmnopqrstuvwxyz", 0)
numeric digits 500 /*just in case there're huge numberss. */
say B58(25420294593250030202636073700053352635053786165627414518)
say B58('61'x) ; say B58('626262'x)
say B58('636363'x) ; say B58('73696d706c792061206c6f6e6720737472696e67'x)
say B58('572e4794'x) ; say B58('ecac89cad93923c02321'x)
exit 0 /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
B58: parse arg z 1 oz,,$;
if \datatype(z
if
do until z==0; $= substr(@, z//58 +1, 1)$; z= z % 58
end /*until*/
if
</syntaxhighlight>
{{out|output|text= when using the default inputs:}}
<pre>
25420294593250030202636073700053352635053786165627414518 ───► 6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM
Line 1,056 ⟶ 1,442:
'ECAC89CAD93923C02321'x ───► 000EJDM8drfXA6uyA
'10C8511E'x ───► Rt5zm
</pre>
=={{header|RPL}}==
Binary numbers cannot exceed 64 bits in RPL.
{{works with|HP|48G}}
« "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" → alphabet
« "" 1
'''IF''' 3 PICK TYPE 10 == '''THEN''' SF '''ELSE''' CF '''END'''
'''WHILE''' SWAP #0 DUP2 + ≠ '''REPEAT'''
58
'''IF''' 1 FS? '''THEN''' / LASTARG 3 PICK * - B→R SWAP
'''ELSE''' MOD LASTARG / IP '''END'''
alphabet ROT 1 + DUP SUB
ROT +
'''END''' DROP
» » '<span style="color:blue">→B58</span>' STO <span style="color:grey">''@ ( n or #n → "code" }''</span>
« { 6946892355 #61 #626262 #636363 #516B6FCD0F #572E4794 #10C8511E }
1 « <span style="color:blue">→B58</span> » DOLIST
» '<span style="color:blue">TASK</span>' STO
{{out}}
<pre>
1: { "Base58" "2g" "a3gV" "aPEr" "ABnLTmg" "3EFU7m" "Rt5zm" }
</pre>
=={{header|Ruby}}==
<
nums = [25420294593250030202636073700053352635053786165627414518,
0x61,
Line 1,072 ⟶ 1,481:
puts nums.map{|n| n.digits(58).reverse.map{|i| ALPHABET[i]}.join}
</syntaxhighlight>
{{out}}
<pre>6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM
Line 1,085 ⟶ 1,494:
Rt5zm
</pre>
=={{header|Scala}}==
{{Out}}Best seen in running your browser either by [https://scalafiddle.io/sf/GMcrlBB/0 ScalaFiddle (ES aka JavaScript, non JVM)] or [https://scastie.scala-lang.org Scastie (remote JVM)].
<syntaxhighlight lang="scala">import java.math.BigInteger
object Base58 extends App {
private val codeString = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
private val (big0, big58) = (BigInt(0), BigInteger.valueOf(58))
def convertToBase58(input: String): String = convertToBase58(input, 16)
def convertToBase58(input: String, base: Int) = {
if (input.isEmpty) "" else {
val big =
if (base == 16 && input.startsWith("0x")) BigInt(input.substring(2), 16) else BigInt(input, base)
@scala.annotation.tailrec
def encode(current: BigInt, sb: StringBuilder): StringBuilder = current match {
case `big0` => sb
case _ =>
val Array(dividend, remainder: BigInteger) = current.bigInteger.divideAndRemainder(big58)
encode(dividend, sb.append(codeString(remainder.intValue)))
}
encode(big, new StringBuilder).reverse.toString
}
}
private def decode(input: String): Array[Byte] = {
val (mapping, trimmed)= (codeString.zipWithIndex.toMap, input.dropWhile(_ == '1').toList)
def zeroes: Array[Byte] = input.takeWhile(_ == '1').map(_ => 0.toByte).toArray
def decoded: BigInt = trimmed.foldLeft(big0)((a, b) => a * big58 + BigInt(mapping(b)))
if (trimmed.nonEmpty) zeroes ++ decoded.toByteArray.dropWhile(_ == 0) else zeroes
}
private def bytes2Hex(buf: Array[Byte]): String = "0x" + buf.map("%02x" format _).mkString
/*
* Running some test examples.
*/
private val veryLongNumber = "25420294593250030202636073700053352635053786165627414518"
println(f"$veryLongNumber%-56s -> ${convertToBase58(veryLongNumber, 10)}%s" )
private val hashes = List("0x61", "0x626262", "0x636363", "0x73696d706c792061206c6f6e6720737472696e67",
"0x516b6fcd0f", "0xbf4f89001e670274dd", "0x572e4794", "0xecac89cad93923c02321", "0x10c8511e")
for (hash <- hashes) {
val b58: String = convertToBase58(hash)
println(f"$hash%-56s -> $b58%-28s -> ${bytes2Hex(decode(b58))}%-56s" )
}
}</syntaxhighlight>
=={{header|Seed7}}==
Line 1,090 ⟶ 1,555:
the function [http://seed7.sourceforge.net/libraries/encoding.htm#toBase(in_bigInteger,in_string) toBase],
which encodes a number with a positional numeric system. No external library is needed.
<syntaxhighlight lang="seed7">$ include "seed7_05.s7i";
include "encoding.s7i";
Line 1,108 ⟶ 1,572:
writeln("16#" <& num radix 16 rpad 53 <& " -> " <& b);
end for;
end func;</
{{out}}
<pre>25420294593250030202636073700053352635053786165627414518 -> 6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM
16#61 -> 2g
16#626262 -> a3gV
Line 1,121 ⟶ 1,584:
16#572e4794 -> 3EFU7m
16#ecac89cad93923c02321 -> EJDM8drfXA6uyA
16#10c8511e -> Rt5zm</pre>
=={{header|Sidef}}==
{{trans|Raku}}
<syntaxhighlight lang="ruby">func encode_base58(n) {
static chars = %w(
1 2 3 4 5 6 7 8 9
A B C D E F G H J K L M N P Q R S T U V W X Y Z
a b c d e f g h i j k m n o p q r s t u v w x y z
)
[chars[n.polymod(n.ilog(58).of(58)...)]].join.flip
}
var tests = [
[25420294593250030202636073700053352635053786165627414518, "6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM"],
[97, "2g"],[6447714, "a3gV"],[6513507, "aPEr"],
[658885050385564465925592505944209249682185612903, "2cFupjhnEsSn59qHXstmK2ffpLv2"],
[349694840079, "ABnLTmg"], [3529059230209907258589, "3SEo3LWLoPntC"],
[1462650772, "3EFU7m"], [1117661258925082241147681, "EJDM8drfXA6uyA"], [281563422, "Rt5zm"]
]
for num, enc in (tests) {
printf("%56s -> %s\n", num, encode_base58(num))
assert_eq(encode_base58(num), enc)
}</syntaxhighlight>
{{out}}
<pre>
25420294593250030202636073700053352635053786165627414518 -> 6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM
97 -> 2g
6447714 -> a3gV
6513507 -> aPEr
658885050385564465925592505944209249682185612903 -> 2cFupjhnEsSn59qHXstmK2ffpLv2
349694840079 -> ABnLTmg
3529059230209907258589 -> 3SEo3LWLoPntC
1462650772 -> 3EFU7m
1117661258925082241147681 -> EJDM8drfXA6uyA
281563422 -> Rt5zm
</pre>
=={{header|Visual Basic .NET}}==
{{trans|C#}}
<
Imports System.Text
Line 1,183 ⟶ 1,682:
End Sub
End Module</
{{out}}
<pre>25420294593250030202636073700053352635053786165627414518 -> 6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM
Line 1,195 ⟶ 1,694:
0xecac89cad93923c02321 -> EJDM8drfXA6uyA
0x10c8511e -> Rt5zm</pre>
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|Wren-big}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">import "./big" for BigInt
import "./fmt" for Fmt
var alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
var big58 = BigInt.new(58)
var convertToBase58 = Fn.new { |hash, base|
var x = (base == 16 && hash.startsWith("0x")) ? BigInt.fromBaseString(hash[2..-1], 16) :
BigInt.fromBaseString(hash, base)
var sb = ""
while (x > BigInt.zero) {
var r = (x % big58).toSmall
sb = sb + alphabet[r]
x = x / big58
}
return sb[-1..0]
}
var s = "25420294593250030202636073700053352635053786165627414518"
var b = convertToBase58.call(s, 10)
System.print("%(s) -> %(b)")
var hashes = [
"0x61",
"0x626262",
"0x636363",
"0x73696d706c792061206c6f6e6720737472696e67",
"0x516b6fcd0f",
"0xbf4f89001e670274dd",
"0x572e4794",
"0xecac89cad93923c02321",
"0x10c8511e"
]
for (hash in hashes) {
var b58 = convertToBase58.call(hash, 16)
Fmt.print("$-56s -> $s", hash, b58)
}</syntaxhighlight>
{{out}}
<pre>
25420294593250030202636073700053352635053786165627414518 -> 6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM
0x61 -> 2g
0x626262 -> a3gV
0x636363 -> aPEr
0x73696d706c792061206c6f6e6720737472696e67 -> 2cFupjhnEsSn59qHXstmK2ffpLv2
0x516b6fcd0f -> ABnLTmg
0xbf4f89001e670274dd -> 3SEo3LWLoPntC
0x572e4794 -> 3EFU7m
0xecac89cad93923c02321 -> EJDM8drfXA6uyA
0x10c8511e -> Rt5zm
</pre>
=={{header|zkl}}==
Uses libGMP
<
src="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv",
dst="123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
Line 1,210 ⟶ 1,764:
0x516b6fcd0f, "bf4f89001e670274dd", 0x572e4794,
"ecac89cad93923c02321", 0x10c8511e);
ns.pump(Console.println,'wrap(n){ BN(n,16).toString(58).translate(src,dst) });</
{{out}}
<pre>
|