Skip to content

Commit

Permalink
Add KATs for ML-DSA
Browse files Browse the repository at this point in the history
This adds KATs based on the 'official' ACVP-Server KAT vectors and a
a python script that illustrates the necessary steps to convert these
KAT vectors into a format usable by our test framework.
  • Loading branch information
atreiber94 authored and reneme committed Oct 14, 2024
1 parent 319dea1 commit 5f1b220
Show file tree
Hide file tree
Showing 9 changed files with 1,093 additions and 3 deletions.
8 changes: 5 additions & 3 deletions src/scripts/dev_tools/gen_dilithium_kat.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,18 +106,20 @@ def main(args = None):
args = sys.argv

randomized = True
is_mldsa = True

type = 'Randomized' if randomized else 'Deterministic'
name = 'ml-dsa' if is_mldsa else 'dilithium'

for file in args[1:]:
mode = map_mode(open(file).readline().strip()[2:])

reader = KatReader(open(file))

output = open('src/tests/data/pubkey/dilithium_%s_%s.vec' % (mode, type), 'w')
output = open('src/tests/data/pubkey/%s_%s_%s.vec' % (name, mode, type), 'w')

print("# See src/scripts/dilithium_kat_compress.py\n", file=output)
print("[Dilithium_%s]" % (mode), file=output)
print("# See src/scripts/dev_tools/gen_dilithium_kat.py\n", file=output)
print("[%s_%s]" % (name.upper() if is_mldsa else name.capitalize(), mode), file=output)

for kat in reader.read_kats():
kat = compress_kat(kat)
Expand Down
144 changes: 144 additions & 0 deletions src/scripts/dev_tools/gen_pqc_dsa_kats.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# This test data is generated from the *_DSA implementations of https://github.com/mjosaarinen/py-acvp-pqc/tree/main
# and using the drbg.aes256_ctr_drbg module from https://github.com/giacomopope/dilithium-py
#
# (C) 2024 Jack Lloyd
# (C) 2024 Amos Treiber, René Meusel - Rohde & Schwarz Cybersecurity
#
# Botan is released under the Simplified BSD License (see license.txt)
#

import binascii
import hashlib
import os
import re
import sys
from dilithium_py.drbg.aes256_ctr_drbg import AES256_CTR_DRBG
from fips204 import ML_DSA, ML_DSA_PARAM
from fips205 import SLH_DSA_PARAMS

random_bytes = os.urandom

# "ML-DSA-44" -> "ml-dsa-4x4"
def transform_mldsa_string(s):
s = s.lower()
transformed = re.sub(r'(\d)(\d)$', r'\1x\2', s)
return transformed

def create_mldsa_ini_label(s, det):
algo = re.sub(r'(\d)(\d)$', r'\1x\2', s)
return f"[{algo}_{det}]"

def sha3_256(v):
h = hashlib.sha3_256()
h.update(v)
return h.digest()


def sha256(v):
h = hashlib.sha256()
h.update(v)
return h.digest()

def sign(sign_internal_func, sk_bytes, m, random_bytes, n, ctx=b"", deterministic=False):
if len(ctx) > 255:
raise ValueError(
f"ctx bytes must have length at most 255, ctx has length {len(ctx) = }"
)
if deterministic:
rnd = None
else:
rnd = random_bytes(n) #drbg.random_bytes(n)
# Format the message using the context
m_prime = bytes([0]) + bytes([len(ctx)]) + ctx + m
# Compute the signature of m_prime
sig_bytes = sign_internal_func(m_prime, sk_bytes, rnd)
return sig_bytes

def main(args = None):
msg = binascii.unhexlify("D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8")
if args is None:
args = sys.argv

if len(args) != 2 or (args[1] != "ml_dsa" and args[1] != "slh_dsa"):
print("Usage: gen_pqc_dsa_kats.py <ml_dsa|slh_dsa>")
return 1

algo = args[1]

# Initialize DRBG with the magic value
entropy = binascii.unhexlify("60496cd0a12512800a79161189b055ac3996ad24e578d3c5fc57c1e60fa2eb4e550d08e51e9db7b67f1a616681d9182d")
drbg = AES256_CTR_DRBG(seed=entropy)

if algo == "slh_dsa":
output = open('src/tests/data/pubkey/slh_dsa.vec', 'w')

print("# See src/scripts/dev_tools/gen_pqc_dsa_kats.py\n", file=output)

for param, alg in SLH_DSA_PARAMS.items():
hash_fn = sha256 if "sha2" in param.lower() else sha3_256

seed = drbg.random_bytes(len(entropy))

drbg_instance = AES256_CTR_DRBG(seed=seed)
keygen_rand = drbg_instance.random_bytes(3*alg.n)
sk_seed = keygen_rand[:alg.n]
sk_prf = keygen_rand[alg.n:2*alg.n]
pk_seed = keygen_rand[2*alg.n:]
pk, sk = alg.slh_keygen_internal(sk_seed, sk_prf, pk_seed)
signature_rand = sign(alg.slh_sign_internal, sk, msg, drbg_instance.random_bytes, alg.n, deterministic=False)
signature_det = sign(alg.slh_sign_internal, sk, msg, drbg_instance.random_bytes, alg.n, deterministic=True)

print("SphincsParameterSet = %s" % param, file=output)
print("seed = %s" % seed.hex().upper(), file=output)
print("msg = %s" % msg.hex().upper(), file=output)
print("pk = %s" % pk.hex().upper(), file=output)
print("sk = %s" % sk.hex().upper(), file=output)
if param == "SLH-DSA-SHAKE-128s":
print("SigDet = %s" % binascii.hexlify(signature_det).decode("utf-8").upper(), file=output)
print("HashSigDet = %s" % binascii.hexlify(hash_fn(signature_det)).decode("utf-8").upper(), file=output)
print("HashSigRand = %s" % binascii.hexlify(hash_fn(signature_rand)).decode("utf-8").upper(), file=output)
print("", file=output)

elif algo == "ml_dsa":
for param in ML_DSA_PARAM.keys():
for det_str, deterministic in [("Deterministic", True), ("Randomized", False)]:
alg = ML_DSA(param)
output = open('src/tests/data/pubkey/%s_%s.vec' % (transform_mldsa_string(param), det_str), 'w')
print("# See src/scripts/dev_tools/gen_pqc_dsa_kats.py", file=output)
print("", file=output)
print(create_mldsa_ini_label(param, det_str), file=output)
print("", file=output)

hash_fn = sha3_256
def mldsa_sign_internal(m, sk, rnd):
# For some reason the interfaces vary between FIPS 204 and FIPS 205...
if rnd == None:
rnd = bytes([0]*32)
return alg.sign_internal(sk, m, rnd)

samples = 25
for _ in range(100):
seed = drbg.random_bytes(len(entropy))

if samples == 0:
continue

samples -= 1
drbg_instance = AES256_CTR_DRBG(seed=seed)
keygen_rand = drbg_instance.random_bytes(32)
pk, sk = alg.keygen_internal(keygen_rand)
signature = sign(mldsa_sign_internal, sk, msg, drbg_instance.random_bytes, 32, deterministic=deterministic)

print("Seed = %s" % seed.hex().upper(), file=output)
print("Msg = %s" % msg.hex().upper(), file=output)
print("HashPk = %s" % binascii.hexlify(hash_fn(pk)).decode("utf-8").upper(), file=output)
print("HashSk = %s" % binascii.hexlify(hash_fn(keygen_rand)).decode("utf-8").upper(), file=output)
print("HashSig = %s" % binascii.hexlify(hash_fn(signature)).decode("utf-8").upper(), file=output)
print("", file=output)
else:
print("Usage: gen_pqc_dsa_kats.py <ml_dsa|slh_dsa>")
return 1

if __name__ == '__main__':
sys.exit(main())

154 changes: 154 additions & 0 deletions src/tests/data/pubkey/ml-dsa-4x4_Deterministic.vec
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# See src/scripts/dev_tools/gen_pqc_dsa_kats.py

[ML-DSA-4x4_Deterministic]

Seed = 23F1C88BD0E65F2C891CE865BD3275A7FFDBE4F9036E75B96AAD0412650E9CD2EA4591D4AB7131EA971B34C23A4ED245
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = 23FFCA1815890E764D3E95D9586B4B36B78FA726AA720A6FACC9485CE5C22CE1
HashSk = BBD7B9D5D89564D38F3E5C930CF77E529AD84868FCC486871E6CBB66CCBDE1FD
HashSig = AF9D83B50B0DC0F5E7877549FF6AE7F05A8B9A8F28ED399EC33BFFEAF06A217B

Seed = 6FB79C668EB6E0F65A09135CDD243CE205D7065A0924F86024ADCD111F654A6DFE2E398A12369064C2A217229113E570
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = 93B8CBA713F8C9EB1D19CEBC19A6787C6CC1E31964253BECCCC9802F76E27AC0
HashSk = 6C22DEAE7B12857E0566C187ADBBB74862C0978CF777565DC7438AE57126ECB9
HashSig = AD165069CC5745E3D5BE6B37E3FB5DE5C9E0F08386BCCD07E18D1941171681C7

Seed = AD4D2D306639620AFCB3753A137F89331836A5ADCE1C40BEBE77B82D43A40D3249000C7AA3786406D5D5FA65462D1A57
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = 8FF607AEF792D68EA8662F098DEB407F4BD5D2FE726F9F1A14DCBED0FDB44E52
HashSk = 40B2D91B0F9B8C5CFE6FC59228287B71B47A4AB844D1D0087C052C2325423C32
HashSig = C31658E5AE02AA4F849BB0C7BD851587B2E438EDE4D02DC7BFAA574181E46041

Seed = 950684CB360FF0C011FD02A09A273C9F023D0A34AE0AA338C6F5283634AE9BEF5D100BCD48F6577E5910BEAAFE6C52C3
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = 6FA5431E69AF41185CF3C08C42B96BB7091CF5AC4DE69CE86F76ECCD47920CC4
HashSk = A0A0DF3AD18D8E1DB7BDEB2E339BDF1D75A1C376AEA3BF6D8D7864B2EE4446F1
HashSig = 9ECF01B41517D77C79A0F930F07AC7C05866806A497D5686437AA9CC62142F54

Seed = 0633CCD19471803E0CEFFC7A11B2E7B70C3329DFDDE5BE18160DF0D4C609900D67154893921376CC4B4B8C586E3EFE79
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = 5658E47FD02903B3341CBE083AFDC1D2FB1CFD71356E7F5033E24148D7C45608
HashSk = 4E65F124A607187E7413C462B3786669323FC72B542A578BB8DFDDBD4CBAFD0A
HashSig = 40CF0BA9CFB34D7922955BD87DBC6D43930849F37DBAF86F91A10A2D45A8FFAB

Seed = 2605426643CAB04B2801416B3239CD046DFE7BA59874A3A05C5B32A4505F21D8B7217B5ECC8646FC6A845211AE4BC708
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = 835A9AF779C23C6B0D3BAAFED72D384FBA4C2E01044028146757DA600EE1882D
HashSk = 29C7213AA5D1915123E2731503F6B1DE8759708D60456233CA4CD3210B77F5BB
HashSig = A9B5A23C0A119954D0BC4006C94AB64AC5B0A720B009D1396CED482033CC9B79

Seed = D3880D1B7802B4A3277687863C5A248BEFC95D3E4748403F3BB61F83ABCDDEAE42AE6C8624812FD38F463122D99D59A9
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = 9FFCBA17132ECF06DF537167ACFE7845301AF53046E56F138249D369CA4ADBE0
HashSk = 6F23C6840447888675CD67742EB0D1CFFA0772F9E59A7D21B8363580562F78F5
HashSig = 4B1BA2AC0B4974E1CD1002BD75CCBA4766D1096F601DECD34167179CBC948F9B

Seed = 343B81870E2721DD75EE0AD7FDB269EB5AAE0AE83A6316AD8ECE3C76D3DD3CC391F1B12B22E988C1257B5F56D905A06C
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = 27F8ACF8A0F46FD7D637712B7349CB168F67F327CD66933001A3FCC4FE17E50E
HashSk = 2932C123DC8D65A2F6BE6EF119A401ACBD86951DCC52F7805CDC18EF1609CFB1
HashSig = 3E8B36F42317995DB63C3914F37E7FD15FB9DAA4B11A1274841B74B644A5A7A9

Seed = 406D9C95F9813CA6A9E6071D3A7A63093F9E00CD15EE968C3AB28CB7368699491E5662F6B63721FE059D50295C3A7516
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = 7447A6691EEF12AE43676F6EF077DD083B20503D11D2E3D46D5E86441E91B990
HashSk = B04D1B11E3CAA61878C3362560865A055C1265C854EE238B85A24603A55B3778
HashSig = 3731257AD3871DF24A4E3D3D4351B48E25B8BABDC985ACF7AE110F0A6F4F3975

Seed = B3C83C13DD15DFFE58FDB6026D32E33E5EF24B094BE16741DD5B587EA841AD19B6F026A127678849EC1B459A365FD645
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = 1F895273F0540216F9F6075BD9FBFFDDE8730126E5453950A39525DDE78BD843
HashSk = 861F343C1FE7455F544235A664A9E0EE40D7B4580B62048FEBFD7A5CC82F64F0
HashSig = 723EEBBE7336F6861ADFA8BC1E7563E5A8C88B9C415876B656FAE2454A9D96CC

Seed = 937BD532FF7C92404ACA9C2389E314F72D780234E1FD930F967A724937204C59877AF25D38245638FDA72B0EE74F8492
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = E4318667275AB40D0F22DE05758B2AA687B24F1DDFD2A20A1E7396F3EE695460
HashSk = 594D7A0A4C3786FAA85FC47A620EF9B1AF0B86BA846118E0BEB1A0FC2A6A12A6
HashSig = 4C6F66AEA3458921F900D658D2B5B868B81C27C2EA852A682DCDA7710E30CC8E

Seed = 075D939507DDEAB7C64FB847EDB74CF693866BEA32C93BC5C129CBD7141C0B79901B26992481236A56CB404D464DA0E1
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = 5E158BE66C1CC67818E92B88D9343094E96A2E163DF8024C3235885D3BA3CE96
HashSk = B99B43BF3B3F1B13683CA8DB1290D4D6F459E793E99BD8A3B58399EE079CABE9
HashSig = CC3003670414ADC3B589CBDFB0AC7B218D9EF73BF5F57A3C8AD1742BF9A7AF09

Seed = 40CC0DF72EECC2E75DE19C2D9765958C72F3C609D730911977CC93D3C68CA97A28EE7AB4102ACF3EAEF5982C302F7427
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = 3513DDD518FE41A94139641047A01FC2AF25B27C351D82D4100750D8EBC1F2FD
HashSk = 7ACE6EF90BE1CE60087E7D1EFC3C059703B132FE94F30AA86997261701B0A754
HashSig = 1B036E081E62ED704734B8F7B9CB7B04D908A6EA26B56EF36E14D22E3DBD0B75

Seed = B6EA97260B9732A7CA5F0AFC4D9ADF4B34B7A28B28AA7B60B6E92E87E65410D5D9C0E1BC46E36B34A29EAF32BDE1623E
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = 2526373FB2C45DF9439B5AE65DE6B8D14180787B68F9EA88BD2D7466ABE0C05C
HashSk = 0775E82244C1C8FC0194DDB95C0C2BED724A951D9A1C1D8F19E1F94146408FC4
HashSig = 6A533791C77B0858577F0957DF4E3F55F0BCA1C7F393CB55F8AC96EEDF65A171

Seed = 626AFD438FD9C449DE3FBE8E826A1ABFDB14D9D0DF7167E39A849DB730118F20B3042CDC5D0714C3D10E1CD447329386
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = 7CB764285F655DE38BFCC05D4C33BD7508E2DD329C48E94EFD13A89DE2960A97
HashSk = C671B09DAB46D026D54E76CAECB4F9808B8C8277C116A3E44CB3BB662575B95D
HashSig = 70F72F899EDD287ABBF39BCF0C591C656F796D6D4CBCA999E5D831636D97C6BD

Seed = 8484D545A1CFC58069DB9AD0E9DB3244DF1D020B8957549064A5E7CAFAE6AE06A671F5E79797B42520464BBB95F5AA2B
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = CB9810BAA56620FB3BF48A503B48CE70CDCA8B3452A5A3F72A35298EA718D83B
HashSk = 1FF31944B5E4003263EA87968AE9492B59C953635E6605B8686642DE8B04A30B
HashSig = FAFFB84C9896F8876B9CB1580BF8A0C0BAB7FF63362C27383734A32C48AE8587

Seed = CF525FF8D68F7717A6DD534843AE9688F2037019A7AAA012951282DA883F499F080192BB5D7B74B5CB1CE6E160519BAF
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = EAA56CB2386302DB6F9708CF96A185B8D2B1AFD96D8C7721F9BF2142606F94CC
HashSk = 60224705C5931BB3AB5EB90831E731959C5F56D384DE04CE8F30768B51FCCB64
HashSig = A87BEABA08D172ADC2181B9BEDB5A4F8BD1913456428865748FE75A123BCE32E

Seed = 6D1579C271A32D9C51709409E2CF2B795638ECBDA9621AF6C409F76856EAA364C741BEDED3CA09C9CB64DE764690CB82
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = 0D7512B28D3EB78B987ED175E34468477AEE6FB3F2F5DAB141449CCF6C6A0CFD
HashSk = A5FC4D414FB610C669497E87711097E4DC14CE603C4477546815C24888F04AD1
HashSig = BECDDC15803830FD00247537C9B164437E6F342A25F4EFFD69A605B1648AB428

Seed = CB872DCDFFA86F3F117A4DC5ADF5EA6A3B1C312D618FC1A070F67586185711D650EBB5B6299BBCD41081B063403F59B7
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = 46744F5F5C66BEA375266FC5182EE5A8C15B27B293DA9AA4C1B1241895BA268E
HashSk = 719E8934ED7FFA3B212B73E60386140D32D213725FAF0A71FF07B34A2C460CDE
HashSig = FE94CCD092E16091DF0D09CFF48CB35197A5F5FAA13D9563E9AF1E0522E349DD

Seed = 4BE36BA806CDB11EC9A65F900AF0CB580D2E5FAC37EE8745AA2970A7DB4C8244491D875C0B4A7FE64FF09BC6AC2A2F83
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = 9B8B0ACE0CCC67ADE076318ED52BF1B828971D1A44422296FBCF074525B8E7F7
HashSk = DDDC718518C65477D89F024306134534376578994183FA5430868AB8F798BE13
HashSig = 5EA7C295BBB98FB362AD5DDCCEF9DF10D4C741D19DAA596AA779D93463ABEEAA

Seed = 81C2294B8C26071D6EF0288F547789A3B563F5D511CF1D7B812C17E2E507DA925D4BE870D837CDF42A1E980C532FC0B6
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = 4CE2847E8B7631A8FEE8233BA71B866E9B8881C965B01446BEF9B0E4E873F3F6
HashSk = D7C59F15998493A728FD6BD7B41DB721FA9FAE1804539BE684DCF9953F82D339
HashSig = E567DD8BA9C44FE0B4DE538CEF429E71DC5B2DDD0D9BB6E574EEBEBABFE07EBF

Seed = C46854665B9852229D9C64000820CB49B8D023FA951977CEDF2BD6650C48FD13B6A0FFD8F002558F0C03F0AECE457A6C
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = EEE51D669BF7E7ADBC66D73E09737051E7108780EB0D22A2491CD105E4219CC5
HashSk = 8544D6072FDABD0664D68E002BC6838F7D5EBE3A5CD2AB1A63F413BB2F099FC8
HashSig = DA061D625DA73504256FA72F55514E6F94669CB8298EFEAE54AF643FC05B5EE5

Seed = 430399BB2441C965586739BA1E5F7CD7BFD1D1D0C903A2C575B764AD7F2E3EE012451A5E136423DAB0BE7A86B99DB19A
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = 2FB676DA63076C441A70B176B25E074C443D59372636C0A10608E31402F5908A
HashSk = 8B503EFFC6CBE3E9A041C8C3202508FD239FB7ECD7FBBDE70307A7853DFC12AB
HashSig = 266AC86541B4DAC81B2EF8684ABE25FA768F4F4676D4A5595F787D074198E195

Seed = D5040EE87EEAF9F4001CE18F5AC6106CBC7AC498C2F290EE47F07702C66AE73E930B6911C7D0E7F0751A4D03AB56F5B2
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = FEB5AC33DF18EE3BC0CFAC14C4BCF8BF5770A21BCD75A0F369D29132DCA46B73
HashSk = BBA0D34E2D281E910190136B53D5C995A98D3BDE8C6AC8CEB99E7344B8DEB39D
HashSig = FF6EE769D99CB5E891902D555467216E3FDC5F50DA63D45BBFC35B134488BBB5

Seed = 2A74F833B43587B6A6C67B1DC708F553E00FFE59841C3AA6C61F8E15E815B1CA1071B5F6FB8BDDBC1CBFF6B053D8854D
Msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8
HashPk = 358D89AC8E4C500C478FE8B571F44BECAF557AD69C1F18A4EB1B82300FD4E4F5
HashSk = 16C429D71F4E25AD4231557541EB221FA5DD5AC51607FCFA7FAF7C6B145E750F
HashSig = 976AF1DC3BC950515F9C6237CF879BB481A628470E74BCD5698C65C1F120F50C

Loading

0 comments on commit 5f1b220

Please sign in to comment.