Login | Register

Coinbase online payment system


Updated on October 11, 2012
Views: 8743 | Clicks: 277

Website Screenshot

General Information



Instant Payments

Payments arrive at the speed of an email (just a few seconds) and are confirmed within the hour. No more waiting three business days for checks.

Low Transaction Fees

Coinbase charges just 0.5% when you buy or sell bitcoin via bank account transfer. After that all bitcoin-to-bitcoin transactions are free.

Pay By Phone

Our website works great on modern smartphones (iPhone, Android, etc). Just visit coinbase.com from your mobile browser.


Simple Transfers

Use your bank account to purchase bitcoins. Transactions are processed within two to three business days. (coming soon)

Merchant Tools

Easily create "buy now" or donate buttons. We also offer full shopping cart integration. (coming soon)

Widespread Adoption

About $2 million a day (USD) is already being transacted in bitcoin. It's quickly becoming an international currency.



Countries of use



private and business


0.5% when you buy or sell bitcoin via bank account transfer

Recent news

Posted on January 16, 2020
Cosmos (ATOM) is now available on Coinbase

Starting today, Coinbase supports Cosmos (ATOM) at Coinbase.com and in the Coinbase Android and iOS apps. Coinbase customers can now buy, sell, convert, send, receive, or store ATOM. ATOM will be available for customers in all Coinbase-supported regions.

Cosmos (ATOM)

Cosmos is an interoperable blockchain protocol that facilitates the transfer of data between existing chains. It operates via a hub-and-spoke model that leverages the design elements of other chains to enable cross-chain interaction. The Cosmos framework features a Byzantine Fault-Tolerant (BFT) consensus algorithm developed by Tendermint to secure the protocol.

One of the most common requests we hear from customers is to be able to buy and sell more cryptocurrencies on Coinbase. Per the terms of our listing process, we anticipate supporting more assets that meet our standards over time. We are also investing in new tools to help people understand and explore cryptocurrencies. We launched informational asset pages (see ATOM here), as well as a new section of the Coinbase website to answer common questions about crypto.

You can sign up for a Coinbase account here to buy, sell, convert, send, receive, or store ATOM today.

Cosmos (ATOM) is now available on Coinbase was originally published in The Coinbase Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Read more on Coinbase
Posted on January 10, 2020
How MakerDAO doubled its users in a single weekend using Coinbase Earn

By Kenzan Boo

On July 26, 2019, Coinbase Earn launched the Dai Advanced Task. In a few days, users created more CDPs (Collateralized Debt Positions) than ever existed. In the previous 11 months, about 9,000 CDPs were created on the blockchain with MakerDAO. We chose to launch on a Friday. On the weekend after the Dai Advanced Task began, over 10,000 CDPs were created.

In this blog, we explore how one of the biggest decentralized finance apps used Coinbase Earn to help grow its network so quickly. We’ll dive into some of the engineering and product challenges along the way and how we solved them.

Coinbase Earn is a platform that connects the community of users with foundations like MakerDAO. The product allows users to earn cryptocurrencies while learning about them by watching educational videos and doing tasks. It’s a way to help educate crypto purchasers so that they are not just buying a ticker, but also understanding the foundations and networks behind the token.

Earn creates a value for the foundations as well. Foundations want to distribute tokens to its new users. Most new token projects dedicate a major portion of their tokens to initial distribution to circulate among the community. Earn is able to help them expand user participation. The more people that use it, the greater the network effect, and the more meaningful the token becomes.


MakerDAO is one of the most popular decentralized apps in the crypto community. It allows users to use ETH as collateral and create CDP’s in a stablecoin called DAI. DAI is made stable with the help of smart contracts on the Ethereum network, keeping it very closely pegged to the US Dollar.


The effects of the Coinbase Earn campaign have been lasting, even months after the first launch weekend. It’s shown sustained growth for the network far past the initial new user effect. While the lesson has introduced many new people to engaging in blockchain debt positions, it has not yet significantly changed the value of the total debt positions.

Below we’ll go through a few quick screenshots showing a run-through of the task.

Intro to the task telling users what they’re about to do.
We guide them through downloading the wallet app. Text to Download if they’re on a computer. The remainder of the task needs to be done using the Coinbase Wallet dApp browser.
Connect Coinbase wallet.
We send the user test funds for the tutorial.
Walk them through the steps on Maker.
Payout immediately.


Current challenges with using decentralized finance apps:

  1. Fear of loss
  2. Difficult to use

Users of decentralized finance have a fear of losing their initial deposits if they type in the wrong receiving address. Furthermore, many of the current user interfaces are notoriously difficult to use since they’re intended for engineers with technical experience and not consumers.

Fear of loss

Problem: Users’ fear of losing their funds.

As part of the tutorial, a very small amount of ETH was needed as collateral and to pay the network fee.

Solution: Provide the funds needed to complete the lesson.

We supplied collateral by building a backend Ruby controller which directly deposits the necessary ETH into the user’s linked wallet. By giving the user the ETH, the user would not lose their own money. Consequently, if they were not able to complete the tutorial, this would lessen any frustration. The below controller snippet highlights how we sent that allowance to the user’s wallet.

class V1::DaiSendEthController < V1::BaseController
  def dai_send_eth
      allowance = DaiEthAllowance.create!(
        user_id: current_user.id,
        wallet_address: wallet_address.downcase,
        eth_allowance_amount: ETH_ALLOWANCE_AMOUNT,
     rescue ActiveRecord::RecordNotUnique
       message: “User #{cb_user_uuid} already has an Eth allowance associated”
     return head :ok
 head :ok

Difficult to Use

Problem: Volatile gas prices (network fees).

Gas is a way for Ethereum to self-balance and make sure the network is always available. During high demand times, the cost to do computing on the Ethereum network is raised to incentivize more people to contribute computing power. Most of the time, it costs a few cents to open a Collateralized Debt Position on Maker. However, at rare times of high network use, the cost to create a CDP can go up to $10, which is a lot more than the tutorial funds we provide.

Solution: We check the ETH network for our users.

As part of the Dai Advanced task, we monitor ETH gas prices for our users through an internal backend system we built with our crypto team. The CheckEthGasPrice class below monitors both internal parity price and external Eth Gas Station prices to make sure that the gas prices are within the normal bounds. If we determine that the current gas conditions are too high, we ask the user to come back at a later time to complete the task. We want the user to be able to experience the full flow in the first pass and not have to come back later after they’re halfway through the tutorial. This also helps the Coinbase support staff reduce the number of support tickets coming in.

class CheckEthGasPriceJob < ApplicationJob
def perform
   gas_station_prices = GasStationApi.prices
   coinbase_parity_price = Ethereum::CoinbaseParityNode.new.gas_price_gwei
   eth_gas_station_price = gas_station_prices[‘average’]
   task_status = DaiTaskEnabled.first
   if coinbase_parity_price > DISABLE_THRESHOLD
      message: “Gas prices is too high, task disabled”,
     task_status.update(enabled: false) if task_status.enabled
         message: “Gas prices is acceptable, task enabled”,
      task_status.update(enabled: true) if !task_status.enabled

Problem: The Maker UI was not designed for mobile, making it difficult to use.

When we started on this endeavor with the Maker foundation, we were tasked with designing the whole flow end to end to make it easy to use. Upon attempting to create a CDP on the Maker site, it was clear that the page was designed to work well on desktop; however, we anticipated many of our users to go through Earn on mobile. A lot of the modals were cut off or other content not visible on a mobile device.

Solution: We worked closely with the Maker team to revise the Maker app to be mobile-friendly. In the screenshot above, the top set shows the UI before the updates made for Earn and bottom shows after. By working with the Maker team, we were able to iterate and improve on the UI to create a seamless experience for our users. The end result was an easy to use flow for our many mobile users.

Problem: Determining whether a user has successfully created a CDP.

To reward the user for completing the task, we need to first figure out when they’ve completed making a CDP.

module EtherscanApi::CdpCrawler
  DAI_TOKEN_CONTRACT = ‘0x8…’.freeze
       name: ‘dai mint event’, 
       event: ‘mint’,
       contract: DAI_TOKEN_CONTRACT,
       topic0: ‘0x0…’, # mint event
       parser: ‘parse_mint’,
       default_begin_block: 7_491_270 # starting from block when campaign launched
       name: ‘dai transfer event, Maker proxy’,
       name: ‘dai transfer event, Instadapp’,

Solution: Create a crawler that subscribes to all DAI events.
We built a crawler specifically to monitor DAI minting events from particular proxy contracts used by the most popular dApp. When our system sees a DAI mint event, we then try to connect that to our user’s originating wallet address in order to mark the lesson as complete. After that, we reward the user in DAI to their Coinbase wallet.


The DAI Advanced lesson has been a huge success for token development teams and for our community of users. By completing this task, many users directly engaged with a blockchain for the first time.

The DAI advanced lesson campaign has now concluded, however we’ll be working on many more community campaigns like this in the future. If you’d like to help build out the future of the crypto community, come join us.

Check out Earn here: http://coinbase.com/earn

Special thanks to John Granata, Alex Cusack and Max Schorer for working on Earn and editing this blog.

How MakerDAO doubled its users in a single weekend using Coinbase Earn was originally published in The Coinbase Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Read more on Coinbase
Posted on January 9, 2020
Capture the Coin — Cryptography Category Solutions

Capture the Coin — Cryptography Category Solutions

By Jake Craige, Max Mikhaylov, Jesse Posner

In the last post of the Capture the Coin competition series we will dive into the solutions for our cryptography challenges. Also, feel free to revisit our other write ups in the series for Trivia, Blockchain as well as the Competition and Prizes announcements.

AES Encryption Flaw

By Jake Craige

This challenge presents you with the output of an encryption and asks for the message that was encrypted (plaintext) as the solution. It was encrypted with Ruby as follows:

def encrypt(message)
require ‘openssl’
# Encrypt the message using random key+iv with AES-128-OFB
cipher = OpenSSL::Cipher.new(‘AES-128-OFB’).encrypt
random_key = cipher.random_key
cipher.key = random_key
random_iv = cipher.random_iv
cipher.iv = random_iv
ciphertext = cipher.update(message) + cipher.final
# Encrypt the IV with AES-128-ECB
simple_cipher = OpenSSL::Cipher.new(‘AES-128-ECB’).encrypt
simple_cipher.key = random_key
encrypted_iv = simple_cipher.update(random_iv) + simple_cipher.final
ciphertext: ciphertext.unpack(‘H*’).first,
encrypted_iv: encrypted_iv.unpack(‘H*’).first

If you have worked with AES before there are a few parts of this that may stand out to you.

First, it uses the Output Feedback (OFB) mode of operation as seen by usage of “AES-128-OFB” in the prompt. There isn’t anything wrong with this on its own, but the Cipher Block Chaining (CBC) and Counter (CTR) modes are more common and in practice, authenticated encryption (AE) like Galois/Counter Mode (GCM) should be used.

Next, we see that the IV is encrypted and uses the Electronic Codebook (ECB) mode. IVs are non-secret values and do not need to be encrypted. The security of the block cipher relies on them being random, but not secret. Furthermore, using ECB mode for encryption is never what you want. It is meant to serve as a building block for other modes, but should not be used as a mode on its own.

Block Ciphers & Modes

Let’s review what block ciphers and modes are, as they are key to solving this problem. A block cipher is a deterministic algorithm that accepts a fixed size secret key and plaintext as input and outputs a fixed size output, called a block. They are used for encryption which implies they also have a decryption operation that accepts the key and ciphertext and returns the plaintext.

A block cipher on its own is not secure for encrypting more than one message because encrypting the same message twice would result in the same ciphertext, put another way, a block cipher is deterministic.

Why is this a problem? Let’s say an army sends the message “Attack at dawn” one day and their adversary figures it out. On another day, if the army sends the same message and the adversary is watching, the will know that an attack is imminent and can set up defenses.

Formally, we say that a block cipher is not IND-CPA secure (indistinguishable under a chosen plaintext attack). This means that if we have a service encrypting data and we provide it two separate plaintexts to encrypt, we should not be able to identify which one was encrypted from the ciphertext.

We solve this issue by introducing different block cipher “modes of operation”. The default is ECB which is insecure, and other modes make it secure by introducing randomness and chaining blocks together in various ways.

We’ll review the ECB and OFB modes as they are the what the challenge uses.

Electronic Codebook (ECB)

source: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_(ECB)

ECB mode works by splitting the plaintext into blocks and independently encrypts each block. The final ciphertext is the concatenation of each block ciphertext.

A popular example of why this mode fails at providing enough security can been seen with the “ECB Penguin” image. We see that even when the image is encrypted, you can still see the penguin. This is clearly an undesirable property of an encryption scheme. An ideal encryption scheme would make the encrypted image look random as seen in the third image. Modes other than ECB provide this.

source: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_(ECB)

Output Feedback (OFB)

source: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Output_Feedback_(OFB)

OFB introduces an initialization vector, exclusive ORs (XOR), and the ciphertext from the previous block is used as input to another. The IV is a random value chosen at the time of encryption and prefixed to the ciphertext. The combination of the random IV and chaining blocks together solves the issues we described with ECB.

The Solution

With an understanding of the block ciphers used in the prompt, we can review how they were used and find the solution. Recall that the two ciphertexts are generated are as follows:

  1. The message is encrypted with a random key and IV using AES-128-OFB.
  2. The same IV is then encrypted with AES-128-ECB using the same key.

Looking at the size of the message ciphertext, we can see that it is 16 bytes long which means the plaintext is exactly one block since AES-128 uses 128-bit blocks. Given this, we can describe the message ciphertext as Encrypt(Key, IV) XOR Message. For the IV encryption, ECB mode was used, so the encrypted IV is simply Encrypt(Key, IV). Due to the property of XOR where a XOR b XOR a = b, we can solve for the plaintext by Ciphertext XOR EncryptedIV which is equivalent to Encrypt(Key, IV) XOR Message XOR Encrypt(Key, IV) = Message.

The solution in Ruby can be found as follows:

message_ct = [“1b08dbade73ae869436549ba781aa077”].pack(“H*”)
iv_ct = [“6f60eadec7539b4930002a8a49289343a7c0024b01568d35d223ae7a9eca2b5c”].pack(“H*”)
message_ct.bytes.zip(iv_ct.bytes).map { |l, r| l ^ r }.pack(“C*”)

This correctly outputs the CTF flag “th1s is sec01234”.

ECDSA Nonce Reuse

By Jake Craige

This challenge is described as follows:

The data below provides two hex encoded ECDSA-SHA256 signatures using the secp256k1 curve for the provided public key. These signatures were generated using the same nonce value which allows recovery of the private key.

Your task is to find the private key and submit it (hex encoded with 0x prefix) as the solution to this challenge.

Pubkey (SER-compressed): 0x2341745fe027e0d9fd4e31d2078250b9c758e153ed7c79d84a833cf74aae9c0bb
Sig #1 (msg): what up defcon
Sig #1 (r, s): (0x5d66e837a35ddc34be6fb126a3ec37153ff4767ff63cbfbbb32c04a795680491, )
Sig #1 (msg): uh oh this isn’t good
Sig #2 (r, s): (0x5d66e837a35ddc34be6fb126a3ec37153ff4767ff63cbfbbb32c04a795680491, 0xd67006bc8b7375e236e11154d576eed0fc8539c3bba566f696e9a5340bb92bee)

The prompt explains what is wrong, so all we have to do is figure out how to solve for the private key. A quick search will provide various explanations of the problem and how to solve it. Wikipedia provides a good explanation of how ECDSA signatures are generated and documents the solution to nonce reuse. We’ll describe the math here using the same variable names as Wikipedia.

Given two signatures s and s’ of different messages digests z and z’ which used the same nonce, the first step is solving for the private key is solving for k.

Now that we know k, we have enough public information to restructure the signature equation and solve for the private key d_a.

We can solve this problem in Python with the following code:

import hashlib
# secp256k1 order
order = int(“fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141”, 16)
# Input from challenge
z = int(hashlib.sha256(“what up defcon”).hexdigest(), 16)
z_prime = int(hashlib.sha256(“uh oh this isn’t good”).hexdigest(), 16)
s = int(“1a53499a4aafb33d59ed9a4c5fcc92c5850dcb23d208de40a909357f6fa2c12c”, 16)
s_prime = int(“d67006bc8b7375e236e11154d576eed0fc8539c3bba566f696e9a5340bb92bee”, 16)
r = int(“5d66e837a35ddc34be6fb126a3ec37153ff4767ff63cbfbbb32c04a795680491”, 16)
# dividing within a field is not standard division so we need to define it as follows
def modinv(a, modulus): return pow(a, modulus — 2, modulus)
def divmod(a, b, modulus): return (a * modinv(b, modulus)) % modulus
# Solve for private key d
k = divmod(z — z_prime, s — s_prime, order)
d = divmod(k * s — z, r, order)
# output challenge flag

This correctly outputs the challenge flag 0x128e06938ac462d9.

Linkable Payments

By Max Mikhaylov

This is a cryptography challenge. We will use Python to solve it. I assume that you are familiar with scalar multiplication for elliptic curves over finite fields. If this topic doesn’t sound familiar, read the first 3 chapters of Jimmy Song’s Programming Bitcoin book. This is a prerequisite for understanding the challenge.

For this challenge I need only one nonstandard package — fastecdsa. We use it to do arithmetic on ECC points of brainpoolP160r1 curve. We will be using only two classes from that package: Point and brainpoolP160r1.

Examining the data

Looking at transactions that were broadcast to the node, we see that all of them contain an invalid destination key. The problem clearly establishes the format for ECC points and the destination key doesn’t follow it (‘dest_key’: ‘G0’). It’s not even a valid hex number.

But the transaction public key looks valid. Let’s try converting those public keys to ECC points on brainpoolP160r1 curve. Let’s write a function that converts a single public key to a point on the curve.

def key_to_point(key):
return Point(int(key[2:42], 16), int(key[42:], 16), curve=brainpoolP160r1)

If we try converting some public keys to points with this function, we will get an error: ValueError: coordinates are not on curve <brainpoolP160r1>

It looks like the public key provided by the sender is not on the brainpoolP160r1 curve. In fact, none of the provided public keys are on that curve. From the description of the transaction model from the Cryptonote whitepaper we know that the node needs to perform scalar multiplication using the sender’s transaction public key and its own private key. Is it dangerous for the node to perform this multiplication with a point that is not on the expected curve? Yes! We will find out why in a bit.

If the node’s implementation wasn’t flawed, it would have checked if the public key provided by the sender is on the expected curve and throw an exception if it is not on the curve (just like fastecdsa library does). However, the node accepted this public key, performed scalar multiplication using its private tracking key and tried to compare whether its version of the shared secret (P_prime) is different from the one provided by the sender (P). Only when comparing those values, the node threw an error since one of the values is not a valid ECC point (the destination key provided by the sender). To make matters worse (or better for us as an attacker), the node exposed its version of the shared secret (P_prime) in the log.

Analyzing ECC points

The first hint of the challenge tells us that we need to concentrate on these invalid ECC points provided by the sender. Since the flawed node software doesn’t check if the provided point is on the curve, we can monkey patch the Point class of fastecdsa library to remove the following check:

def point_init_monkey_patch(self, x, y, curve):
self.x = x
self.y = y
self.curve = curve
Point.__init__ = point_init_monkey_patch

We can now try converting tx_pub_key to ECC point for all transactions one more time; no error:


pub_key_points = txs_to_pub_key_points(txs) # txs is dict of txs.json contents

We can also convert shared secret values from node logs to ECC points, now that we monkey patched the ECC library:

def err_log_to_shared_secret_points(err_log):
    shared_secret_points = []
    for entry in err_log:
        msg = entry[‘err_msg’]
        shared_secret = msg.split(‘P_prime=’)[1].split()[0]
        shared_secret_point = key_to_point(shared_secret)
     return shared_secret_points
shared_secret_points = err_log_to_shared_secret_points(err_log) # err_log is dict of err_log.json contents

Let’s go back to public key points. The first public key point looks very suspicious. I am talking about the Y-coordinate being 0. Let’s try calculating the order of this point.


def point_order(p):
    for x in range(2, brainpoolP160r1.p):
    if x * p == p:
        return x — 1



This is very low order! Turns out other public key points have low order as well. Does this give us some way to derive the private key used by the node to calculate shared secrets?

Invalid-curve attack

It turns out that these exact conditions allow us to carry out an invalid-curve attack. You can read more about what an invalid-curve attack is in “Guide to Elliptic Curve Cryptography” by Hankerson, Menezes and Vanstone on page 182. Also read a recent CVE-2019–9836 describing this attack in a practical setting (this was the second hint for this challenge).

The gist of the attack: if we can make the node compute shared secrets from low order points of relatively prime order, and can find results of these computations, we can recover the secret using the Chinese Remainder Theorem (CRT). To be more specific, we need the product of all low order points to be greater than the private key in order for the recovered key to be unique (thus, match the private key). If we calculate the product of the order of all points in `pub_key_points`, we can in fact see that this number doesn’t fit in 160 bits, thus has to be larger than the private key used with brainpoolP160r1 curve.


product = 1
for point in pub_key_points:
    product *= point_order(point)
from math import log2


175.1126248794482 # the product occupies 176 bits in binary representation

First, we need to be able to use the CRT. There are many resources on how CRT works, so you can read those if you are curious about math behind it. For solving this problem, I copied the CRT implementation from Rosetta Code.

We are now ready to perform the attack! The main idea behind this is the following:

  • We know that multiplying a low order point by a very large scalar (the private key) will result in a point of the same low order (the shared secret).
  • We can calculate the smallest possible scalar that, when multiplied by the public key, will result in the same low order shared secret.
  • We can do that by simply trying all possible scalars that are smaller than the order of the public key.
  • By bruteforcing the smallest possible scalar that gives us the shared secret when multiplied by the public key, we can construct a system of simultaneous congruences in the exact format that is suitable for applying the CRT. Since the product of all relatively prime orders is greater than the private key we are looking for, the result of applying the CRT is unique.


v = [] # can think of values in this list as the minimum number of EC additions of E_hat to itself to get shared_secret
moduli = [] # prime moduli of the system
print(“Constructing a system of simultaneous congruences:”)
for P_hat, shared_secret in zip(pub_key_points, shared_secret_points):
     order = point_order(P_hat)
     # search for shared_secret mod o_prime; i.e. the min number of additions of E_hat to itself to get shared_secret
     for x in range(1, brainpoolP160r1.p):
         if x * P_hat == shared_secret: # found the min number of additions
            print(f’e ≡ {x} mod {order}; ’, end=’’)


Constructing a system of simultaneous congruences:

e ≡ 1 mod 2; e ≡ 1 mod 11; e ≡ 7 mod 23; e ≡ 1 mod 5; e ≡ 34 mod 41; e ≡ 4 mod 7; e ≡ 273 mod 293; e ≡ 161 mod 691; e ≡ 93 mod 347; e ≡ 7 mod 17; e ≡ 162 mod 229; e ≡ 19 mod 53; e ≡ 7 mod 13; e ≡ 380 mod 977; e ≡ 83 mod 89; e ≡ 82 mod 109; e ≡ 4771 mod 9767; e ≡ 381213 mod 439511; e ≡ 758 mod 10009; e ≡ 14048 mod 26459; e ≡ 11 mod 37; e ≡ 196934 mod 949213;


e = chinese_remainder(moduli, v)



This private key hex looks unusual… This is definitely a flag!

P.S. If you are curious about how I found low order points in the first place, see my question on Cryptography Stack Exchange that I asked when working on this challenge.

Schnorrer Signature

By Jesse Posner

This challenge describes a defective signature scheme called Schnorrer signatures. This scheme is nearly identical to Schnorr signatures, however, it contains a critical flaw that allows Schnorrer signatures, unlike Schnorr signatures, to be easily forged. The goal of the challenge is to produce a valid Schnorrer signature for a given public key and message.

A Schnorrer signature, and its defect, are best understood by contrasting them with a Schnorr signature. A Schnorr signature applies the Fiat-Shamir heuristic to the Schnorr identification protocol, an interactive proof-of-knowledge sigma protocol, and transforms it into a digital signature protocol.

In Schnorr, the Fiat-Shamir heuristic challenge is generated by hashing the message and the public nonce, but in Schnorrer the challenge is the hash of the message and the public key. By replacing the public nonce with the public key in the challenge hash, the Schnorrer signature undermines the security of the scheme.

Schnorr Identification Protocol

The Schnorr identification protocol consists of 3 elements: (1) a key generation algorithm, (2) a prover and (3) a verifier. The prover generates a secret, `x`, and wants to prove to the verifier that she knows `x` without revealing it to the verifier.

Both parties will need to agree on some parameters: a cyclic group, with a generator, `G`, and a prime modulus, `q`. For example, the Bitcoin protocol uses the secp256k1 parameters, with a generator specified by an elliptic curve point with compressed coordinates:

02 79BE667E F9DCBBAC 55A06295 CE870B07 029BFCDB 2DCE28D9 59F2815B 16F81798

An uppercase letter, such as `G`, `P`, or `R`, denotes a group element, for example, an elliptic curve point. Lowercase letters denote scalar values, such as `x`, `r`, and `s`.

Key Generation Algorithm

The prover uses the key generation algorithm to produce a public-private key pair, `x` and `P`. `x` is an integer selected at random from a finite field with modulo `q`. The public key `P` is calculated by using `x` as a scalar value and multiplying it by `G`:


The private key, `x`, is the discrete logarithm of `P` with the base `G`, and thus the verifier is unable to efficiently derive the private key from the public key, and so the prover can reveal a public key without revealing the private key, hence the “public” and “private” denotations.


Let’s suppose that Alice wants to prove to Bob that she knows the value `x`. Alice begins the Schnorr identification protocol by generating a nonce, `r`, to be used as a scalar, similar to the private key. However, unlike the private key, the nonce must be used just once (“for the nonce”). Alice then computes the value `r*G` to derive the group element `R`, similarly to how the public key was generated. This value, `R`, is typically referred to as the public nonce, or the nonce commitment. Once Alice has her public key, `P`, and public nonce, `R`, she sends those values to Bob.

Bob now must generate another scalar value called the challenge value, `c`. After Bob receives `P` and `R`, he then generates `c` and sends it to Alice. Note that while `c` is independent from `R`, it is very important that Bob wait until he has received `R` from Alice before sending `c` to her. In fact, if Bob fails to do this, and sends `c` to Alice prior to receiving `R`, Alice can trick Bob into believing that she has knowledge of the secret key without actually knowing it. The integrity of the verification depends on `R` being generated prior to `c`, as we will see shortly.

Alice completes the conversation with Bob by multiplying her private key, `x`, by the challenge, `c`, and adding that product to her private nonce, `r`, to produce what is referred to as the `s` value. `s` must be modulo `q` (all scalar values must be modulo `q` so that they fall within the curve order).

We can now see the purpose of the nonce: it allows Alice to produce a value that is the product of (1) the private key, `x`, and (2) a value chosen solely by Bob, namely, the challenge, `c`. Yet Alice must accomplish this without directly disclosing `x` to Bob. If we omitted the nonce from the protocol, then `s` would be equal to `x*c`, and, while this value would indeed prove Alice’s knowledge of `x` to Bob, it does so far too aggressively and allows Bob to trivially compute `x` by dividing `s` by `c`.

```x = s/c```

However, with the addition of the nonce, x is hidden from Bob and cannot be computed solely from `s`.

```x = (s — r)/c```

Upon receiving `s` from Alice, Bob verifies the outputs of the protocol, `s` and `R` as follows: Bob computes `s*G`, and checks whether that value is equal to the sum of (1) the public nonce, `R`, and (2) the public key, `P`, multiplied by the challenge, `c`. Bob can be confident that Alice knows `x` if this equality holds, because Bob scaled `P` by `c`, and yet Alice knew the discrete logarithm of the result (offset by the public nonce), `s`. Thus, unless Alice has an efficient means of calculating discrete logarithms, she must know `x`.

However, as alluded to above, if Bob provides `c` to Alice prior to receiving `R`, then Alice can choose a malicious `R` and trick Bob into verifying the output, despite Alice not actually having knowledge of the private key, `x`, and the nonce, `r`. Alice does this by selecting a random integer modulo `q` to be used as `s`, and then computes `s*G` and `c*P`. Next, Alice subtracts `c*P` from `s*G` to compute `R`.

```R := s*G — c*P```

Now Alice has a valid public nonce, `R`, without knowing the private nonce, `r`, and a valid `s` without knowing the private key, `x`. Thus, we can see that it is critically important that Bob not disclose `c` to Alice until he has received `R` from her, otherwise Alice can choose `R` maliciously, by computing the difference between `c*P` and `s*G`.

Schnorr Signature

The Fiat-Shamir heuristic is a method that transforms Sigma protocols into digital signature schemes. It does this by replacing the challenge value, `c`, with a cryptographic hash of (1) a message, `m`, which is the data that is being signed, and (2) the public nonce, `R`. Requiring `R` as an input to a hash function that creates `c` prevents Alice from computing `R` from `c*P` and `s*G`, because `c` is now generated based on `R`, and thus `R` must preexist `c`.

The signature protocol proceeds similarly to the identity protocol: Alice multiplies her private key, `x`, by the challenge value, `c`, and then adds it to the private nonce, `r`, to produce `s`. The signature consists of the pair of values, `s`, and the nonce commitment, `R`, which are provided to Bob by Alice. Bob can compute `c` himself because `c := H(m || R)`.

The structure of the verification algorithm is the same as the identity protocol: `s*G == R + c*P`

Schnorrer Signature

A Schnorrer signature is identical to a Schnorr signature, except the challenge value, `c`, is a hash of (1) the message and (2) the public key, `P`, instead of (1) the message and (2) the nonce commitment, `R`. This seemingly small modification to the scheme renders it insecure.

The forgery attack proceeds along the same lines as the identification attack described above. In the identification attack, Bob provided the challenge value to Alice prior to receiving the public nonce, `R`. Similarly, because the Schnorrer signature challenge value does not include `R`, Alice can reverse the order of the protocol, and choose an `s` value first, and then calculate `R` as the difference between `s*G` and `c*P`, and thus forge a signature, in other words, with this defect, Alice can produce a valid Schnorrer signature without knowing the private key, `x`, (and also without knowing the nonce, `r`).

Forging A Signature

By Jake Craige

This challenge is described as follows:

Given two Pedersen commitments in and out, you must construct a proof that the difference between the commitment amounts is zero. We’ll use the secp256k1 curve and define `g` as the standard base point of the curve and `h=g^SHA256(“CoinbaesRulez”)`.

We’ll define out input and output commitments as `in=g¹³³⁷⋅h⁹⁸⁷⁶` and `out=g²⁶⁷⁴ ⋅h³⁴⁵⁶` and walk through the evaluation here.

= in⋅out^−1
= (g¹³³⁷⋅h⁹⁸⁷⁶)⋅(g^−2674⋅h³⁴⁵⁶)^−1
= g^(1337+2674)⋅h^(9876−3456)
y = g⁴⁰¹¹⋅h⁶⁴²⁰

We see that this is not a commitment to zero and actually creates more money thaen went into it. Your task is to provide us a `(t, s)` pair that convinces a verifier that `y` is a commitment to zero even though that’s not true.

Here is the input data you should use to create the signature. The elliptic curve points (commitments) are provided in the SEC compressed encoding. For the signature, we’ll use the Schnorr Identification Protocol proof described in the attached PDF. You must use the provided nonce so that we get a deterministic outcome for the CTF verification.


The submission should be in the format `(t, s)` where both `t` is the hex encoded compressed point and `s` is a hex encoded unsigned integer. They should both have a `0x` prefix and the parenthesis and `,` must be present to verify. An example format would be: `(0xdead, 0xbeef)`.

The problem with the construction defined above is how `h` is selected. For a pedersen commitment to be trusted no one can know the discrete log of `h` with respect to `g`. Restated: no one should know `x` such that `h=g^x`. Knowledge of that allows one to forge commitments.

Recall that our commitment looks like `y=g^a⋅h^b` where `a` is the amount and `b` is the blinding factor. We provide a proof for `y=h^z`. With a non-malicious prover, this proves a commitment to a zero amount because `y=g⁰⋅h^b=h^b`, so we simply prove that we know the blinding factor `b` and verify against the public key `y`.

Unfortunately, by naively deriving `h` from `g`, we know the discrete log and can forge the signature. Here’s how.

We first set up the equality we wish to forge, and restructure it such that everything is done in base `g`. This is the step that can only be done if you know the discrete log of `h` which is the value `x`.

From this, we can solve for the value `z` which is what we need to create the proof. For simpler notation, we drop the base to show how this value is solved for.

With that equation in hand, we can proceed to create the proof. The values for `a, b, x` can be found in the problem statement: `a=4011`, `b=6420`, and `x=SHA256(“CoinbaesRulez”)` We treat the byte output of the SHA256 function as big-endian to represent it as a number.

Using this information we can compute `z` using our equation from before. In Python this can be done as follows:

import hashlib
# secp256k1 order
order = int(“fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141”, 16)
def modinv(a, modulus): return pow(a, modulus — 2, modulus)
a = 4011
b = 6420
x = int(hashlib.sha256(“CoinbaesRulez”).hexdigest(), 16)
z = (a * modinv(x, order) + b) % order

Now that we know `z`, the last step is to create a proof of knowledge of discrete log to submit as the solution flag. This is done using the Schnorr Identification Protocol where we use the Fiat-Shamir transform to make it non-interactive by setting the challenge value to be the big-endian representation of the SHA256 output of the compressed points H, T, and Y concatenated together as bytes. The problem description provides a fixed nonce to make the output deterministic. The solution in Python, building on the former Python code, is:

from fastecdsa.curve import secp256k1
from fastecdsa.point import Point
from fastecdsa.encoding.sec1 import SEC1Encoder
# Challenge input
H = secp256k1.G * x
r = 0x19
# Generate the proof of knowledge of discrete log
T = H * r
Y = H * z
hashInput = SEC1Encoder.encode_public_key(H)
hashInput += SEC1Encoder.encode_public_key(T)
hashInput += SEC1Encoder.encode_public_key(Y)
c = int(hashlib.sha256(hashInput).hexdigest(), 16)
s = (r + c*z) % order
# Print the formatted flag
print(“(0x” + SEC1Encoder.encode_public_key(T).encode(“hex”) + “, 0x” + format(s, ‘x’) + “)”)

To see more about how these Pedersen Commitments are used in practice in blockchains, I recommend reading up on MimbleWimble based blockchains.


This concludes our writeups for the Capture the Coin competition. We hope you enjoyed learning more about a variety of blockchain security topics and can join us again next year.

In the meantime, if solving blockchain security challenges is something that you see yourself doing full time, then join us at Coinbase to help build the most trusted brand in the Crypto here.

This website contains links to third-party websites or other content for information purposes only (“Third-Party Sites”). The Third-Party Sites are not under the control of Coinbase, Inc., and its affiliates (“Coinbase”), and Coinbase is not responsible for the content of any Third-Party Site, including without limitation any link contained in a Third-Party Site, or any changes or updates to a Third-Party Site. Coinbase is not responsible for webcasting or any other form of transmission received from any Third-Party Site. Coinbase is providing these links to you only as a convenience, and the inclusion of any link does not imply endorsement, approval or recommendation by Coinbase of the site or any association with its operators.

All images provided herein are by Coinbase.

Capture the Coin — Cryptography Category Solutions was originally published in The Coinbase Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Read more on Coinbase
Posted on January 9, 2020
Cosmos (ATOM) is launching on Coinbase Pro

Cosmos (ATOM) is now available on Coinbase Pro

On Tuesday, February 14, ATOM began trading on Coinbase Pro. Support for ATOM is available in all Coinbase’s supported jurisdictions. Per previous launches, transfers opened during business hours, Pacific Standard Time.

On Tuesday, February 14, ATOM began trading on Coinbase Pro. Per previous launches, transfers opened during business hours, Pacific Standard Time.

Once sufficient supply of ATOM was established on the platform, trading on the ATOM/USD, and ATOM/BTC order books began in phases, beginning with post-only mode and proceeding to full trading after our metrics for a healthy market were met. Support for ATOM will be immediately available in all Coinbase’s supported jurisdictions.

At this point, Coinbase will not support ATOM staking.

Cosmos is an interoperable blockchain protocol that facilitates the transfer of data between existing chains. It operates via a hub-and-spoke model that leverages the design elements of other chains to enable cross-chain interaction. The Cosmos framework features a Byzantine Fault-Tolerant (BFT) consensus algorithm developed by Tendermint to secure the protocol.

Please note that ATOM is not yet available on Coinbase.com or via our consumer mobile apps. We will make a separate announcement if and when this support is added.

The Stages of the ATOM Launch

There will be four stages to the launch as outlined below. We will follow each of these stages independently for each new order book. If at any point one of the new order books does not meet our assessment for a healthy and orderly market, we may keep the book in one state for a longer period of time or suspend trading as per our Trading Rules.

We will send tweets from our Coinbase Pro Twitter account as each order book moves through the following phases:

  1. Transfer-only. Starting on Monday, January 13, customers were able to transfer ATOM into their Coinbase Pro account. Customers weren’t able to place orders and no orders were filled on these order books. Order books were in transfer-only mode for at least 12 hours. We will communicated the exact timing for this phase via Twitter closer to the date.
  2. Post-only. In the second stage, customers were able to post limit orders but there were no matches (completed orders). Order books were in post-only mode for a minimum of one minute.
  3. Limit-only. In the third stage, limit orders started matching but customers were unable to submit market orders. Order books were in limit-only mode for a minimum of ten minutes.
  4. Full trading. In the final stage, full trading services will be available, including limit, market, and stop orders.

One of the most common requests we receive from customers is to be able to trade more assets on our platform. Per the terms of our listing process, we anticipate supporting more assets that meet our standards over time.

You can sign up for a Coinbase Pro account here to start trading. For more information on trading ATOM on Coinbase Pro, visit our support page.

Cosmos (ATOM) is launching on Coinbase Pro was originally published in The Coinbase Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Read more on Coinbase
Posted on January 7, 2020
The Coinbase Pro mobile app is now available for Android devices

The Coinbase Pro mobile app is now available for Android

By Linda Xie, product manager, Coinbase Pro

The new Coinbase Pro mobile app for Android delivers a world-class trading experience for investors on the go.

Following the launch of the Coinbase Pro mobile app for iOS customers in October, today we’re making that same trading experience available to Android users. Designed to provide advanced crypto traders with the necessary tools to make trades on the go, the Coinbase Pro mobile app for Android enables traders to capitalize on market conditions at any time, wherever they are. As the dominant mobile operating system globally, Android is a vital piece of the international cryptoeconomy that Coinbase is building.

The Coinbase Pro mobile app, is a powerful, mobile-first trading platform that was built with a focus on speed, ease of use, and a clean, streamlined trading experience. The mobile trading experience provided by the app offers the functionality of our desktop platform, built in a way to make traders feel in control at every step. No action requires more steps than it needs to, meaning traders can see prices, check their portfolios, and execute their orders faster than ever before.

As part of today’s release, users on both Android and iOS now have access to new features such as deposits and withdrawals into fiat and crypto accounts, along with enhanced security features including passcode authentication.

Since the launch of the Coinbase Pro mobile app in October, it has become clear that our customers want to trade on the go. In just over eight weeks, we’ve seen hundreds of millions in trade volume via the mobile platform. Through the app, these trades are also taking fewer steps and less time for the user to execute compared the desktop experience.

The Coinbase Pro mobile app for Android offers the same feature-rich trading experience as our previously launched iOS app, including real-time candles, depth charts, order books and advanced order types, along with intuitive shortcuts. The experience is equally as intuitive and powerful for both Android and iOS users. Orders made via the app carry the same fees as those executed via the desktop platform, and traders have access to the more than 50 trading pairs available today on Coinbase Pro. The app is available to Coinbase Pro customers in 100+ countries around the world.

To download the app, visit the Google Play Store.

All images provided herein are by Coinbase.

The Coinbase Pro mobile app is now available for Android devices was originally published in The Coinbase Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Read more on Coinbase

See all news of Coinbase

Coinbase Comments:

Add your comment