From d82fac91edad72cac69b0381aac66ff158ed58e3 Mon Sep 17 00:00:00 2001 From: Chengcheng Zhang <943420582@qq.com> Date: Tue, 26 Mar 2019 17:24:55 +0800 Subject: [PATCH] add get_new_key --- pybtm/__init__.py | 2 +- pybtm/key.py | 259 ++++++++++++++++++++++++++++++++++++++++++++++++++++- pybtm/signature.py | 38 ++++++++ pybtm/utils.py | 14 +++ setup.py | 2 +- 5 files changed, 310 insertions(+), 5 deletions(-) create mode 100644 pybtm/signature.py create mode 100644 pybtm/utils.py diff --git a/pybtm/__init__.py b/pybtm/__init__.py index 8f6fa39..0384550 100644 --- a/pybtm/__init__.py +++ b/pybtm/__init__.py @@ -1,2 +1,2 @@ name = "pybtm" -version = "0.0.8" \ No newline at end of file +version = "0.0.9" \ No newline at end of file diff --git a/pybtm/key.py b/pybtm/key.py index 7289c20..75e6f83 100644 --- a/pybtm/key.py +++ b/pybtm/key.py @@ -3,6 +3,8 @@ import hashlib import pbkdf2 import hmac from .edwards25519 import * +from .signature import * +from .utils import * def get_entropy(): @@ -39,8 +41,8 @@ def get_mnemonic(entropy_hexstr=None): entropy_bytes = bytes.fromhex(entropy_hexstr[:32]) checksum = hashlib.sha256(entropy_bytes).hexdigest()[:1] - new_entropy_str = "0" + entropy_hexstr[:32] + checksum - new_entropy_bytes = bytes.fromhex(new_entropy_str) + new_entropy_hexstr = "0" + entropy_hexstr[:32] + checksum + new_entropy_bytes = bytes.fromhex(new_entropy_hexstr) new_entropy_int = int.from_bytes(new_entropy_bytes, byteorder='big') for i in range(11, -1, -1): @@ -127,4 +129,255 @@ def get_xpub(xprv_hexstr): buf = encodepoint(scalarmultbase(scalar)) xpub = buf + xprv_bytes[len(xprv_bytes)//2:] xpub_hexstr = xpub.hex() - return xpub_hexstr \ No newline at end of file + return xpub_hexstr + + +# get_expanded_private_key create expanded private key from xprv +# You can get more test data from: https://gist.github.com/zcc0721/ef0bf2e69f5e92b29d716981f2a8fe7d +# test data 1: +# xprv_hexstr: 406c82307bf7978d17f3ecfeea7705370e9faef2027affa86c8027c6e11a8a50e231e65bd97048850ae6c39d0f46b63ae70aa24f5aac7877727c430c2201e6d6 +# expanded_private_key_str_xprv: 406c82307bf7978d17f3ecfeea7705370e9faef2027affa86c8027c6e11a8a50d828bf44b1a109c2bbb4c72685858e2f2ab8b405beef1e4ecc12d1ed8511e8eb +# test data 2: +# xprv_hexstr: 6032adeb967ac5ccbf988cf8190817bf9040c8cfd9cdfe3d5e400effb2946946d478b61cc6be936f367ae769eb1dc65c473ee73cac2eb43cf6d5e7c62b7f0062 +# expanded_private_key_str_xprv: 6032adeb967ac5ccbf988cf8190817bf9040c8cfd9cdfe3d5e400effb2946946ddbb71e7a76595c6bc24937d76085d24315713764cbdf1364ab9091953009cd8 +# test data 3: +# xprv_hexstr: 509a095ad862322641b8d66e84561aae1d4816045167e2c4dfadf464928e114300c0a162d41c0cdf196d61f4492f546e50bfff253b9d5d930d1bb89197cd333d +# expanded_private_key_str_xprv: 509a095ad862322641b8d66e84561aae1d4816045167e2c4dfadf464928e11432787f5e10f9598f80fb41e4a648b609463c06e625641366f3279658b2b0f5268 +def get_expanded_private_key(xprv_hexstr): + hc_hexstr = hmac.HMAC(b'Expand', bytes.fromhex(xprv_hexstr), digestmod=hashlib.sha512).hexdigest() + expanded_private_key_hexstr = xprv_hexstr[:64] + hc_hexstr[64:] + return expanded_private_key_hexstr + + +# get_public_key create 32 bytes public key from xpub +# xpub length is 64 bytes. +# You can get more test data from: https://gist.github.com/zcc0721/9e10f2fa5bd0c8f33aa6dfc87f6aa856 +# test data 1: +# xpub_hexstr: ecc2bbb6c0492873cdbc81edf56bd896d3b644047879840e357be735b7fa7b6f4af1be7b8d71cc649ac4ca3816f9ccaf11bf49f4effb845f3c19e16eaf8bfcda +# public_key_hexstr: ecc2bbb6c0492873cdbc81edf56bd896d3b644047879840e357be735b7fa7b6f +# test data 2: +# xpub_hexstr: 406c82307bf7978d17f3ecfeea7705370e9faef2027affa86c8027c6e11a8a50e231e65bd97048850ae6c39d0f46b63ae70aa24f5aac7877727c430c2201e6d6 +# public_key_hexstr: 406c82307bf7978d17f3ecfeea7705370e9faef2027affa86c8027c6e11a8a50 +# test data 3: +# xpub_hexstr: b435f948bd3748ede8f9d6f59728d669939e79c6c885667a5c138e05bbabde1de0dcfcbe0c6112022fbbf0da522f4e224a9c2381016380688b51886248b3156f +# public_key_hexstr: b435f948bd3748ede8f9d6f59728d669939e79c6c885667a5c138e05bbabde1d +def get_public_key(xpub_hexstr): + public_key_hexstr = xpub_hexstr[:64] + return public_key_hexstr + + +def prune_intermediate_scalar(f): + f = bytearray(f) + f[0] = f[0] & 248 # clear bottom 3 bits + f[29] = f[29] & 1 # clear 7 high bits + f[30] = 0 # clear 8 bits + f[31] = 0 # clear 8 bits + return f + + +# get_child_xprv create new xprv through the path +# xprv_hexstr length is 64 bytes. +# path_list item is hex string. +# child_xprv length is 64 bytes. +# You can get more test data from: https://gist.github.com/zcc0721/3377f520954db38070e8e9c80d3a5bfd +# test data 1: +# xprv_hexstr: 10fdbc41a4d3b8e5a0f50dd3905c1660e7476d4db3dbd9454fa4347500a633531c487e8174ffc0cfa76c3be6833111a9b8cd94446e37a76ee18bb21a7d6ea66b +# path_list: 010400000000000000 +# path_list: 0100000000000000 +# child_xprv_hexstr: 0813a3abf814e4b4064b9b0492071176d8d98652081aced6fefe2b7363a83353f960274ff5ef195599a765e7bc24eddc2a1e6c73da0e6e0a4b47e65338bea9a6 +# test data 2: +# xprv_hexstr: c003f4bcccf9ad6f05ad2c84fa5ff98430eb8e73de5de232bc29334c7d074759d513bc370335cac51d77f0be5dfe84de024cfee562530b4d873b5f5e2ff4f57c +# path_list: 00 +# path_list: 00 +# child_xprv_hexstr: b885ac5535c35ae45b51a84b1190f7c31b21acff552c7680413905a9c6084759e9a8f3578fe2973e37d96bad45e8d9255f3b82019f326550d24374aeafece958 +# test data 3: +# xprv_hexstr: 0031615bdf7906a19360f08029354d12eaaedc9046806aefd672e3b93b024e495a95ba63cf47903eb742cd1843a5252118f24c0c496e9213bd42de70f649a798 +# path_list: 00010203 +# child_xprv_hexstr: 20f86339d653bb928ad1f7456279692ac6adf89035f846c6659aaa151c034e497387952cb0dbd6c03bae6742ebe3213b7c8da5805900ab743a653dd3799793eb +# test data 4: +# xprv_hexstr: 0031615bdf7906a19360f08029354d12eaaedc9046806aefd672e3b93b024e495a95ba63cf47903eb742cd1843a5252118f24c0c496e9213bd42de70f649a798 +# path_list: 00 +# child_xprv_hexstr: 883e65e6e86499bdd170c14d67e62359dd020dd63056a75ff75983a682024e49e8cc52d8e74c5dfd75b0b326c8c97ca7397b7f954ad0b655b8848bfac666f09f +# test data 5: +# xprv_hexstr: c003f4bcccf9ad6f05ad2c84fa5ff98430eb8e73de5de232bc29334c7d074759d513bc370335cac51d77f0be5dfe84de024cfee562530b4d873b5f5e2ff4f57c +# path_list: 010203 +# path_list: 7906a1 +# child_xprv_hexstr: 4853a0b00bdcb139e85855d9594e5f641b65218db7c50426946511397e094759bd9de7f2dcad9d7d45389bc94baecaec88aabf58f6e1d832b1f9995a93ec37ea +def get_child_xprv(xprv_hexstr, path_list): + for i in range(len(path_list)): + selector_bytes = bytes.fromhex(path_list[i]) + xpub_hexstr = xprv_to_xpub(xprv_hexstr)['xpub'] + xpub_bytes = bytes.fromhex(xpub_hexstr) + xprv_bytes = bytes.fromhex(xprv_hexstr) + hc_bytes = hmac.HMAC(xpub_bytes[32:], b'N'+xpub_bytes[:32]+selector_bytes, digestmod=hashlib.sha512).digest() + hc_bytearr = bytearray(hc_bytes) + + f = hc_bytearr[:32] + f = prune_intermediate_scalar(f) + hc_bytearr = f[:32] + hc_bytearr[32:] + + carry = 0 + total = 0 + for i in range(32): + total = xprv_bytes[i] + hc_bytearr[i] + carry + hc_bytearr[i] = total & 0xff + carry = total >> 8 + if (total >> 8) != 0: + print("sum does not fit in 256-bit int") + xprv_hexstr = hc_bytearr.hex() + + child_xprv_hexstr = xprv_hexstr + return child_xprv_hexstr + + +# get_child_xpub create new xpub through the path +# xpub_hexstr length is 64 bytes. +# path_list item is hex string. +# child_xpub length is 64 bytes. +# You can get more test data from: https://gist.github.com/zcc0721/1dea9eb1edb04f57bc01fecb867301b8 +# test data 1: +# xpub_hexstr: cb22ce197d342d6bb440b0bf13ddd674f367275d28a00f893d7f0b10817690fd01ff37ac4a07869214c2735bba0175e001abe608db18538e083e1e44430a273b +# path_list: 010400000000000000 +# path_list: 0100000000000000 +# child_xpub_hexstr: 25405adf9bcefebaa2533631a6bdd5a93108e52ed048c7c49df21a28668768f8d15048473b96fc4d3bc041a881168b41552cabe883221a683aeddc37c1f4644c +# test data 2: +# xpub_hexstr: cb22ce197d342d6bb440b0bf13ddd674f367275d28a00f893d7f0b10817690fd01ff37ac4a07869214c2735bba0175e001abe608db18538e083e1e44430a273b +# path_list: 00 +# path_list: 00 +# child_xpub_hexstr: 1ff4b10aa17eb164a01bedf4f48d55c1bcbd55f28adb85e31c4bad98c070fc4ecb4228fb3f2f848384cc1a9ea82e0b351a551a035dd8ab34e198cfe64df86c79 +# test data 3: +# xpub_hexstr: cb22ce197d342d6bb440b0bf13ddd674f367275d28a00f893d7f0b10817690fd01ff37ac4a07869214c2735bba0175e001abe608db18538e083e1e44430a273b +# path_list: 00010203 +# child_xpub_hexstr: 19ab025cd895705c5e2fab8d61e97bcf93670d2c2d6b4cdf06b5347a0cf0527df138d9e540093aad51ed56cf67e6a4b36e6c68327c61593707829339cc9a7f65 +# test data 4: +# xpub_hexstr: ead6415a077b91aa7de32e1cf63350f9351d0298f5accc2cf92ef9429bd1f86c166364ce19322721b7dec84442c3665d97d0e995ba4d01c0f4b19b841379ac90 +# path_list: 00010203 +# path_list: 03ededed +# path_list: 123456 +# child_xpub_hexstr: c6888c31265519f59975f9fe25a4199735efbb24923648dd880dacb6ed580bdc7b79a9aa09095590175f756c1e11fcb4f8febecb67582c9fea154fd2547cd381 +# test data 5: +# xpub_hexstr: 1b0541a7664cee929edb54d9ef21996b90546918a920a77e1cd6015d97c56563d513bc370335cac51d77f0be5dfe84de024cfee562530b4d873b5f5e2ff4f57c +# path_list: 010203 +# path_list: 7906a1 +# child_xpub_hexstr: e65c1a9714e2116c6e5d57dee188a53b98dc901a21def5a5ca46fcf78303f4f2bd9de7f2dcad9d7d45389bc94baecaec88aabf58f6e1d832b1f9995a93ec37ea +def get_child_xpub(xpub_hexstr, path_list): + for i in range(len(path_list)): + selector_bytes = bytes.fromhex(path_list[i]) + xpub_bytes = bytes.fromhex(xpub_hexstr) + hc_bytes = hmac.HMAC(xpub_bytes[32:], b'N'+xpub_bytes[:32]+selector_bytes, digestmod=hashlib.sha512).digest() + hc_bytearr = bytearray(hc_bytes) + + f = hc_bytearr[:32] + f = prune_intermediate_scalar(f) + f = bytes(f) + scalar = decodeint(f) + F = scalarmultbase(scalar) + + P = decodepoint(xpub_bytes[:32]) + P = edwards_add(P, F) + public_key = encodepoint(P) + + xpub_bytes = public_key[:32] + hc_bytes[32:] + xpub_hexstr = xpub_bytes.hex() + + child_xpub_hexstr = xpub_hexstr + return child_xpub_hexstr + + +# xprv_sign sign message +# xprv_hexstr length is 64 bytes. +# message_hexstr length is variable. +# signature_hexstr length is 64 bytes. +# You can get more test data from: https://gist.github.com/zcc0721/61a26c811a632623678e274cc7e5c10b +# test data 1: +# xprv_hexstr: c003f4bcccf9ad6f05ad2c84fa5ff98430eb8e73de5de232bc29334c7d074759d513bc370335cac51d77f0be5dfe84de024cfee562530b4d873b5f5e2ff4f57c +# xpub_hexstr: 1b0541a7664cee929edb54d9ef21996b90546918a920a77e1cd6015d97c56563d513bc370335cac51d77f0be5dfe84de024cfee562530b4d873b5f5e2ff4f57c +# message_hexstr: a6ce34eec332b32e42ef3407e052d64ac625da6f +# signature_hexstr: f02f5bb22d8b32f14e88059a786379c26256892f45cf64770c844d0c5de2e52c00307b7bb25fcbb18be13c339a2f511a7c015a8cf81ac681052efe8e50eff00e +# test data 2: +# xprv_hexstr: 008ce51e3b52ee03eb0ad96c55eb5c9fe8736410518b585a0b7f35b2ab48d24c166364ce19322721b7dec84442c3665d97d0e995ba4d01c0f4b19b841379ac90 +# xpub_hexstr: ead6415a077b91aa7de32e1cf63350f9351d0298f5accc2cf92ef9429bd1f86c166364ce19322721b7dec84442c3665d97d0e995ba4d01c0f4b19b841379ac90 +# message_hexstr: 68656c6c6f206279746f6d # value is: 'hello bytom' +# signature_hexstr: 1cc6b0f4031352ffd7a62540f13edddaaebf2df05db7a4926df5513129a8e85dcff1324545a024b16f958239ea67840ced3c2d57bb468dbf0e6cf1d1075f0b0f +# test data 3: +# xprv_hexstr: 88c0c40fb54ef9c1b90af8cce8dc4c9d54f915074dde93f79ab61cedae03444101ff37ac4a07869214c2735bba0175e001abe608db18538e083e1e44430a273b +# xpub_hexstr: cb22ce197d342d6bb440b0bf13ddd674f367275d28a00f893d7f0b10817690fd01ff37ac4a07869214c2735bba0175e001abe608db18538e083e1e44430a273b +# message_hexstr: 1246b84985e1ab5f83f4ec2bdf271114666fd3d9e24d12981a3c861b9ed523c6 +# signature_hexstr: ab18f49b23d03295bc2a3f2a7d5bb53a2997bed733e1fc408b50ec834ae7e43f7da40fe5d9d50f6ef2d188e1d27f976aa2586cef1ba00dd098b5c9effa046306 +def xprv_sign(xprv_hexstr, message_hexstr): + xprv_hexstr = xprv_to_expanded_private_key(xprv_hexstr)['expanded_private_key'] + xprv_bytes = bytes.fromhex(xprv_hexstr) + message_bytes = bytes.fromhex(message_hexstr) + data_bytes = xprv_bytes[32:64] + message_bytes + + message_digest = hashlib.sha512(data_bytes).digest() + message_digest = sc_reduce32(message_digest.hex().encode()) + message_digest = bytes.fromhex(message_digest.decode()) + message_digest_reduced = message_digest[0:32] + + scalar = decodeint(message_digest_reduced) + encoded_r = encodepoint(scalarmultbase(scalar)) + xpub_hexstr = xprv_to_xpub(xprv_hexstr)['xpub'] + xpub_bytes = bytes.fromhex(xpub_hexstr) + hram_digest_data = encoded_r + xpub_bytes[:32] + message_bytes + + hram_digest = hashlib.sha512(hram_digest_data).digest() + hram_digest = sc_reduce32(hram_digest.hex().encode()) + hram_digest = bytes.fromhex(hram_digest.decode()) + hram_digest_reduced = hram_digest[0:32] + + sk = xprv_bytes[:32] + s = sc_muladd(hram_digest_reduced.hex().encode(), sk.hex().encode(), message_digest_reduced.hex().encode()) + s = bytes.fromhex(s.decode()) + + signature_bytes = encoded_r + s + signature_hexstr = signature_bytes.hex() + return signature_hexstr + + +# xpub_verify verify signature +# xpub_hexstr length is 64 bytes. +# message_hexstr length is variable. +# signature_hexstr length is 64 bytes. +# You can get more test data from: https://gist.github.com/zcc0721/61a26c811a632623678e274cc7e5c10b +# test data 1: +# xprv_hexstr: c003f4bcccf9ad6f05ad2c84fa5ff98430eb8e73de5de232bc29334c7d074759d513bc370335cac51d77f0be5dfe84de024cfee562530b4d873b5f5e2ff4f57c +# xpub_hexstr: 1b0541a7664cee929edb54d9ef21996b90546918a920a77e1cd6015d97c56563d513bc370335cac51d77f0be5dfe84de024cfee562530b4d873b5f5e2ff4f57c +# message_hexstr: a6ce34eec332b32e42ef3407e052d64ac625da6f +# signature_hexstr: f02f5bb22d8b32f14e88059a786379c26256892f45cf64770c844d0c5de2e52c00307b7bb25fcbb18be13c339a2f511a7c015a8cf81ac681052efe8e50eff00e +# test data 2: +# xprv_hexstr: 008ce51e3b52ee03eb0ad96c55eb5c9fe8736410518b585a0b7f35b2ab48d24c166364ce19322721b7dec84442c3665d97d0e995ba4d01c0f4b19b841379ac90 +# xpub_hexstr: ead6415a077b91aa7de32e1cf63350f9351d0298f5accc2cf92ef9429bd1f86c166364ce19322721b7dec84442c3665d97d0e995ba4d01c0f4b19b841379ac90 +# message_hexstr: 68656c6c6f206279746f6d # value is: 'hello bytom' +# signature_hexstr: 1cc6b0f4031352ffd7a62540f13edddaaebf2df05db7a4926df5513129a8e85dcff1324545a024b16f958239ea67840ced3c2d57bb468dbf0e6cf1d1075f0b0f +# test data 3: +# xprv_hexstr: 88c0c40fb54ef9c1b90af8cce8dc4c9d54f915074dde93f79ab61cedae03444101ff37ac4a07869214c2735bba0175e001abe608db18538e083e1e44430a273b +# xpub_hexstr: cb22ce197d342d6bb440b0bf13ddd674f367275d28a00f893d7f0b10817690fd01ff37ac4a07869214c2735bba0175e001abe608db18538e083e1e44430a273b +# message_hexstr: 1246b84985e1ab5f83f4ec2bdf271114666fd3d9e24d12981a3c861b9ed523c6 +# signature_hexstr: ab18f49b23d03295bc2a3f2a7d5bb53a2997bed733e1fc408b50ec834ae7e43f7da40fe5d9d50f6ef2d188e1d27f976aa2586cef1ba00dd098b5c9effa046306 +def xpub_verify(xpub_hexstr, message_hexstr, signature_hexstr): + result = False + result = verify(xpub_to_public_key(xpub_hexstr)['public_key'], signature_hexstr, message_hexstr)['result'] + return result + + +def get_new_key(entropy_hexstr=None, mnemonic_hexstr=None): + if (entropy_hexstr is None) and (mnemonic_str is None): + entropy_hexstr = get_entropy() + mnemonic_str = get_mnemonic(entropy_hexstr) + if (entropy_hexstr is None) and (mnemonic_str is not None): + pass + if entropy_hexstr is not None: + mnemonic_str = get_mnemonic(entropy_hexstr) + seed_hexstr = get_seed(mnemonic_str) + root_xprv_hexstr = get_root_xprv(seed_hexstr) + xpub_hexstr = get_xpub(root_xprv_hexstr) + xprv_base64 = create_qrcode_base64(root_xprv_hexstr) + return { + "entropy": entropy_hexstr, + "mnemonic": mnemonic_str, + "seed": seed_hexstr, + "xprv": root_xprv_hexstr, + "xpub": xpub_hexstr, + "xprv_base64": xprv_base64 + } \ No newline at end of file diff --git a/pybtm/signature.py b/pybtm/signature.py new file mode 100644 index 0000000..e5fe969 --- /dev/null +++ b/pybtm/signature.py @@ -0,0 +1,38 @@ +import ed25519 + +# You can verify or get more test data from: https://gist.github.com/zcc0721/bfa5c34a49ddfcaf9fdc3374cecb1477 +# test data 1: +# private_key_str: 33c6e964cf64246fc37f26be46c7b783ef4364f9d4c69daa4ccd9d0fef5fcef1 +# public_key_str: b25690a0ccd290a3346fb412dfd342c5ce6134ef116e89b0642d7534e34df432 +# message_str: 68656c6c6f206279746f6d # value is: 'hello bytom' +# signature_str: dfb19c1892796ad9560eb61a065c016c82a7a81a42f2c3f69d20f44582262551b62fee6836c866e008c2cb37bba7e2045013f073ad7f69f5dd2a634929c3d406 +# test data 2: +# private_key_str: 0164f0d6bc1f063fc74f1010dc4c5393af40d215cc905884443ed0cfe2e2c1c4 +# public_key_str: 5faaee522735460654190609cab55f96edd44ea78e358d6a02ef769b0c9eb314 +# message_str: b435f948bd3748ede8f9d6f59728d669939e79c6c885667a5c138e05bbabde1de0dcfcbe0c6112022fbbf0da522f4e224a9c2381016380688b51886248b3156f +# signature_str: 18d29864775ff4ec0c78a477f57c5d4dd03526d55ba33bd6768acf3ca0cf7e41fe9c241a7bc550f4fa14a745fbe0155cb896f9e4d88c87337e6dc3a313c8d80b +# test data 3: +# private_key_str: 7eb40ebe8beee07dfbc645300f571948a9ce83191c28505e710b6900ec2531ed +# public_key_str: 026b5e22e282d07051203fb0596be140cf17f2532a31407f3b177faa74237cbe +# message_str: 48ec69c784c519b65d0e52badda3b7c25113a6b53b4c8e582abee3e2f9aab41514f15bd44c999f3d2ddae4bbab15baf9f4d82dde4f97aa5042cbcfdd8271530e +# signature_str: 691fe6fc51603adbac0db2f71f383e7039b6a031a2242da8fd6203f9c71e3b526d0cdace626811ee06797de21afebe54d0293027eb6b22b10c63d4dd0ab8790c +def sign(private_key_str, message_str): + signing_key = ed25519.SigningKey(bytes.fromhex(private_key_str)) + # signature = signing_key.sign(message_str.encode(), encoding='hex') + signature = signing_key.sign(bytes.fromhex(message_str), encoding='hex') + return { + "signature": signature.decode() + } + + +def verify(public_key_str, signature_str, message_str): + result = False + verifying_key = ed25519.VerifyingKey(public_key_str.encode(), encoding='hex') + try: + verifying_key.verify(signature_str.encode(), bytes.fromhex(message_str), encoding='hex') + result = True + except ed25519.BadSignatureError: + result = False + return { + "result": result + } diff --git a/pybtm/utils.py b/pybtm/utils.py new file mode 100644 index 0000000..3b170fb --- /dev/null +++ b/pybtm/utils.py @@ -0,0 +1,14 @@ +import qrcode +import pybase64 +from io import BytesIO + +# create_qrcode_base64 create qrcode, then encode it to base64 +# type(s) is str +def create_qrcode_base64(s): + img = qrcode.make(s) + buffered = BytesIO() + img.save(buffered, format="JPEG") + base64_str = pybase64.b64encode(buffered.getvalue()).decode("utf-8") + return { + "base64": base64_str + } \ No newline at end of file diff --git a/setup.py b/setup.py index d846802..3ca616f 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ with open("README.md", "r") as fh: setuptools.setup( name="pybtm", - version="0.0.8", + version="0.0.9", author="zcc0721", author_email="zcc0721@foxmail.com", description="Python3 implementation of the Bytom protocol.", -- 2.11.0