75 lines
2 KiB
Nim
75 lines
2 KiB
Nim
import algorithm
|
|
|
|
const SHA256Len = 32
|
|
const AddrLen = 25
|
|
const AddrMsgLen = 21
|
|
const AddrChecksumOffset = 21
|
|
const AddrChecksumLen = 4
|
|
|
|
proc SHA256(d: pointer, n: culong, md: pointer = nil): cstring {.cdecl, dynlib: "libssl.so", importc.}
|
|
|
|
proc decodeBase58(inStr: string, outArray: var openarray[uint8]) =
|
|
let base = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
|
|
|
outArray.fill(0)
|
|
|
|
for aChar in inStr:
|
|
var accum = base.find(aChar)
|
|
|
|
if accum < 0:
|
|
raise newException(ValueError, "Invalid character: " & $aChar)
|
|
|
|
for outIndex in countDown((AddrLen - 1), 0):
|
|
accum += 58 * outArray[outIndex].int
|
|
outArray[outIndex] = (accum mod 256).uint8
|
|
accum = accum div 256
|
|
|
|
if accum != 0:
|
|
raise newException(ValueError, "Address string too long")
|
|
|
|
proc verifyChecksum(addrData: openarray[uint8]) : bool =
|
|
let doubleHash = SHA256(SHA256(cast[ptr uint8](addrData), AddrMsgLen), SHA256Len)
|
|
|
|
for ii in 0 ..< AddrChecksumLen:
|
|
if doubleHash[ii].uint8 != addrData[AddrChecksumOffset + ii]:
|
|
return false
|
|
|
|
return true
|
|
|
|
proc main() =
|
|
let
|
|
testVectors : seq[string] = @[
|
|
"3yQ",
|
|
"1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9",
|
|
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",
|
|
"1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nJ9",
|
|
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I",
|
|
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62ix",
|
|
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62ixx",
|
|
"17NdbrSGoUotzeGCcMMCqnFkEvLymoou9j",
|
|
"1badbadbadbadbadbadbadbadbadbadbad",
|
|
"16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM",
|
|
"1111111111111111111114oLvT2",
|
|
"BZbvjr",
|
|
]
|
|
|
|
var
|
|
buf: array[AddrLen, uint8]
|
|
astr: string
|
|
|
|
for vector in testVectors:
|
|
stdout.write(vector & " : ")
|
|
try:
|
|
decodeBase58(vector, buf)
|
|
|
|
if buf[0] != 0:
|
|
stdout.write("NG - invalid version number\n")
|
|
elif verifyChecksum(buf):
|
|
stdout.write("OK\n")
|
|
else:
|
|
stdout.write("NG - checksum invalid\n")
|
|
|
|
except:
|
|
stdout.write("NG - " & getCurrentExceptionMsg() & "\n")
|
|
|
|
main()
|