Bitcoin Forum
November 09, 2024, 05:53:04 AM *
News: Latest Bitcoin Core release: 28.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1] 2 »  All
  Print  
Author Topic: Payment Address Validation  (Read 1767 times)
AliceWonderMiscreations (OP)
Full Member
***
Offline Offline

Activity: 182
Merit: 107


View Profile WWW
February 22, 2017, 06:30:51 AM
 #1

I'm currently working on a payment system. Why not just BitPay or similar? Because some of the content sold may violate their rules, either now or in the future, I honestly don't know and don't care because while the content is not illegal, there is a good chance now or in the future BitPay (or others) will tell me I can't use their service with it. It does violate PayPal rules, and only some credit card processing companies will allow it - and then only with really high TX fee.

Anyway private addresses do not belong anywhere on the server. So the payment addresses have to be generated elsewhere (on an offline computer) and then inserted into a database the web application fetches them from.

That opens it up to the possibility of SQL injection attack - meaning a hacker could inject their own payment addresses into the database.

So to combat that, the master ECDSA key used to generate all the payment addresses is used to create a signature for each payment address.

The web application then grabs both the payment address and the signature and uses the public key from the master ECDSA to verify the payment address before it goes on the invoice for the customer to pay.

That got me thinking - why isn't something like that already part of bitcoin?

What I mean is - a payment address includes a signature as part of the bitcoin uri

The client then fetches the public key used to create the signature via DNS where it is secured by DNSSEC (similar to how DANE works with TLSA records) and then verifies the payment address is valid.

Something like that wouldn't require any changes to the bitcoin protocol itself, just client support. Clients that do not want to do it don't can just ignore the signature.

It would be a form of two-factor authentication so that the end user can verify the address they are paying to does in fact belong to the website they are making a payment to and is not hacker injected.

I hereby reserve the right to sometimes be wrong
Abdussamad
Legendary
*
Offline Offline

Activity: 3682
Merit: 1580



View Profile
February 22, 2017, 06:58:54 AM
Merited by ABCbits (1)
 #2

addresses are not private. the private portion is called the private key. in  order to generate addresses without exposing the private key you simply install the wallet's extended public key aka xpub and master public key on the server. then you can safely generate all the addresses you like without risking theft of bitcoins sent to said addresses because it isn't possible to generate the private keys from the xpub.

opensource code to do the above is available for a variety of languages. if you tell me which language your app is coded in maybe i can point you in the right direction. for example for php there is bitwasp's libraries:

https://github.com/Bit-Wasp/bitcoin-php

and smaller set of libraries in the bitcoin way plugin:

https://wordpress.org/plugins/bitcoin-payments-for-woocommerce/

note that you need a bip32 deterministic wallet for this. you shouldn't be using any other type of wallet anyway. software that creates deterministic wallets includes electrum, mycelium, bitcoin core and bitpay wallet.
AliceWonderMiscreations (OP)
Full Member
***
Offline Offline

Activity: 182
Merit: 107


View Profile WWW
February 22, 2017, 07:28:13 AM
 #3

addresses are not private. the private portion is called the private key. in  order to generate addresses without exposing the private key you simply install the wallet's extended public key aka xpub and master public key on the server. then you can safely generate all the addresses you like without risking theft of bitcoins sent to said addresses because it isn't possible to generate the private keys from the xpub.

opensource code to do the above is available for a variety of languages. if you tell me which language your app is coded in maybe i can point you in the right direction. for example for php there is bitwasp's libraries:

https://github.com/Bit-Wasp/bitcoin-php

and smaller set of libraries in the bitcoin way plugin:

https://wordpress.org/plugins/bitcoin-payments-for-woocommerce/

note that you need a bip32 deterministic wallet for this. you shouldn't be using any other type of wallet anyway. software that creates deterministic wallets includes electrum, mycelium, bitcoin core and bitpay wallet.

Ofcourse addresses are not private.

I don't want the servers do any address generation, deterministic or not. They just fetch an address when someone wants to send money.

But I do insist upon the web server having a way to validate the address it fetched belongs to me, not to a hacker who injected it into the database (which is likely a different server than the web app front-end) and that's why I create a signature for each address signed by the private ECDSA key I use as a seed on my machine that generates addresses. The signature in hex is only 128 characters long, and the public (not private) ECDSA key from the seed can then be used to validate the signature was generated by someone with the private key.



the string on the right is the signature of the address to its left, created using the private seed used for address generation and the address.

The public key that corresponds with the seed can then be used to validate them.

What I am suggesting is that, say, for example www.example.com is selling snake oil for bitcoin.

They can put a public key in DNS protected by DNSSEC and then sign all their bitcoin payment addresses uses the corresponding private key.

When I want to buy some extra fine snake oil, the bitcoin URI on their website includes the signature.

My client fetches the public key from DNS and if it DNSSEC validates, then uses it to check the signature matches the address with the public key.

That's what I want to see bitcoin clients able to do.

It would defend against MITM attacks (which can happen even with TLS) changing the payment address, and it would defend against malicious attackers injecting their own payment addresses into the web application.

bitcoin payments can't be reversed, so we have to defend against that kind of fraud before it happens. Validating the payment address really belongs to the website using cryprography is the only sure way to know it does.

I hereby reserve the right to sometimes be wrong
Abdussamad
Legendary
*
Offline Offline

Activity: 3682
Merit: 1580



View Profile
February 22, 2017, 09:34:53 AM
Merited by ABCbits (2)
 #4

addresses are not private. the private portion is called the private key. in  order to generate addresses without exposing the private key you simply install the wallet's extended public key aka xpub and master public key on the server. then you can safely generate all the addresses you like without risking theft of bitcoins sent to said addresses because it isn't possible to generate the private keys from the xpub.

opensource code to do the above is available for a variety of languages. if you tell me which language your app is coded in maybe i can point you in the right direction. for example for php there is bitwasp's libraries:

https://github.com/Bit-Wasp/bitcoin-php

and smaller set of libraries in the bitcoin way plugin:

https://wordpress.org/plugins/bitcoin-payments-for-woocommerce/

note that you need a bip32 deterministic wallet for this. you shouldn't be using any other type of wallet anyway. software that creates deterministic wallets includes electrum, mycelium, bitcoin core and bitpay wallet.

Ofcourse addresses are not private.

I don't want the servers do any address generation, deterministic or not. They just fetch an address when someone wants to send money.

But I do insist upon the web server having a way to validate the address it fetched belongs to me, not to a hacker who injected it into the database (which is likely a different server than the web app front-end) and that's why I create a signature for each address signed by the private ECDSA key I use as a seed on my machine that generates addresses. The signature in hex is only 128 characters long, and the public (not private) ECDSA key from the seed can then be used to validate the signature was generated by someone with the private key.

There are many problems with this. First of all you are supposed to trust your own servers. You can't design an app where you think some of the servers might be compromised while the others aren't. That's just crazy.

Second if you are going to store the public ecdsa key then you might as well use that to generate addresses independently on the webserver. This is deterministic address generation. Why bother with the whole signature generation and validation?

Quote
It would defend against MITM attacks (which can happen even with TLS) changing the payment address, and it would defend against malicious attackers injecting their own payment addresses into the web application.

bitcoin payments can't be reversed, so we have to defend against that kind of fraud before it happens. Validating the payment address really belongs to the website using cryprography is the only sure way to know it does.

Payment requests are similar to what you are talking about here. That uses TLS which for some reason you don't like. I don't know what to say.
AliceWonderMiscreations (OP)
Full Member
***
Offline Offline

Activity: 182
Merit: 107


View Profile WWW
February 22, 2017, 01:12:23 PM
Last edit: February 22, 2017, 01:28:42 PM by AliceWonderMiscreations
 #5


There are many problems with this. First of all you are supposed to trust your own servers. You can't design an app where you think some of the servers might be compromised while the others aren't. That's just crazy.

NO NO NO NO FUCKING NO.

Trust by itself is the cause of so many software compromises.

Never trust when verification is an option.

When verification is not an option, find a way to make it an option.

Quote
Second if you are going to store the public ecdsa key then you might as well use that to generate addresses independently on the webserver.

That's one way, but it has nothing to do with what I am suggesting here - which is a way for bitcoin clients to validate a payment address belongs to the web server they are buying something from.

I hereby reserve the right to sometimes be wrong
AliceWonderMiscreations (OP)
Full Member
***
Offline Offline

Activity: 182
Merit: 107


View Profile WWW
February 22, 2017, 01:35:00 PM
 #6

For what it's worth, I don't create new addresses with the normal deterministic method people use.

I use my own method that works extremely well, and it is not possible to determine if two addresses are related. That's why I won't generate addresses on the web server.

I'm sure many would say I'm doing it wrong because I'm doing it differently, but I have me reasons. Anyway - it is not related to what I am suggesting here, which is a method for clients to leverage DNSSEC to fetch a public key (which doesn't have to be related to the keys or even the same ECDSA curve bitcoin uses) to verify the authenticity of the address a payment is being made to.

I hereby reserve the right to sometimes be wrong
achow101
Moderator
Legendary
*
expert
Offline Offline

Activity: 3542
Merit: 6886


Just writing some code


View Profile WWW
February 22, 2017, 02:06:30 PM
Merited by ABCbits (1)
 #7

BIP 70 has something similar to what you are trying to do. It has the option to allow merchants to sign the payment request with a X.509 certificate to prove that the request and thus the address to pay is actually theirs.

However, I still don't see how this solves your problem. If someone injects an address into your database, then you probably won't know that that happened and still end up signing the address and giving it out anyways.

DannyHamilton
Legendary
*
Offline Offline

Activity: 3486
Merit: 4831



View Profile
February 22, 2017, 02:36:56 PM
Merited by ABCbits (2)
 #8

- snip -
However, I still don't see how this solves your problem. If someone injects an address into your database, then you probably won't know that that happened and still end up signing the address and giving it out anyways.

I think (hope) the idea is to pre-sign all the pre-generated addresses at the time they are generated and store both the address AND the signature in the database.

Since the attacker doesn't have access to the private key, he won't be able to generate a valid signature to replace in the database when he injects his fake address.

I also assume that the plan is to have the master public key statically embedded directly in a webpage file on the web server, so that the attacker can't inject his own master public key into the database.

In this way, the attacker would need to be able to accomplish ALL of the following for a successful attack:
  • Inject an address into the address database table
  • Inject a signature into the signature database table
  • Replace the web page file on the webserver with one that has the attacker's master public key
AliceWonderMiscreations (OP)
Full Member
***
Offline Offline

Activity: 182
Merit: 107


View Profile WWW
February 22, 2017, 03:08:55 PM
 #9

- snip -
However, I still don't see how this solves your problem. If someone injects an address into your database, then you probably won't know that that happened and still end up signing the address and giving it out anyways.

I think (hope) the idea is to pre-sign all the pre-generated addresses at the time they are generated and store both the address AND the signature in the database.

Yes, just like with DNSSEC where the zone files are signed offline and uploaded to the nameserver so that even if the nameserver itself is hacked, fake responses won't validate because the private key isn't there.
Bind is starting to screw that up now by having on the fly DNSSEC signing capabilities with signing key on nameserver but smart admins don't do that.

The signing key would not be on the SQL server or any of the web application servers.

Quote
I also assume that the plan is to have the master public key statically embedded directly in a webpage file on the web server, so that the attacker can't inject his own master public key into the database.

Exactly.

Quote
In this way, the attacker would need to be able to accomplish ALL of the following for a successful attack:
  • Inject an address into the address database table
  • Inject a signature into the signature database table
  • Replace the web page file on the webserver with one that has the attacker's master public key

Exactly.

I hereby reserve the right to sometimes be wrong
Abdussamad
Legendary
*
Offline Offline

Activity: 3682
Merit: 1580



View Profile
February 25, 2017, 08:10:49 AM
 #10

  • Replace the web page file on the webserver with one that has the attacker's master public key

Why not just replace the web page?

Payment requests work because we rely on commercial CAs to validate identities. How is the server's public key going to be checked in this scenario?

AliceWonderMiscreations (OP)
Full Member
***
Offline Offline

Activity: 182
Merit: 107


View Profile WWW
March 05, 2017, 06:57:15 AM
 #11

  • Replace the web page file on the webserver with one that has the attacker's master public key

Why not just replace the web page?

Payment requests work because we rely on commercial CAs to validate identities. How is the server's public key going to be checked in this scenario?



What I'm suggesting has nothing to do with certificate authorities.

The public key would be in DNS - and secured by DNSSEC.

I would suggest using libsodium for signing the payment address, because libsodium is a lot easier to implement and also has support in PHP via a PECL module and will have native support in PHP in PHP 7.2.

So sign the address with libsodium, and put the public key in DNS secured by DNSSEC.

I hereby reserve the right to sometimes be wrong
Abdussamad
Legendary
*
Offline Offline

Activity: 3682
Merit: 1580



View Profile
March 05, 2017, 10:37:47 AM
 #12

  • Replace the web page file on the webserver with one that has the attacker's master public key

Why not just replace the web page?

Payment requests work because we rely on commercial CAs to validate identities. How is the server's public key going to be checked in this scenario?



What I'm suggesting has nothing to do with certificate authorities.

The public key would be in DNS - and secured by DNSSEC.

I would suggest using libsodium for signing the payment address, because libsodium is a lot easier to implement and also has support in PHP via a PECL module and will have native support in PHP in PHP 7.2.

So sign the address with libsodium, and put the public key in DNS secured by DNSSEC.

If users' bitcoin clients are going to check dns then why publish the address on the web page at all? Let the bitcoin wallets grab the xpub from dns and send to some address derived from that.
AliceWonderMiscreations (OP)
Full Member
***
Offline Offline

Activity: 182
Merit: 107


View Profile WWW
March 05, 2017, 01:24:01 PM
Last edit: March 05, 2017, 02:02:46 PM by AliceWonderMiscreations
 #13

Maybe I am being paranoid - but when you use a deterministic address where the address is generated from a public key such that the corresponding private key can know there was a payment, I suspect there is a mathematical way to determine payment addresses are related.

That is why I do not use deterministic addresses, I don't want someone to be able to go through the blockchain and determine what payment addresses of mine are related (come from the same seed). I use a private mechanism for generating payment addresses where I first generate private keys involving a salt etc. and then the payment address from those generated private keys.

I do it this say so that someone without knowledge of the seed can not determine if two payment addresses are likely related.

Thus providing a signature for the address that the client can use to validate the address is in my opinion of value.

There are many people who do not use deterministic addresses, they are mathematically cool but I fear that same math allows them to be mined for relationships and is a potential privacy issue.

A libsodium generated signature and corresponding key is easy and works.

Why is what you are suggesting superior?

-=-

Also if the client is coming up with a deterministic address, how the fuck do I know what invoice it is for?

I hereby reserve the right to sometimes be wrong
Abdussamad
Legendary
*
Offline Offline

Activity: 3682
Merit: 1580



View Profile
March 05, 2017, 08:33:05 PM
 #14

Maybe I am being paranoid - but when you use a deterministic address where the address is generated from a public key such that the corresponding private key can know there was a payment, I suspect there is a mathematical way to determine payment addresses are related.

No there isn't. The only way to tell they are related is because they show up in transactions together when you go to spend your coins. This applies to all wallet types including the old fashioned non-deterministic ones.

Of course if you are worried about people finding out that the addresses are related by looking at the blockchain you can simply use coin control features as found in electrum or bitcoin core to pick your inputs manually and avoid revealing any links between your addresses.

Also in case you didn't know even Bitcoin Core is now deterministic.

BTW regarding generating lots of private keys offline please do read this:

https://bitcointalk.org/index.php?topic=912337.0

Pay special attention to posts by gmaxwell and dabura667 (especially post #8)

Quote
Also if the client is coming up with a deterministic address, how the fuck do I know what invoice it is for?

I just made all that up. No client supports picking up xpubs from DNS, validating DNSSEC and then generating an address to send payments to. Stealth addresses are the closest thing to that but they are not widely supported.

Payment requests OTOH are very well supported. Just use that and spare us Smiley
AliceWonderMiscreations (OP)
Full Member
***
Offline Offline

Activity: 182
Merit: 107


View Profile WWW
March 06, 2017, 06:38:28 AM
 #15

Maybe I am being paranoid - but when you use a deterministic address where the address is generated from a public key such that the corresponding private key can know there was a payment, I suspect there is a mathematical way to determine payment addresses are related.

No there isn't. The only way to tell they are related is because they show up in transactions together when you go to spend your coins. This applies to all wallet types including the old fashioned non-deterministic ones.

They are mathematically related, they have to be in order for the private key associated with the public key seed to find the value.

Do you have a mathematic proof demonstrating the relationship can never be inferred from the signatures use to spend the value? I would like to see it.

Quote
Of course if you are worried about people finding out that the addresses are related by looking at the blockchain you can simply use coin control features as found in electrum or bitcoin core to pick your inputs manually and avoid revealing any links between your addresses.

Also in case you didn't know even Bitcoin Core is now deterministic.

For a wallet that is fine. However I don't use bitcoin-core to generate payment addresses for e-commerce. I use a python script that I wrote. It isn't deterministic. It does use a seed but it does not use the deterministic properties of ECC.

Quote
BTW regarding generating lots of private keys offline please do read this:

https://bitcointalk.org/index.php?topic=912337.0

Pay special attention to posts by gmaxwell and dabura667 (especially post #8)

What point are you trying to make?

I don't use bitcoind to generate keys.

Quote
Quote
Also if the client is coming up with a deterministic address, how the fuck do I know what invoice it is for?

I just made all that up. No client supports picking up xpubs from DNS, validating DNSSEC and then generating an address to send payments to. Stealth addresses are the closest thing to that but they are not widely supported.

Payment requests OTOH are very well supported. Just use that and spare us Smiley

Spare me your opinion. It's fine that you don't like my idea, but I don't think you really understand what I am doing or talking about.

Having the ability for the client to verify a payment address with cryptography is not a bad thing, and if implemented you don't have to use that feature if you do not want to.

I hereby reserve the right to sometimes be wrong
AliceWonderMiscreations (OP)
Full Member
***
Offline Offline

Activity: 182
Merit: 107


View Profile WWW
March 06, 2017, 06:50:05 AM
 #16

btw - another benefit of not using deterministic keys -

The seed that is used for my generation method can be backed up at one location and the script at another.

If the backup seed is ever compromised, it can not be used to steal value that exists in payments addresses unless the perpetrator is also able to compromise the backed up script that takes the seed and generates the addresses and the salt that the script uses (the salt is essentially a second seed).

The seeds don't even need to be valid keys.

That kind of paranoia may not seem reasonable to you, but it does to me.

I hereby reserve the right to sometimes be wrong
Abdussamad
Legendary
*
Offline Offline

Activity: 3682
Merit: 1580



View Profile
March 06, 2017, 02:58:57 PM
 #17

bip39 supports passphrases so you can have more than one secret behind your HD wallet.

Spare me your opinion. It's fine that you don't like my idea, but I don't think you really understand what I am doing or talking about.

I admit that I'm not sure what you are up to because you've done a piss poor job of explaining it. Maybe you control the bitcoin clients your users use in which case you can do what you like.

Quote
Having the ability for the client to verify a payment address with cryptography is not a bad thing, and if implemented you don't have to use that feature if you do not want to.

Once again that's what payment requests do.

Anyway I'm out.
AliceWonderMiscreations (OP)
Full Member
***
Offline Offline

Activity: 182
Merit: 107


View Profile WWW
March 06, 2017, 10:04:15 PM
 #18

bip39 supports passphrases so you can have more than one secret behind your HD wallet.

Spare me your opinion. It's fine that you don't like my idea, but I don't think you really understand what I am doing or talking about.

I admit that I'm not sure what you are up to because you've done a piss poor job of explaining it. Maybe you control the bitcoin clients your users use in which case you can do what you like.

Quote
Having the ability for the client to verify a payment address with cryptography is not a bad thing, and if implemented you don't have to use that feature if you do not want to.

Once again that's what payment requests do.

Anyway I'm out.


Not all clients support payment requests, Bitcoin is a protocol for creating and validating transactions. Clients support the protocol for creating and validating those transactions. What else they do, be it deterministic address generation or payment requests is up to the client.

With respect to deterministic addresses, why I don't like them is as I stated there must be a mathematical relationship in order for public key A to generate B and C that private key A can then determine the private key for.

How to exploit that mathematical property may not yet be known, if a method even exists, but remember that the logjam attack on DHE ciphers was well known to the NSA long before it was known to the public, hence why ECDHE is what people really should be using for forward secrecy - or DHE with at least 2048-bit groups preferably generated locally rather than from the RFC.

I have not seen a mathematical proof that says it is impossible to show that public keys B and C have a greater than X probability of being generated from the same unknown deterministic key A. Until I see a mathematical proof that such a technique would be impossible to develop (and X doesn't have to be 100%, even 5% would be dangerous) I do not trust that deterministic key technology is not a possible privacy leak.

For a wallet it is probably fine, though it may make it easier to determine which output in a transaction is a change address, but wallet technology itself is rather poor with respect to privacy. Hopefully clients with better handling of how they spend emerge but they do not really exist now, one has to use multiple wallets to keep their BTC spending from being associated together.

For a business that receives transactions, though, privacy of customers is extremely important. It can't be as easy as the .gov making a small payment and then finding payments addresses related to the one they made in order to find out what wallets made payments to that company.

-=-

Payment requests may be a solution but it isn't the only solution to the problem of knowing that you are paying the right address. And they are not universally supported or required for a bitcoin client to implement, just like my DNS based public key and address signatures would not be required for a client to implement.

With multiple solutions, the free market can decide which is the solution they want to use.

Just like we are free to use libbitcoin instead of bitcoind or are free to use armory instead of bitcoin-core.

I hereby reserve the right to sometimes be wrong
AliceWonderMiscreations (OP)
Full Member
***
Offline Offline

Activity: 182
Merit: 107


View Profile WWW
March 06, 2017, 11:31:20 PM
Last edit: March 06, 2017, 11:43:25 PM by AliceWonderMiscreations
 #19

Can someone explain to me what mechanism payment requests have to prevent a fished MITM payment request, e.g. to example.photos instead of example.photo ?? (yes both TLDs exist).

EDIT -

Also according to the BIP - https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki - cryptographic signatures are optional, and when used, are validated by the PKI system which we know is not secure (easy to get fake certificates) rather than by DNSSEC which is a lot harder for malicious signatures due to the superior design of DNSSEC (no certificate authorities to trust).

PKI also has the problem that not all systems trust the same certificate authorities. DNSSEC does not have that problem.

I hereby reserve the right to sometimes be wrong
AliceWonderMiscreations (OP)
Full Member
***
Offline Offline

Activity: 182
Merit: 107


View Profile WWW
March 07, 2017, 12:07:52 AM
 #20

From the BIP it looks like it is not even possible to secure payment requests with DANE.

DANE secures PKI by requiring a fingerprint of the key in DNS secured by DNSSEC, but that fingerprint is in a TLSA record which requires a specific port and protocol. A fingerprint valid for TCP on Port 443 may not be valid for TCP on Port 25 even though the domain name is the same.

It doesn't look like payment requests even allow for that kind of fidelity when PKI is used.

e.g. the same key that is used on the web server would validate, the same key that is often on webservers in a hosting center where a lot of people who work for the hosting company potentially have access to the private key.

With the solution I am proposing, the public key is in DNS and the key used to sign the payment addresses does not even have to be online (though it would have to be online if you let the web server generate deterministic addresses)

I hereby reserve the right to sometimes be wrong
Pages: [1] 2 »  All
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!