This repository has been archived by the owner on Jun 15, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 81
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Edit account age witness for Asciidoc style
And remove BIP-style header; we'll move away from this approach, as we're not really ready or in need of this level of formality.
- Loading branch information
Showing
1 changed file
with
51 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,17 @@ | ||
== Payment account age witness | ||
:toc: | ||
= Payment account age witness | ||
:toc: left | ||
:sectanchors: | ||
Manfred Karrer <mk@nucleo.io> | ||
2017-09-14 | ||
|
||
.... | ||
Bisq-IP: 2 | ||
Layer: Exchange | ||
Title: Payment account age witness | ||
Author: Manfred Karrer <[email protected]> | ||
Comments-Summary: No comments yet. | ||
Comments-URI: Bisq Forum thread [1] | ||
Status: Draft | ||
Created: 2017-09-14 | ||
License: GPL Version 3 | ||
.... | ||
[abstract] | ||
This proposal describes a protection mechanism against a fraud scheme in which a criminal has obtained illegal access of a bank account and tries to buy bitcoin with the stolen funds. The victim of the stolen bank account will likely contact his bank once he discovers the fraud and initiate a bank chargeback. The bitcoin seller would in such a case be at risk to lose the received payment in Fiat currency. We *assume* that the criminal who has access to the bank account intends to take out the funds of that account as quickly as possible as well as that he intends to do that in a few large transactions because with each transaction the risk increases that the fraud gets discovered and the account gets frozen. With the *trade amount limits* in Bisq we have already a protection against that fraud scheme but we would like to increase the security by adding a verification scheme for the *age of the bank account*. To protect users privacy we use a hashing scheme and only the other trading peer - who will receive anyway the payment details during the trade process - is able to verify that the provided hash in the offer matches the real account data. | ||
|
||
== Abstract | ||
|
||
This proposal describes a protection mechanism against a fraud scheme in which a criminal has obtained illegal access of a bank account and tries to buy Bitcoin with the stolen funds. The victim of the stolen bank account will likely contact his bank once he discovers the fraud and initiate a bank chargeback. The Bitcoin seller would in such a case be at risk to lose the received payment in Fiat currency. | ||
|
||
We *assume* that the criminal who has access to the bank account intends to take out the funds of that account as quickly as possible as well as that he intends to do that in a few large transactions because with each transaction the risk increases that the fraud gets discovered and the account gets frozen. | ||
|
||
With the *trade amount limits* in Bisq we have already a protection against that fraud scheme but we would like to increase the security by adding a verification scheme for the *age of the bank account*. | ||
|
||
To protect users privacy we use a hashing scheme and only the other trading peer - who will receive anyway the payment details during the trade process - is able to verify that the provided hash in the offer matches the real account data. | ||
NOTE: This proposal was implemented in Bisq v0.6.0 | ||
|
||
== Overview | ||
|
||
The initial idea for this scheme was already discussed on the link:https://forum.bisq.io/t/new-requirement-for-payment-accounts-with-chargeback-risk/2376/65[Bisq Forum [1\]]. | ||
The initial idea for this scheme was already discussed on the Bisq Forum footnote:[https://forum.bisq.io/t/new-requirement-for-payment-accounts-with-chargeback-risk/2376/65] footnote:[https://forum.bisq.io/t/payment-account-age-based-trade-amount-limits/2948]. | ||
|
||
This proposal is only relevant for Fiat payment accounts as with Altcoin accounts there is no risk for chargeback. | ||
|
||
|
@@ -49,10 +35,11 @@ When a user set up a Fiat payment account (e.g. SEPA, Zelle,...) he publishes an | |
|
||
The AccountAgeWitness object contains a hash and the date of publishing. | ||
|
||
[source,java] | ||
---- | ||
// AccountAgeWitness class contains: | ||
private final byte[] hash; // Ripemd160(Sha256(ageWitnessInputData, salt and pubKey)); 20 bytes | ||
private final long date; // 8 byte | ||
// AccountAgeWitness class contains: | ||
private final byte[] hash; // Ripemd160(Sha256(ageWitnessInputData, salt and pubKey)); 20 bytes | ||
private final long date; // 8 byte | ||
---- | ||
|
||
The hash is created with Sha256 and wrapped into a Ripemd160 hash to get a 20 byte hash instead of 32 bytes as it would be with Sha256. Input for the hash is a concatenation of the ageWitnessInputData (e.g. IBAN), a 256 bit salt and the pubKey. | ||
|
@@ -66,42 +53,43 @@ That AccountAgeWitness data structure results in 28 bytes per item but as we use | |
|
||
__Note: If the data would become too large we can consider a time to live mechanism where AccountAgeWitness objects need to get triggered with a refresh message to stay active. That way outdated objects which have not received any TTL signal since a long period (e.g. 6 months) would get pruned.__ | ||
|
||
[source,java] | ||
---- | ||
// class AccountAgeWitnessService | ||
public AccountAgeWitness getMyWitness(PaymentAccountPayload paymentAccountPayload) { | ||
byte[] accountInputDataWithSalt = Utilities.concatenateByteArrays(paymentAccountPayload.getAgeWitnessInputData(), | ||
paymentAccountPayload.getSalt()); | ||
byte[] hash = Hash.getSha256Ripemd160hash(Utilities.concatenateByteArrays(accountInputDataWithSalt, | ||
keyRing.getPubKeyRing().getSignaturePubKeyBytes())); | ||
long date = new Date().getTime(); | ||
return new AccountAgeWitness(hash, date); | ||
} | ||
// getAgeWitnessInputData at example class SepaAccount | ||
public byte[] getAgeWitnessInputData() { | ||
// We don't add holderName because we don't want to break age validation if the user recreates an account with | ||
// slight changes in holder name (e.g. add or remove middle name) | ||
return super.getAgeWitnessInputData(ArrayUtils.addAll(iban.getBytes(Charset.forName("UTF-8")), | ||
bic.getBytes(Charset.forName("UTF-8")))); | ||
} | ||
// CountryBasedPaymentAccountPayload super class | ||
@Override | ||
protected byte[] getAgeWitnessInputData(byte[] data) { | ||
return super.getAgeWitnessInputData(ArrayUtils.addAll(countryCode.getBytes(Charset.forName("UTF-8")), data)); | ||
} | ||
// PaymentAccountPayload base class | ||
protected byte[] getAgeWitnessInputData(byte[] data) { | ||
return ArrayUtils.addAll(paymentMethodId.getBytes(Charset.forName("UTF-8")), data); | ||
} | ||
// Getting salt from CryptoUtils, called from PaymentAccountPayload constructor with size 32 | ||
public static byte[] getRandomBytes(int size) { | ||
byte[] bytes = new byte[size]; | ||
new SecureRandom().nextBytes(bytes); | ||
return bytes; | ||
} | ||
// class AccountAgeWitnessService | ||
public AccountAgeWitness getMyWitness(PaymentAccountPayload paymentAccountPayload) { | ||
byte[] accountInputDataWithSalt = Utilities.concatenateByteArrays(paymentAccountPayload.getAgeWitnessInputData(), | ||
paymentAccountPayload.getSalt()); | ||
byte[] hash = Hash.getSha256Ripemd160hash(Utilities.concatenateByteArrays(accountInputDataWithSalt, | ||
keyRing.getPubKeyRing().getSignaturePubKeyBytes())); | ||
long date = new Date().getTime(); | ||
return new AccountAgeWitness(hash, date); | ||
} | ||
// getAgeWitnessInputData at example class SepaAccount | ||
public byte[] getAgeWitnessInputData() { | ||
// We don't add holderName because we don't want to break age validation if the user recreates an account with | ||
// slight changes in holder name (e.g. add or remove middle name) | ||
return super.getAgeWitnessInputData(ArrayUtils.addAll(iban.getBytes(Charset.forName("UTF-8")), | ||
bic.getBytes(Charset.forName("UTF-8")))); | ||
} | ||
// CountryBasedPaymentAccountPayload super class | ||
@Override | ||
protected byte[] getAgeWitnessInputData(byte[] data) { | ||
return super.getAgeWitnessInputData(ArrayUtils.addAll(countryCode.getBytes(Charset.forName("UTF-8")), data)); | ||
} | ||
// PaymentAccountPayload base class | ||
protected byte[] getAgeWitnessInputData(byte[] data) { | ||
return ArrayUtils.addAll(paymentMethodId.getBytes(Charset.forName("UTF-8")), data); | ||
} | ||
// Getting salt from CryptoUtils, called from PaymentAccountPayload constructor with size 32 | ||
public static byte[] getRandomBytes(int size) { | ||
byte[] bytes = new byte[size]; | ||
new SecureRandom().nextBytes(bytes); | ||
return bytes; | ||
} | ||
---- | ||
|
||
|
||
|
@@ -113,7 +101,7 @@ The AccountAgeWitness data will be distributed in the P2P network and stored loc | |
|
||
When a node receives an AccountAgeWitness object it verifies that the tradeDate is not older or newer than 1 day compared with the local time of the node, otherwise it will reject the object. The date check is only done when receiving the data via the P2P network broadcasting, otherwise we could not fill up our initial map received form the seed node with the past distributed AccountAgeWitness objects. | ||
|
||
_Note: There is no date check for the data we receive from seed nodes. This is in the current state not an issue because the seed nodes are bonded with BSQ against abuse but in future improvements we would like to distribute more functions from the seed node to ordinary nodes and then there is a security issue with that._ | ||
NOTE: There is no date check for the data we receive from seed nodes. This is in the current state not an issue because the seed nodes are bonded with BSQ against abuse but in future improvements we would like to distribute more functions from the seed node to ordinary nodes and then there is a security issue with that. | ||
|
||
|
||
=== Offer | ||
|
@@ -134,7 +122,7 @@ When a trader takes an offer both users are exchanging in the trade process the | |
5. Verify if signature of the predefined input data (offer ID or preparedDepositTx) is correct using the peers pubKey. | ||
|
||
|
||
_Note: By using offer ID and preparedDepositTx for the nonce we avoid the need for a challenge protocol. We have chosen data which are defined by the other peer so they cannot be manipulated._ | ||
NOTE: By using offer ID and preparedDepositTx for the nonce we avoid the need for a challenge protocol. We have chosen data which are defined by the other peer so they cannot be manipulated. | ||
|
||
|
||
== Attempts of gaming the scheme | ||
|
@@ -187,11 +175,5 @@ To fade in that feature we use a date based approach. | |
|
||
Offers which are not containing the accountAgeWitness hash (created before v.0.6) will become invalid after February 2018. That is required because we need to prevent that it is possible to circumvent the account age verification scheme. | ||
|
||
|
||
_Implementation detail: + | ||
The trade amount limit is part of the OfferPayload so it is flexible with changes in updates and the value at offer creation time will be taken for both traders even if the hard coded value in the application would have been changed in an update and one of the traders have not updated yet. The reduction factors and the time schedule is not part of the offer and cannot be changed in future updates without breaking backward compatibility. We consider that risk acceptable and choose not to add that data to the offer to not overload the offer with details._ | ||
|
||
|
||
== References | ||
|
||
link:https://forum.bisq.io/t/payment-account-age-based-trade-amount-limits/2948[[1\] Forum thread] |