[Idea] Posted Phonons

@Senor and I are excited to announce a potential new feature that we have dubbed “Posted Phonons”. We hope to get community feedback and involvement with the end goal being that posted phonons become part of the Phonon Protocol.

In short, a phonon is a private key that is guaranteed to be known by a single phonon card and no other entity. We will refer to this as the “phonon guarantee”. Currently, when transfering a phonon, both the sender and recipient must have their cards actively paired. This pairing process ensures both cards are following the protocol’s rules, thus maintaining the phonon guarantee.

This pairing process works extremely well in some situations but not so well in many others. For example, imagine your friend messages you saying that they have purchased tickets to a gig you wanted to see. You wish to reimburse them immediately using the Phonon protocol, but doing so would require you both to coordinate opening your Phonon wallet apps, unlocking your cards, and waiting for the transaction to complete. As a result, your friend instead tells you they are too busy to sync and to just Venmo them.

Another scenario where active pairing is an inconvenience is high traffic online retailers. For each customer paying with the Phonon protocol, the retailer would need to maintain an active pairing connection and potentially need a phonon card for each connection. Even if the retailer wanted to go down this route, the development work involved would be substantial and require knowledge outside your typical web developer’s skill set.

Posted Phonons

The changes we propose under posted phonons will drastically improve the usability of the Phonon protocol in the above scenarios, and many others, while maintaining the phonon guarantee.

We introduce the concept of a “posted phonon”, which is a phonon that exists outside of any phonon card. A posted phonon consists primarily of a phonon private key encrypted with the intended recipient’s card’s public key, a signature proving the posted phonon comes from a valid phonon card, and a nonce. If a posted phonon comes from a valid card and the private key can only be decrypted once by a single phonon card then the phonon guarantee is maintained.

To create a posted phonon the sender’s card requires the recipient’s card’s public key and nonce (more below on how these could be requested if a card is offline). Once created, the original phonon is removed from the sender’s card, and the sender receives a posted phonon which can then be sent to the recipient over any medium (HTTP, email, smoke signals). A recipient can consume any received posted phonons at any time but posted phonons should be consumed in order of ascending nonce (consecutive order is not required). A phonon card will reject any posted phonons containing a nonce less than its current internal nonce.

With posted phonons in place, the “reimbursing a friend for tickets” scenario looks a little different. Instead of having to coordinate being online to pair, you ask your friend for their card’s public key and a nonce. Once you receive these details you are able to generate a posted phonon and send it to them using whatever medium suits. Your friend can then consume the posted phonon onto their phonon card whenever it is convenient for them.

Although this flow reduces the need for you and your friend to coordinate being online at the same time, it does introduce friction in other areas. Your friend, the receiver, has to send you their public key and a suitable nonce. To provide a suitable nonce they must keep track of nonces they have previously given out. Additionally, the receiver must ensure that they consume posted phonons in the correct order. Imagine if your friend had previously provided their mother with a nonce lower than yours but had not yet received a posted phonon from her. In this scenario, if they were to receive your posted phonon before their mother’s, your friend can not consume your phonon until they either receive and consume their mothers, or confirm that their mother isn’t going to send a posted phonon with that lower nonce. If their mother’s posted phonon is received after yours is consumed the funds will be lost to both your friend and their mother forever.

Phonon Inbox

To overcome these significant usability issues we have designed a service that we have dubbed a “phonon inbox”. A phonon inbox, sitting outside the of Phonon Protocol, is a service that manages the issuance, storage and consumption of posted phonons. To explain a phonon inbox we will again use the well-explored “reimbursing a friend for tickets” scenario.

Your friend, the recipient, at a previous point in time has signed up for a phonon inbox. When they signed up they provided the inbox with their desired username and their phonon card’s public key and current nonce. When you go to reimburse your friend, you enter their username into your phonon app which makes a request to your friend’s phonon inbox asking for their card’s public key and a nonce. Once these details are received your app immediately creates a posted phonon and sends it to your friend’s phonon inbox. Next time your friend opens their phonon app their card automatically consumes any ready posted phonons. To overcome the uncertainty around if it is safe to consume a received posted phonon when a posted phonon has not been received for a lower nonce, each nonce should be issued with an expiry timestamp. This timestamp gives the sender an explicit cutoff time in which they must send the posted phonon or it may be no longer consumable due the recipient possibly already consuming a posted phonon with a higher nonce.

Phonon inboxes can be self hosted or accessed through a service provider and therefore a discovery system is needed. One idea we have come up with is a “phonon inbox address”, such as hinchy$phonon.dao or personal$hinchy.com, which leverage the DNS system. Another complementary solution is for users to add their phonon inbox url to their ENS records.


Next Steps

  1. Get community consensus that this is a feature worth committing DAO resources towards
  2. Have the Core Devs confirm the feature is viable
  3. Complete the mock card implementation
  4. Have the Core Devs sign off on the mock card implementation
  5. Have the Core Devs implement the feature
  6. Phonon DAO develops an inbox system for public use


  • @deviator for looking over and giving feedback on our initial idea
  • @rake for coming up with the name “Posted Phonons”

This is great! Love the innovation.

1 Like

nice - seems like a really cool idea

1 Like

Solving offline usability is a pretty important goal so am very supportive of further investigation so would love to see Clamato’s suggestion of a call at an Aus/US friendly time where Dan/Nate/other members of the community can stress-test it.

I do worry slightly about the user experience of an expiry timestamp at scale but am struggling to think of a better solution and think there is value to having this out there to stimulate other ideas.


Hey @Dcc, glad you think the idea is worth exploring.

The nonce expiry timestamp is definitely the weakest part of the proposed solution. Originally the idea was for the sender’s card to generate a unique nonce when generating the posted phonon. This has two advantages. The sender doesn’t need to request a nonce from the recipient, and second, the recipient can consume the posted phonons in any order. @deviator pointed out that this solution is not viable because of card memory limitations and recipient’s card being required to store these unique nonces.

Although not ideal,I don’t believe the proposed solutions nonce flow is a deal breaker. The sender’s app should request the nonce and send the phonon in quick succession so even at mass scale the receiver’s inbox should be receiving posted phonons roughly in order of nonce issuance.

Let me know if you have any thoughts on this. I’ll have a chat with @clamato about organizing a time for a community call.

1 Like

Great proposal hinchy and señor. This situation would most likely have come up, so props on your forward thinking for the solution.

In a way, is this a bit like picking up tickets at will call?


@Rush I love an example like “will call” because everyone understands how that works today.

I own season tickets. I can’t attend tonight’s game. I tell the kiosk at the ballpark only you, Rush, are allowed to pick them up. And in this example, it’s up to the kiosk to check your ID, and make sure those tickets aren’t picked up by someone else!

Posted Phonons achieve exactly the same outcome: Rush gets my tickets. But with a few nuances:

  1. The kiosk functions less like a terminal/ticket window at a ballpark and more like email. Once you have the time to log onto the internet, you can grab your tickets. They are sitting there in your inbox. I sent them to you! (Note: In this example, the tickets are a gift. You probably wouldn’t even need the added service (which can be available to you) of having the tickets be verified as real.

  2. Unlike the kiosk, where an identity revealing verification step is required (check license ID), posted phonons are encrypted to recipient address. No identity is revealed. You either have the intended card, or not.

  3. Because it’s encrypted, even if it were stolen (I look exactly like my brother - better believe I can get his tickets at will call!) impossible to use. Can’t access the contents of the Posted Phonon.

@hinchy i miss anything?


Nope, I think that is everything.

One thing that I didn’t make clear in my original post but you brought up in point #3 is the fact that posted phonons do not need to be kept private. Because a posted phonon can only be consumed by the intended recipient there is no issue with making them public. There may be some interesting use cases for this such as providing proof a payment was made.

1 Like

I am offering a bounty of $200 PHONON to the first person who can show how the following design of Posted Phonons breaks any of the guarantees of the Phonon Protocol. Nonce management/tracking and how posted phonon transfer packets are transmitted are outside the scope of bounty as they sit outside of The Protocol. Any suggested improvements may also be eligible for an additional bounty. For simplicity we’ll assume a posted phonon can only consist of a single phonon.

The following additions are made to the applet

  • An integer nonce
  • GetPostedPhononNonce() - method to retrieve a card’s nonce
  • PostPhonons(recipientsPublicKey, nonce, phononIndex): - a method to create a posted phonon transfer packet
  • ReceivePostedPhonons(postedPhononTransferPacket) - a method to consume a posted phonon transfer packet

Step 1

The recipient retrieves their card’s nonce and public key by calling GetPostedPhononNonce and IdentifyCard.

Step 2 [Outside scope]

The recipient sends their card’s nonce and public key to the sender

Step 3

The sender calls PostPhonons with the recipient’s nonce, recipient’s public key and which phonon they wish to send.

  • The phonon’s private key is encrypted with the recipient’s public key
  • A signature is created. The following is signed with the sending card’s private key
    • The phonon’s public keys
    • The encrypted phonon’s private keys
    • The recipient’s nonce
    • The recipient’s public key
  • A phonon transfer packet is created with the following
    • The nonce
    • The sending card’s certificate
    • The encrypted phonon private key
    • The signature
    • Phonon metadata
    • Recipient’s public key
  • The phonon is deleted from the sender’s card

Step 4 [Outside scope]

The posted phonon transfer packet is sent to the recipient. The recipient is able to validate the phonon outside of the card.

Step 5

The recipient calls ReceivePostedPhonon passing in the transfer packet. The card

  • Reconstructs the signature data using the nonce, phonon public key, encrypted phonon private key from the transfer packet and its own public key.
  • Confirms the signature is signed by the public key in the sender’s certificate.
  • Confirms the certificate comes from a valid CA.
  • Confirms the nonce is greater than its internal nonce
  • Decrypts the phonon’s private key and adds the phonon to storage
  • Increases its nonce to match the nonce in the transfer packet
1 Like

Hey, taking another look at this and after another look through I think I see a security issue in this design.

That being said I think the goal of enabling non-interactive or offline phonon sends is an excellent goal and there may still be a way to tweak this design to achieve it.

So basically the security issue I see here is in the encryption of the posted phonon packet.

As described, the “phonon inbox” service would record a card’s public key and current nonce, and then pass that to senders so that they could use this key to encrypt a phonon and drop it off in the inbox.

The issue here is that the sender has no guarantee that the public key they use to encrypt the phonon is a legitimate phonon public key. An attacker could generate a public key from a private key outside of the phonon system, use it to impersonate a legitimate card, and then decrypt the phonon transfer packet, including phonon private key, in order to doublespend the phonon outside of the protocol…

Thinking through it as I type this, but I think maybe this could be solved by including the full recipient certificate on the Inbox service and passing that to the sender? That way the sender could use the CA sig on the cert to prove that the public key they are encrypting to is a Phonon protocol public key, therefore guaranteeing that assets encrypted to this key will follow the phonon protocol rules.

I think that solves the major security hole?

Assuming so, the issues I see for further refinement are the nonce handling and selecting appropriate crypto for sending the posted phonons.

For nonce handling I think this design is functional as is but it seems like there may be some irritating edge cases and susceptibility to spam attacks with the "ordered list and expiring TTLs’ approach. Maybe there’s a way to store some out of order nonces on the card temporarily to smooth this over.

For the crypto we clearly can’t use the existing pairing logic because it relies on both parties being online, so we need a one way crypto function that can send enough data to handle large phonon transfers. Shouldn’t be hard to find but still has to be picked.


yep, I 100% agree with this.

But I don’t think this is correct. A legitate phonon card will refuse to consume a posted phonon transfer packet that isnt encryped with its own public key. The end result is the phonon has been removed from senders card, cant be consumed by a valid phonon card, but the private key is acceessible to the recipient. I’d say the phonon has basically been redeemed and there is no risk of a double spend.

Also, in my original design I forgot to add in that the encryted data needs to include some sort of salt.

Ah, yea you’re right about the fact that this won’t cause a doublespend. It’s more like an encrypted redeem to another public key, but this issue still prevents this from working as intended to perform a non interactive phonon send.

Actually I now realize that without the receiving Inbox validating the sender’s cert they have no guarantee that the data they are receiving is a genuine phonon. It could be an outside the protocol private key susceptible to doublespends with the sender impersonating a legitimate phonon card.

But this is also easily solved by having the sending card and the receiving inbox mutually validate each other’s certifcate signatures.

In this case, the sender must prove they own the certificate’s corresponding private key, which guarantees that the keys they are sending have remained secret within the Phonon Protocol rules, while the receiver Inbox just presents their receiver card’s certificate, proving that the destination of the sent phonons is a legitimate phonon card. The Inbox does not need to have access to the receiver cert’s private key, since the card can use that later to prove it’s identity while decrypting the actual phonon transfer packet. This property allows the receiving side to receive while offline.

So in short, I think adding these two security checks to the flow resolves this issue.

  1. sender validates certificate of receiving phonon card
  2. receiver validates certificate of sending phonon card and requires it to authenticate as the owner of the certificate’s identity key.

And wondering what is the purpose of the salt in the encrypted posted phonon transfer packet? Just message authentication or does it impact security? I think if using something like ECDSA the signatures will always include a random component anyway, so I don’t think you need to add an additional salt to prevent key reuse attacks.

100% but I believe the packet structure I suggested a few messages up achieves what you want. Each posted phonon contains the sender’s certificate and a signed message containing data such as the phonon’s public key and the recipient’s public key and nonce. With the certificate, signature and the clear text data, anyone (inbox, recipient card or another third party) can validate that the transfer packet is coming from a valid phonon card, which phonon card the packet is intended for and that the phonon being transferred has value.

  1. I don’t believe a sender needs to care if they are sending a phonon to a legitimate phonon card or not. As you said “…It’s more like an encrypted redeem to another public key…”. If a posted phonon is produced for an invalid public key the phonon is now outside the network and it cannot reenter. It cannot be double spent. It is the recipient’s responsibility to provide a valid phonon public key if they wish to receive a valid phonon. Otherwise they are receiving a private key they must decrypt themselves.
  2. As explained above I believe the current design already achieves this.

ahhh ok. I’ll admit I’m not very knowledgable about encryption so I am probably misunderstanding. I’ll just provide a high level overview and let the experts work out the specifics :slight_smile:

I made a very high level implementation of the posted phonons with tests. I think youll be interested in TestPostedPhononCanOnlyComeFromValidCard and TestPostedPhononCanOnlyBeConsumedByRecipient.

Yep, you’re right I missed the signature in the sender data, that handles it.

Ah, unexpected and interesting design, so if the recipient provides a phonon card’s pubkey they can receive it onto their card as a phonon, but if they provide an non-phonon pubkey then the phonon is essentially being redeemed? I think that basically works, though it may be a bit challenging to implement these rules on the card.

Will check out the implementation you shared!

I actually think this is much simpler than the current design because the sender and recipient aren’t required to pair. Instead, the recipient card just needs to confirm the following…

// The recipient card is the intended recipient
if !packet.RecipientsPublicKey.Equal(&c.PublicKey) {
  return keyIndex, nil, ErrNotIntendedRecipient

// The sending card is a valid phonon card (this check will need adjusting to account for multiple CAs)
if !cardCertificateIsValid(&packet.SendersCertificate, c.Certificate.CAPublicKey) {
	return keyIndex, nil, ErrInvalidSenderCard

// The contents of the packet is signed by the sending card (which is already known to be a valid phonon card)
if !postedPhononTransferPacketContentsIsValid(packet) {
	return keyIndex, nil, ErrInvalidTransferPacketSignature

// The recipient isn't attempting to consume the packet twice
if packet.Nonce <= c.transactionNonce {
	return keyIndex, nil, ErrInvalidNonce

I am becoming more convinced that the posted phonon design can simplify the current transaction flow.

In the current flow, before transacting, two cards must complete a four step pairing process. This process achieves two things. It produces a shared secret for phonons to be encrypted with as they are in transit and ensures double spending isn’t possible by validating that both cards are valid phonon cards.

One of the properties of a posted phonon transfer packet is that it contains a signed message from, and the certificate of, the sending card. With this, a receiving card is able to verify the sender is a valid phonon card. Instead of using a shared secret to encrypt the phonon private key, a sending card can encrypt the phonon with the receiving card’s public key.

The advantages of using this design are:

  • Simpler applet code and faster transactions. Pairing logic can be removed
  • Transactions are replayable. Cards don’t need to hold onto pairing state
  • Posted phonon functionality can easily be added with an additional nonce to the card and being able to mark a transaction as “posted”.

Walk through

  1. Two terminals wish to exchange phonons. Each of their terminals requests from their cards their card’s public key, next nonce and phonon list.
  2. They exchange these details and their terminals come to an agreement on which phonons are going to be exchanged. At this point I would say that the cards are “virtually paired”. The terminals have agreed not to pair with any other cards until the number of phonons agreed to be exchaged are exchanged. This is to prevent a transfer being blocked due to a previously consumed transfer having the same or higher nonce.
  3. Once a terminal has sent and received the expected number of phonons it is safe to transact with another card. For example, terminal A told terminal B its next nonce is 3 and it is expecting 3 phonons. Once a transaction with a nonce of 5 is received it can “unpair”.