commit 1d77ece1388a859b39cde44ace057e9024723238
parent a1509e657d610aeb94ba4ce943561ca02a9b8e4e
Author: Mikolai Gütschow <mikolai.guetschow@tu-dresden.de>
Date: Tue, 7 Apr 2026 16:43:58 +0200
protocol: rename blind_coin to planchet
Diffstat:
2 files changed, 109 insertions(+), 112 deletions(-)
diff --git a/draft-guetschow-taler-protocol.md b/draft-guetschow-taler-protocol.md
@@ -465,9 +465,9 @@ for i in 0..n:
coinᵢ.priv = coin_seedᵢ[:32]
coinᵢ.pub = EdDSA-GetPub(coinᵢ.priv)
h_denomᵢ = SHA-512(uint32(0) | uint32(1) | denomᵢ.pub)
- blind_coinᵢ = RSA-FDH-Blind(SHA-512(coinᵢ.pub), blind_secretᵢ, denomᵢ.pub)
- h_planchetᵢ = SHA-512( SHA-512( denomᵢ.pub ) | uint32(0x1) | blind_coinᵢ )
-planchets = (⟨h_denomᵢ⟩, ⟨blind_coinᵢ⟩)
+ planchetᵢ = RSA-FDH-Blind(SHA-512(coinᵢ.pub), blind_secretᵢ, denomᵢ.pub)
+ h_planchetᵢ = SHA-512( SHA-512( denomᵢ.pub ) | uint32(0x1) | planchetᵢ )
+planchets = (⟨h_denomᵢ⟩, ⟨planchetᵢ⟩)
msg = Sign-Msg(WALLET_RESERVE_WITHDRAW,
( sum( ⟨denomᵢ.value⟩ ) | sum( ⟨denomᵢ.fee_withdraw⟩ )
| SHA-512( ⟨h_planchetᵢ⟩ ) | uint256(0x0) | uint32(0x0) | uint32(0x0) ))
@@ -477,11 +477,11 @@ sig = EdDSA-Sign(reserve.priv, msg)
~~~
(E1) coin issuance and signing (exchange)
-(⟨h_denomᵢ⟩, ⟨blind_coinᵢ⟩) = planchets
+(⟨h_denomᵢ⟩, ⟨planchetᵢ⟩) = planchets
for i in 0..n:
denomᵢ = Denom-Lookup(h_denomᵢ)
check denomᵢ known and not withdrawal-expired
- h_planchetᵢ = SHA-512( SHA-512( denomᵢ.pub ) | uint32(0x1) | blind_coinᵢ )
+ h_planchetᵢ = SHA-512( SHA-512( denomᵢ.pub ) | uint32(0x1) | planchetᵢ )
msg = Sign-Msg(WALLET_RESERVE_WITHDRAW,
( sum( ⟨denomᵢ.value⟩ ) | sum( ⟨denomᵢ.fee_withdraw⟩ )
| SHA-512( ⟨h_planchetᵢ⟩ ) | uint256(0x0) | uint32(0x0) | uint32(0x0) ))
@@ -491,7 +491,7 @@ total = sum( ⟨denomᵢ.value⟩ ) + sum( ⟨denomᵢ.fee_withdraw⟩ )
check reserve.balance >= total
persist reserve.balance -= total
for i in 0..n:
- blind_sigᵢ = RSA-FDH-Sign(blind_coinᵢ, denomᵢ.priv)
+ blind_sigᵢ = RSA-FDH-Sign(planchetᵢ, denomᵢ.priv)
persist withdrawal // todo: what exactly? should be checked first for replay?
~~~
@@ -774,8 +774,6 @@ where (for RSA, without age-restriction)
// todo: double-check incompatibility between h_denom and hash of denom used below
-// todo: rename blind_coin to planchet, here and in withdrawal, too?
-
{::comment}
// see TALER_EXCHANGE_get_melt_data
⟨batch_seedₖ⟩ // see TALER_refresh_expand_seed_to_kappa_batch_seeds
@@ -802,15 +800,15 @@ for k in 0..kappa:
blind_secretₖᵢ = HKDF("bks", planchet_seedₖᵢ, "", 32)
coinₖᵢ.priv = HKDF("coin", planchet_seedₖᵢ, "", 32)
coinₖᵢ.pub = EdDSA-GetPub(coinₖᵢ.priv)
- blind_coinₖᵢ = RSA-FDH-Blind(SHA-512(coinₖᵢ.pub), blind_secretₖᵢ, denomᵢ.pub)
- h_planchetₖᵢ = SHA-512( SHA-512( denomᵢ.pub ) | uint32(0x1) | blind_coinₖᵢ )
+ planchetₖᵢ = RSA-FDH-Blind(SHA-512(coinₖᵢ.pub), blind_secretₖᵢ, denomᵢ.pub)
+ h_planchetₖᵢ = SHA-512( SHA-512( denomᵢ.pub ) | uint32(0x1) | planchetₖᵢ )
h_planchetsₖ = SHA-512( ⟨h_planchetₖᵢ⟩ )
value = coin.denom.fee_refresh + sum( ⟨denomᵢ.value⟩ ) + sum( ⟨denomᵢ.fee_withdraw⟩ )
commitment = SHA-512( refresh_seed | uint256(0x0) | coin.pub | value
| SHA-512( ⟨h_planchetsₖ⟩ ) )
for i in 0..n:
h_denomᵢ = SHA-512(uint32(0) | uint32(0x1) | denomᵢ.pub)
-planchets = (⟨h_denomᵢ⟩, ⟨blind_coinₖᵢ⟩, ⟨transferₖᵢ.pub⟩))
+planchets = (⟨h_denomᵢ⟩, ⟨planchetₖᵢ⟩, ⟨transferₖᵢ.pub⟩))
msg = Sign-Msg(WALLET_COIN_MELT,
( commitment | coin.h_denom | uint256(0x0)
| value | denom.fee_refresh ))
@@ -832,7 +830,7 @@ denom = Denom-Lookup(coin.h_denom)
check denom known and not refresh-expired
check RSA-FDH-Verify(SHA-512(coin.pub), coin.sig, denom.pub)
check coin.pub known and dirty
-(⟨h_denomᵢ⟩, ⟨blind_coinₖᵢ⟩, ⟨transferₖᵢ.pub⟩)) = planchets
+(⟨h_denomᵢ⟩, ⟨planchetₖᵢ⟩, ⟨transferₖᵢ.pub⟩)) = planchets
for i in 0..n:
denomᵢ = Denom-Lookup(h_denomᵢ)
check denomᵢ known and not withdraw-expired
@@ -842,7 +840,7 @@ check coin.value >= value
persist coin.value -= value
for k in 0..kappa:
for i in 0..n:
- h_planchetₖᵢ = SHA-512( SHA-512( denomᵢ.pub ) | uint32(0x1) | blind_coinₖᵢ )
+ h_planchetₖᵢ = SHA-512( SHA-512( denomᵢ.pub ) | uint32(0x1) | planchetₖᵢ )
h_planchetsₖ = SHA-512( ⟨h_planchetₖᵢ⟩ )
commitment = SHA-512( refresh_seed | uint256(0x0) | coin.pub | value
| SHA-512( ⟨h_planchetsₖ⟩ ) )
@@ -854,7 +852,7 @@ check EdDSA-Verify(coin.pub, msg, sig)
if refresh-record not found:
ɣ = 0..kappa at random
for i in 0..n:
- blind_sigᵢ = RSA-FDH-Sign(blind_coinᵧᵢ, denomᵧᵢ.priv)
+ blind_sigᵢ = RSA-FDH-Sign(planchetᵧᵢ, denomᵧᵢ.priv)
persist refresh-record = (commitment, ɣ, ⟨blind_sigᵢ⟩, h_planchetsᵧ)
msg = Sign-Msg(EXCHANGE_CONFIRM_MELT,
( commitment | uint32(ɣ) ))
@@ -902,8 +900,8 @@ for k in 0..kappa and k != ɣ:
blind_secretₖᵢ = HKDF("bks", planchet_seedₖᵢ, "", 32)
coinₖᵢ.priv = HKDF("coin", planchet_seedₖᵢ, "", 32)
coinₖᵢ.pub = EdDSA-GetPub(coinₖᵢ.priv)
- blind_coinₖᵢ = RSA-FDH-Blind(SHA-512(coinₖᵢ.pub), blind_secretₖᵢ, denomᵢ.pub)
- h_planchetₖᵢ = SHA-512( SHA-512( denomᵢ.pub ) | uint32(0x1) | blind_coinₖᵢ )
+ planchetₖᵢ = RSA-FDH-Blind(SHA-512(coinₖᵢ.pub), blind_secretₖᵢ, denomᵢ.pub)
+ h_planchetₖᵢ = SHA-512( SHA-512( denomᵢ.pub ) | uint32(0x1) | planchetₖᵢ )
h_planchetsₖ = SHA-512( ⟨h_planchetₖᵢ⟩ )
value = coin.denom.fee_refresh + sum( denomᵢ.value ) + sum( denomᵢ.fee_withdraw )
commitment' = SHA-512( refresh_seed | uint256(0x0) | coin.pub | value
diff --git a/draft-guetschow-taler-protocol.xml b/draft-guetschow-taler-protocol.xml
@@ -446,9 +446,9 @@ for i in 0..n:
coinᵢ.priv = coin_seedᵢ[:32]
coinᵢ.pub = EdDSA-GetPub(coinᵢ.priv)
h_denomᵢ = SHA-512(uint32(0) | uint32(1) | denomᵢ.pub)
- blind_coinᵢ = RSA-FDH-Blind(SHA-512(coinᵢ.pub), blind_secretᵢ, denomᵢ.pub)
- h_planchetᵢ = SHA-512( SHA-512( denomᵢ.pub ) | uint32(0x1) | blind_coinᵢ )
-planchets = (⟨h_denomᵢ⟩, ⟨blind_coinᵢ⟩)
+ planchetᵢ = RSA-FDH-Blind(SHA-512(coinᵢ.pub), blind_secretᵢ, denomᵢ.pub)
+ h_planchetᵢ = SHA-512( SHA-512( denomᵢ.pub ) | uint32(0x1) | planchetᵢ )
+planchets = (⟨h_denomᵢ⟩, ⟨planchetᵢ⟩)
msg = Sign-Msg(WALLET_RESERVE_WITHDRAW,
( sum( ⟨denomᵢ.value⟩ ) | sum( ⟨denomᵢ.fee_withdraw⟩ )
| SHA-512( ⟨h_planchetᵢ⟩ ) | uint256(0x0) | uint32(0x0) | uint32(0x0) ))
@@ -457,11 +457,11 @@ sig = EdDSA-Sign(reserve.priv, msg)
<artwork><![CDATA[
(E1) coin issuance and signing (exchange)
-(⟨h_denomᵢ⟩, ⟨blind_coinᵢ⟩) = planchets
+(⟨h_denomᵢ⟩, ⟨planchetᵢ⟩) = planchets
for i in 0..n:
denomᵢ = Denom-Lookup(h_denomᵢ)
check denomᵢ known and not withdrawal-expired
- h_planchetᵢ = SHA-512( SHA-512( denomᵢ.pub ) | uint32(0x1) | blind_coinᵢ )
+ h_planchetᵢ = SHA-512( SHA-512( denomᵢ.pub ) | uint32(0x1) | planchetᵢ )
msg = Sign-Msg(WALLET_RESERVE_WITHDRAW,
( sum( ⟨denomᵢ.value⟩ ) | sum( ⟨denomᵢ.fee_withdraw⟩ )
| SHA-512( ⟨h_planchetᵢ⟩ ) | uint256(0x0) | uint32(0x0) | uint32(0x0) ))
@@ -471,7 +471,7 @@ total = sum( ⟨denomᵢ.value⟩ ) + sum( ⟨denomᵢ.fee_withdraw⟩ )
check reserve.balance >= total
persist reserve.balance -= total
for i in 0..n:
- blind_sigᵢ = RSA-FDH-Sign(blind_coinᵢ, denomᵢ.priv)
+ blind_sigᵢ = RSA-FDH-Sign(planchetᵢ, denomᵢ.priv)
persist withdrawal // todo: what exactly? should be checked first for replay?
]]></artwork>
<artwork><![CDATA[
@@ -730,7 +730,6 @@ knows coin |
<t>where (for RSA, without age-restriction)</t>
<t>// todo: document ECDH-EdDSA(priv, pub) (returns hash512)</t>
<t>// todo: double-check incompatibility between h_denom and hash of denom used below</t>
- <t>// todo: rename blind_coin to planchet, here and in withdrawal, too?</t>
<artwork><![CDATA[
(W1) coin melting (wallet)
@@ -745,15 +744,15 @@ for k in 0..kappa:
blind_secretₖᵢ = HKDF("bks", planchet_seedₖᵢ, "", 32)
coinₖᵢ.priv = HKDF("coin", planchet_seedₖᵢ, "", 32)
coinₖᵢ.pub = EdDSA-GetPub(coinₖᵢ.priv)
- blind_coinₖᵢ = RSA-FDH-Blind(SHA-512(coinₖᵢ.pub), blind_secretₖᵢ, denomᵢ.pub)
- h_planchetₖᵢ = SHA-512( SHA-512( denomᵢ.pub ) | uint32(0x1) | blind_coinₖᵢ )
+ planchetₖᵢ = RSA-FDH-Blind(SHA-512(coinₖᵢ.pub), blind_secretₖᵢ, denomᵢ.pub)
+ h_planchetₖᵢ = SHA-512( SHA-512( denomᵢ.pub ) | uint32(0x1) | planchetₖᵢ )
h_planchetsₖ = SHA-512( ⟨h_planchetₖᵢ⟩ )
value = coin.denom.fee_refresh + sum( ⟨denomᵢ.value⟩ ) + sum( ⟨denomᵢ.fee_withdraw⟩ )
commitment = SHA-512( refresh_seed | uint256(0x0) | coin.pub | value
| SHA-512( ⟨h_planchetsₖ⟩ ) )
for i in 0..n:
h_denomᵢ = SHA-512(uint32(0) | uint32(0x1) | denomᵢ.pub)
-planchets = (⟨h_denomᵢ⟩, ⟨blind_coinₖᵢ⟩, ⟨transferₖᵢ.pub⟩))
+planchets = (⟨h_denomᵢ⟩, ⟨planchetₖᵢ⟩, ⟨transferₖᵢ.pub⟩))
msg = Sign-Msg(WALLET_COIN_MELT,
( commitment | coin.h_denom | uint256(0x0)
| value | denom.fee_refresh ))
@@ -767,7 +766,7 @@ denom = Denom-Lookup(coin.h_denom)
check denom known and not refresh-expired
check RSA-FDH-Verify(SHA-512(coin.pub), coin.sig, denom.pub)
check coin.pub known and dirty
-(⟨h_denomᵢ⟩, ⟨blind_coinₖᵢ⟩, ⟨transferₖᵢ.pub⟩)) = planchets
+(⟨h_denomᵢ⟩, ⟨planchetₖᵢ⟩, ⟨transferₖᵢ.pub⟩)) = planchets
for i in 0..n:
denomᵢ = Denom-Lookup(h_denomᵢ)
check denomᵢ known and not withdraw-expired
@@ -777,7 +776,7 @@ check coin.value >= value
persist coin.value -= value
for k in 0..kappa:
for i in 0..n:
- h_planchetₖᵢ = SHA-512( SHA-512( denomᵢ.pub ) | uint32(0x1) | blind_coinₖᵢ )
+ h_planchetₖᵢ = SHA-512( SHA-512( denomᵢ.pub ) | uint32(0x1) | planchetₖᵢ )
h_planchetsₖ = SHA-512( ⟨h_planchetₖᵢ⟩ )
commitment = SHA-512( refresh_seed | uint256(0x0) | coin.pub | value
| SHA-512( ⟨h_planchetsₖ⟩ ) )
@@ -789,7 +788,7 @@ check EdDSA-Verify(coin.pub, msg, sig)
if refresh-record not found:
ɣ = 0..kappa at random
for i in 0..n:
- blind_sigᵢ = RSA-FDH-Sign(blind_coinᵧᵢ, denomᵧᵢ.priv)
+ blind_sigᵢ = RSA-FDH-Sign(planchetᵧᵢ, denomᵧᵢ.priv)
persist refresh-record = (commitment, ɣ, ⟨blind_sigᵢ⟩, h_planchetsᵧ)
msg = Sign-Msg(EXCHANGE_CONFIRM_MELT,
( commitment | uint32(ɣ) ))
@@ -820,8 +819,8 @@ for k in 0..kappa and k != ɣ:
blind_secretₖᵢ = HKDF("bks", planchet_seedₖᵢ, "", 32)
coinₖᵢ.priv = HKDF("coin", planchet_seedₖᵢ, "", 32)
coinₖᵢ.pub = EdDSA-GetPub(coinₖᵢ.priv)
- blind_coinₖᵢ = RSA-FDH-Blind(SHA-512(coinₖᵢ.pub), blind_secretₖᵢ, denomᵢ.pub)
- h_planchetₖᵢ = SHA-512( SHA-512( denomᵢ.pub ) | uint32(0x1) | blind_coinₖᵢ )
+ planchetₖᵢ = RSA-FDH-Blind(SHA-512(coinₖᵢ.pub), blind_secretₖᵢ, denomᵢ.pub)
+ h_planchetₖᵢ = SHA-512( SHA-512( denomᵢ.pub ) | uint32(0x1) | planchetₖᵢ )
h_planchetsₖ = SHA-512( ⟨h_planchetₖᵢ⟩ )
value = coin.denom.fee_refresh + sum( denomᵢ.value ) + sum( denomᵢ.fee_withdraw )
commitment' = SHA-512( refresh_seed | uint256(0x0) | coin.pub | value
@@ -944,7 +943,7 @@ for i in 0..n:
<refcontent>National Institute of Standards and Technology (U.S.)</refcontent>
</reference>
</references>
- <?line 958?>
+ <?line 956?>
<section anchor="change-log">
<name>Change log</name>
@@ -1052,87 +1051,87 @@ EajICvRouIyqtrcEMzOykwpB4zWRcBTUmNDG9k5MHim0O/jV3tPd4ycHXcgT
0q6iU5fyrCYkqYAZ7xIb6hAVZv2Ay7SaaCbY5UDsDDI0jaO+24dhqkmDgqbF
aJUryYVJ0FHOC6vsYgPr1oOdXJ4KMBbKso8zbDUatE8LR4KH3ANToVaIZYLk
1+rF1nW2IQ445CLjYHvH0/uUNuq07YIVKC66Nkd6s73VfitHVyFmGaS9vVUA
-yfpaaZ7w9GXWt83WOOa4q2JWY5ednEzLyPw28ToPb7N+jrDs0igCi3Ul1ZuB
-Da6TFydZn+t03FUesYhUfmG2YAaOrUvCsogVcFU5WKxVgqXPpwx2vs607c9T
-RMicElw20JWA17vPnx+cdU8OTg9OfnnQfX149nT/ZPd1nayljdmrXQj/yQxh
-yoD4zD2FLE5rBgFZwtLqCRKSBhVUT2q/d+uyVZj23LdaTS58CN7TgpAOOoDz
-oqQhzCQp0HIHbqu8CPRnTQrC2Jru8xpkyNw+XjrPo+g8m9p5x0gTYRg0LGZZ
-Qq1xj4yhT5CD+pDA3oXs/O3LgSCikAO5RFIIP9V6iYJUzvbZr/ewOpZmCYvO
-sXKARBeFT0tUKDpL5/vNOvMtDNnouwGJ3g8dUQPR9rgM4CiAOcEyozjDIJEC
-FHhr2h0yhWosw7VrV3iBmyb4pYtO+0eWQEATeMKlAvpYHqGdzogMOLjAnf1o
-aFZVAJd7o0rfgkgJ9S2vPZrTW8OUCvKWFsiqzbIxbkU/8qFUT0AsV1R4rMMw
-TdsSZjWTlLPCU1rtKvpkN4i5681Ut9z7UW+TeimO57Gre/KgXrEAGPWxSJ2w
-HtZUxd5aYw8bMQhXQujAjVHVm/AYzVtquUMMsQaB60+QTb6ugvfCCOSu17AU
-AmovOx3dgWBMRjZUlNNWE6Mw3w1qQE9awGLiyJ//U6H8R49UpZHGq65awpAD
-HtO5seVVxLoMwqmYl01o/ScQ2/1EyRIb2T3zO2rL9x1W1ONejVEBEag3GIvz
-ToquqDNADzDxGS7OpXQGJ9DzBEWXaxeSTbRWqcrVuCs6wgAtKVAfcB3gCS3c
-kYNrWB7nEwGxgHxyI5Ouf8q90BI63w5tZinrFgK1SOjSXs6KJc0EtGpMlqWc
-UK1oqyvMSLo0+mJVgGsk/0fgOYUimGXGzzR+BUYLU31m/+uJgwc1WJMdP96D
-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
+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
-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
+/m3m9JQpNvtYRHfUTEx8Fm0MEylGrnoLWbYU54oazd3MthpuMR+uuaNMUY7O
+QN1Weey2iwPMNiJu0zrcfXVsdXEAkx9Nxb+f4sB+hfEw3TuqGYWIzHDeVwYf
+C4nSXCL1QXQg00K7bJlrP6dk6cAgh6FH5r6OYoKrp9YwUt385npJ76IlbjyK
+awZTfrhkU0gpyF+5M0T2rLaFsNK5LV3skMkQFTzMAaF/2l9QgWce9C1ODu46
+C1qZ/GipLmQ/+d1F6Y+a9I0TnIow0dhwoNKbuklaihlvcdOC5LQAEUdo1L6S
+4r6FIoxjwCgIJU4QeEaxZyXQt5cFeLrTOJNAZTJatM1pjgn+hT2n13pnJOj1
+48OTo6JIlARCM9ukstwoVM3dYgWpLBFVvH+/VoJTsTupyD+1PakgHlXb0Aoh
+8ZyhQle1X+WqTMN9w1rc5+CI9idVDFlairhjflRoZzFcmU/iTvgQ3O8Y3ywk
+rtZI4n42R69U8gNW/lqf2w7WVu65Z8a6PqE74eKNP+sMfJMxyzfWaLSgZXl8
+1sQ5zK2SLVrKJBNfVd0i61xfhq0UTNoBXX2W5mdwkkZx5Xrpz8idTNy81iqP
+m4N83Pq5mmviV4HxonVTZv/5jwvTIvrcSW60Qv71zgH1Tj7+jo7vr95Hc5Mx
+yzdWTnBhS3NY1hRHQJx5jVuibpOJn2KFkAoM6gwJKdFf/+M/9R6CL6w619EX
+WuVTs7rdisHdaAbx7h8Hz/KW5RurWuQtr3nwbP5U+sEeZB0UGdkiNsV0Ak+V
+ibePYnkBX9ddaGqs2UFCGU2mIG59P8Cf5Ojz9ILzUG2YJsOt3i0n7lBNu8+D
+6MKyrtptlFza2Az9gw6Wj1KNeNpF7e5isQPXA6mwaGgrK7RTLpHTy1sJrJtG
+3XN3OnW7edMEe1J5DPRjxE5L+8t7wF5VBwI3TZ8p0A4okeBOAqKuOH4k3pBs
+nEeid6TkP1VQl29ArbMyYgCKxxDonSUyUMwPSQigItZ0Loq/69Kb03PQBGCL
+gCJA7coXYGnArjhmlogODNtSSRtkUQ5jIWn/8qePAi8MRq/azQ/GHpFCmGce
+dMyDmdLRtCquyzRoQzZzRL2ZeLtRL0VG+gBfnZ1/rUo057JEQ6KBZZrFElEe
+S4E5cluKc85nOGoBSUjI4Fb4Nb4SmLG5ohCr4nLpvFoFOiIFSsa4915yvmOq
+cEUTNX9RJcgPrilEqw/ymUPoc3yLDu8Vj+8V+9zonyNtKkYVFBL0EVUyA2vd
+HO9ft3310b85MpZUaNkpvrzn0kE+hUq5GmOey9L9f/LRLNlD8ZAgqXNnwdkp
+rX7QSNR5xHHJBo1I1S0pzlXnlq59qik3EQZCBZWeO8OlpBIuabjKgwOLjoYl
+0gzUWEXBdd1znZLIRdatf2pSk7heZTuyPgY0i87TUV306OC5rrcYFJSkUR60
+okIqKaZwL3CzqvpkGECqPBUOMEmJoPSk0WgYZ5dMRy8CDdNfW+QJDp6Ckwg9
+sA7kppda/7USO7M6r05fzZXG87q4URUvlcSVtVYnJVfWWY0iq1FhFVKRF1dJ
+ZPORPNxRtOJ46FqC8tkOj2qCkAz94m7tAiGkBupIRTeIqcvU4olZoc7L0+JZ
+pdOu8Ks/H7v7Ra3iF7A7C9ZAyhVWKot04R/KfEByrJVVLDgYSXrNgqi4+JSk
+eYgvvkKG//mP+BJ7KRJ4Rk5EjtWysd5h2Y+mR/9oxgz58dwCQp1iWQHnN5/c
+1k0Rgn5Xl+QX8kkK65//WH3mfeFiQ8F8y1g+iQfNwO83VaOuO/XpBRZUVGkM
+2kzYd5GFDfEXB8ZgPFa2Nioz2AlQDg+mdvVvXS5NEyrLU3muoLaLGtuRyNZ9
+OkVBiq63TFCWBIAK8OXFHN1n4fz0vOEik3zOvurAsCiX5RoUTKGQSixmnul+
+RS9reOGF5aLCCw/WFOK1VBiwFW/h75pqIuhCVFhNo39kZ//Izv6es7NiCJbH
+X5XBVyH2+MUtBx9rRR8qxMsDoI7x7RfG24bic0fZv09xUiU3YxjBbnS+3Ml8
+yosqPv5lnXdViACi+FKIj5WCuMbmj4/l/R8Kh0XvrfhobJBZ9OoKfcD/oySM
+2v8u17dx/zEucsMU6CVdym3/qNbGIfoSS+Nwka+My6eDCPwBPsWL0tPX4jVX
+aeSIK/YyAynPX3RxsXXhTDNzuX1RsyCYaxYEhWb4s5VZjGXpPXxRuifPPyXy
+x4z36ceM77FDfCdzGeI4CvFnD3Glou9C/ou/lyreuxBEI/y2O8CYA8R2JH41
++6otfnqXe52NIRCQb3wojENvQKNfvr2g38aj3ycSO7HopezylbbiB6bZY+7R
+rxsf0U88xXjszTrwskH+fq8TnnA3HoyZ/ejo0WPx02T5iTd8FyjOCYWP4wXt
+vUga1v8DGlTYQrZ8AAA=
-->