Comments (11)
Yes david had these concerns. But even if we can use the accountID it is better to have a different field since you should rotate your encryption key periodically. And you might not want the thing decrypting to have access to the secret for the account.
I'm leaning toward adding it to account.
from stellar-protocol.
Can't we just use public key of the account (account ID) for encryption? Recipient can then decrypt it using corresponding secret key of the account.
from stellar-protocol.
Ed25519 keys are not directly useable for encryption (ed25519 is just a digital signature system), and even if not the case, using the account ID directly does not allow for flexibility in the encryption scheme, and finally I've been taught that you shouldn't use the same key in two separate systems (i.e. greater surface area for key compromise).
I have a feeling that David would be very against directly using an account's public key for our memo scheme.
from stellar-protocol.
@nullstyle An interesting counterexample of reusing two ed25519 public keys to create a key exchange for nacl box:
https://github.com/dchest/ed2curve-js
Also supported in agl's Go package:
https://github.com/agl/ed25519/blob/master/extra25519/extra25519.go
Clever stuff :-)
from stellar-protocol.
Worth a read:
https://nacl.cr.yp.to/box.html
The issue worth thinking about is correctly choosing the nonce. Given two accounts A and B, each with an attached account sequence number at the point in time of the transaction, the sum of the two sequences would provide a unique nonce every time for the pairing of A and B's public keys. If the sum overflowed you'd probably need to disallow it as a nonce, but that is unlikely to ever happen :-)
from stellar-protocol.
It was my understanding that compliance would not work without federation... if this is the case I don't see why this should go in core.
In any case, I'd like to if possible create a layered architecture for this and only move things into core when we have a proven case that we need it there as it makes iterating/experimenting much faster
from stellar-protocol.
This is less about compliance (though it is obviously useful there) and more about providing a way for accounts to exchange information securely. But now that you mention it I think it might be better to make this more generic and add the ability to save key/value pairs attached to an account. Created this other issue: #27
from stellar-protocol.
I was thinking last night about how to successfully use the Accounts to share Bank Account Info and other KYC stuff both for a wallet on many machines, and with a counter party.
To keep us on the same page; I'm using Asymmetric PKI to communicate a Symmetric Key stored on the account's properties (aka the password/passphrase/cipherkey for decoding encrypted account data). This technique also applies to encrypted data sent OOB (out-of-band) (like via IPFS) and uses Stellar to communicate the symmetric key value.
Here's what I came up with:
(1)
Dynamically generate a 64-byte symmetric key, double encrypt it (first with a private key (i.e. a msg from alice)/then with the public key (i.e. an envelope to alice)); and stick it in a KVP on the account.
This value is retrievable by any software that can get both the ciphertext (every Stellar connected agent can get this) and both the public and private keys used to encrypt it. The ciphertext is complete gibberish to an attacker because it's an encrypted block of arbitrary random data; the message could validly be any 64 byte value and there's no way to tell what it should be.
(2)
Use this symmetric key to encode all the other data values that you wish to be encrypted. My hope is to somehow use the data from (1) as seed information to make a OneTimePad for each distinct key value on the account (using PSRGs in a way that makes it impossible to attack the PSRG).
One risk to keep in mind is we have to assume would-be attackers will know the value of certain fields stored on the account (like a phone number, bank account number, ssn, etc.). The algorithm must prevent knowing that information from compromising the rest of the encrpyted data (hence my focus on creating a OneTimePad technique because it prevents information leakage from one byte to the next).
Here is a basic psuedocode of the approach:
account.setData("encryptMethod", "OneTimePad")
otp_seed = random(64 bytes)
message = encrypt(private_key, otp_seed) // A message from Alice
envelope = encrypt(public_key, message) // A letter for Alice
account.setData("myOtpSeed", envelope)
key_name = "US/SSN"
raw_data = "mike's super secret ssn"
encrypted_value = otp_encode(otp_seed, key_name, raw_data)
account.setData(key_name, encrypted_value)
To get the values back, retrieve the OTP seed ciphertext; use the private key to decrypt the outside envelope (a message to alice); then the public key (a message from alice); and now you have the OTP seed to decode the encrypted KVP data stored on the account.
Again in psuedocode:
enc_method = account.getData("encryptMethod")
// Use some method/mechanism to call the right decryption method based on the returned value
otp_envelope = account.getData("myOtpSeed")
otp_message = decrypt(private_key, otp_envelope) // Get message in the letter for Alice
otp_seed = decrypt(public_key, otp_message) // Decrypt the message from Alice
key_name = "US/SSN"
ssn_ciphertext = account.getData(key_name)
ssn_value = otp_decode(otp_seed, key_name, ssn_ciphertext)
The agent can now use the decrypted value and reuse the same otp_seed to decrypt other values.
To be clear the otp_seed is a seed for an algorithm generating the one time pad. The key_name is used to create a unique location/address within that pad for 64 bytes of OTP data. The value stored on the account is not the one time pad itself, nor is any value within the dynamically generated one time pad ever reused (each key gets its own unique 64 byte string within the pad).
One advantage here is the OTP seed can be rotated as often as we like. It requires decrypting all the KVPs and reencrypting/restoring them; but that's a rather small burden to bear for an easy to implement "Rotate the account's encryption seed" procedure. The other advantage is the keypair used to encrypt the seed can also be rotated as often as desired; it requires only that the OTP seed be reencrypted, but the data values themselves can be left alone.
As is typical, if the encryption KeyPair is lost; the OTP seed is unrecoverable, along with the encoded data.
That scheme allows me to share encrypted data with myself safely only using OOB storage for the keypair encrpyting the OTP seed.
But I still can't share with other accounts because they don't have my private key (nor am I going to give it to them).
To share that information with another Stellar Account we create a third account that we both share.
If we concatenate our two public account addresses, putting the "numerically lower" one first, then use that as the passphrase for this third account; we can, without prior foreknowledge, create a named account space that we can collaborate through. This also let's me change the answers specifically for that counter party, and let's the counter party populate whatever extra data they wish about my account that we can "share".
shared_account_address = keyPair.fromRawSeed(hash.Hash(AccountAddress1 + AccountAddress2))
We go through essentially the same procedure, but this time we need to store the OTP seed 4 times.
One of the parties generates a 64 bytes of OTP seed.
First they encrypt it with their own private key (a message from them);
Second they encrypt it with the counterparty's public key (an envelope for the counter party);
Third they store the result on the account.
Fourth, they also encrypt it with their own public key and store that on the account too.
This way both parties can decrypt the OTP seed value that account uploaded.
The other two copies of the seed show up when the counterparty checks the account.
It detects that the seed has changed because the copy of the seed that it uploaded (assuming there was one there) does not match what the other account uploaded.
It updates its own copies of the seed information by uploading the new OTP seed value to the two key_names (one for itself, and one for the counterparty) that it "controls".
It can now move on to decoding/encoding KVP values on the account.
Either account can change the OTP seed at any time.
Either account can change the keypair it uses to encrypt the OTP seed at any time.
Whenever the OTP seed itself changes, the account will have to reencrypt all encrypted data on the account. Whenever the keypair used to encrypt the seed changes, it only updates the two encrypted seed values it controls. The counterparty can detect the changes next time it accesses the account.
This technique scales to N accounts by concatenating the public addresses of all accounts involved in numeric ascending order and each account adding an additional encrpyted seed value for each of the other accounts.
The total number of encrypted seed KVPs is N^2. This is required because the private key used by each account involved is secret to each account.
from stellar-protocol.
I recently learned that a "stream cipher" is the name of the thing I described to protect the data.
from stellar-protocol.
Can do this with manage data and an ecosystem proposal
from stellar-protocol.
This is the construction I use in my Interstellar-Whisper example (Alice and Bob share a secret using X25519, Alice is the receiver below, and AES used for encryption):
The 32 byte initiation vector is given by the sum (concatenation) of the first 16 bytes of Alice’s public key (interpreted as an integer) and the sending accounts’ sequence number. Specifically,
IV = (pk_Alice[0:16] + sequence_number)[-16:]
This construction assures that IV is unique and direction-dependent. If Alice sends Bob a message, the IV will be given by the sum of Bob’s public key and the sequence_number of Alice’s account. Even if Alice sends Bob the exact same plaintext within a transaction with the exact same sequence_number for her account, the IV is guaranteed to be different, unless a collision of the first 16 bytes of the public key occurs which is highly unlikely (~1 in 2^64 chance).
Edit: I just realized that xor-ing would be even better than concatenating, no need to take only 16 bytes.
from stellar-protocol.
Related Issues (20)
- SEPs (6, 12, 24, 31): Update callback header from `X-Stellar-Signature` to `Signature` HOT 4
- SEP-9: define a generalized account identifier format HOT 4
- SEP-9: add `bank_account_type` field HOT 2
- SEP-6: /deposit and /withdraw IDs should map to list of transactions rather than a single transaction HOT 22
- SEP-24: make `account` for deposit request optional to match withdraw request
- Add SEP for Soroban token interface HOT 1
- Nice
- SEP-7: thoughts on using "web+stellar://" instead of "web+stellar:"? HOT 1
- SEP-6: standardize structured off-chain deposit instructions for users HOT 1
- SEP-6: Providing deposit instructions asynchronously
- security HOT 1
- SEP-24: Layered fee structure HOT 1
- SEP-24: Configure fees by payment method HOT 1
- SEP-9: support `organization.referrer`
- Add deviation parameter instead of pure uniform periods HOT 8
- Support for `memo` field in SEP-9 Financial Account Fields
- Prettier SEP CI workflow failing suddenly HOT 1
- Blog
- SEP-24 improvements HOT 4
- Prettier should output what the diff is required to make it pass HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from stellar-protocol.