View difference between Paste ID: bp5RKXuC and zatuLeVJ
SHOW: | | - or go back to the newest paste.
1-
/*Stealth Short Payment IDs - proposal for shortening "user" payment IDs (to 64 bit) while keeping full 32 byte "blockchain" payment IDs, incorporating a stealth feature to improve anonymity, and adding a new v2 integrated address
1+
/*Stealth Short Payment IDs - proposal for shortening both "user" and "blockchain" payment IDs to 64 bit, incorporating a stealth feature to improve anonymity, and adding a new shorter v2 integrated address
2
3
We are basically discussing three different aspects here, which aren't strictly related:
4
1. Stealth IDs, which change every TX, just like (or rather, similar to) addresses
5
6-
2. Shortened IDs, less characters to display, copy, etc. The current space 2^256 is absurdly large and unnecessary, but whether that justifies changing (while the "network" version remains 256-bit), I'm not sure. CN addresses are "long" in any case, but I believe there's a cutoff point around 110-120 characters that results in line wrapping even on 1080p screens on many webpages. I think it's warranted to try to keep it under that bound if there is little reason not to. I guess it boils down to: is public address space precious even though it's already very long, or is "wasting" more characters not of any/much consequence?
6+
2. Shortened IDs, less characters to display, copy, store, etc. The current space 2^256 is absurdly large and unnecessary; this proposal reduces size on chain to 1/4th.
7
Example Addresses:
8
Standard (95):
9
45BEPXEXAN6YrvHgP3owF8GCzBZ2vCZNb9sMxZG6D7iuSvjVret5ciY2GfqVMHZiPoTEEcmSmVhcyaReTjJafrSqV26ZoYE
10
64-bit ID integrated (106):
11
4TZ76dT4mbsizsTtJzy7kYBo9f8xduc8wTsWb86pCmx5Cmh43CDxNS1FRcMrE3CNQ2ZT17vzCudc5TbNYBzizwqZFah5K1Js7VpL88qPSi
12
Full 256-bit ID integrated (139):
13
4LRv6jJYxh5Ba1Z4UfCZYmTzP7g1mP5uUC32KgWcMtBi2QV6xGjHpqs5ZeEnpAwaWVNgF7b7xtumQGoL9posmQMfRvFupJBXkZyWGdcDizfMUAiEgrG7cA98yf6vcqJzZT1EPg8A69e
14
15-
3. New (v2) integrated addresses: not strictly necessary, unless implementing 2 as well.
15+
3. New (v2) integrated addresses to replace/deprecate v1, which isn't in use yet.
16
17-
Part of the idea is to not keep changing things all the time, so it seems reasonable to (at least try to) get it into a state where it can operate for years with no additional changes. #3 acts as a nice way to "tie it up with a bow", because shorter is better than longer (right?), and it creates an easy way to "enable" stealth IDs as the receivers take the time to implement them. If you just implement tx construction logic for stealth IDs, the existing payment ID implementation breaks (that seems bad). Thus if a receiver hands out v2 integrated addresses, they would be expected to support stealth IDs; if not, then use old method.
17+
We want to get the payment ID scheme to a point where it is ready for years of use with no further changes. To maintain compatibility with the current payment ID scheme during the transition, stealth payment IDs will only be generated by default through the use of integrated addresses. Thus, when recipients are ready to accept the new stealth version, they'd hand out integrated addresses.
18
19-
If shortening "user" payment IDs gets a general nack (there are some possibly valid considerations about out-of-band revealing of unwanted data by the ID generator/higher chance of "accidental" collision, etc, with a smaller set size), I would recommend the solution be to re-purpose the "existing" integrated address to use stealth logic (since no one has implemented it yet, it's not in a tagged release, etc) and continue to treat manual payment IDs the same as today (untouched). Even with consensus for shortening, I still feel it appropriate to "overwrite" v1 integrated addresses with the new short version; since no one supports them yet, we can avoid supporting them into perpetuity.
19+
This new 64 bit ID will be given a new tx_extra nonce tag: 0x01 (current payment ID is 0x00).
20
21-
Chance of collision for randomly generating 1 million IDs at 64-bit: 1,000,000^2 / (2^64 * 2) = ~1/36,893,488
21+
With 64 IDs, there's a non-negligible chance for collision if randomly generating. So recipients generating them randomly are advised to sanity check them for uniqueness.
22-
50% chance happens at 5.06 billion IDs generated.
22+
Example: 1 million IDs at 64-bit (simplified): 1,000,000^2 / (2^64 * 2) = ~1/36,893,488
23-
If receivers are randomly generating IDs (and they should be, to avoid revealing data to their customers) with non-negligible chance of collision, values should be checked against existing.
23+
50% chance happens around 5.06 billion IDs generated.
24
25
For reference to those unfamiliar with the integrated address in current head, it looks like:
26-
"netbyte (0x13)" + "32 byte public spend key" + "32 byte public view key" + "32 byte payment ID (8 byte proposed for v2)" + "4 byte checksum of all previous data"
26+
"netbyte (0x13 [standard Monero is 0x12])" + "32 byte public spend key" + "32 byte public view key" + "32 byte payment ID (8 byte proposed for v2)" + "4 byte checksum of all previous data"
27
*/
28-
Another option for v2 integrated addresses is variable length IDs. This loses the consistency of all addresses being the same cnBase58 and hex length (BTC has the same hex length, but variable base58 length), but is only marginally more difficult for wallets to parse and account for.
28+
29
/*
30
For our stealth key, we will use a derivation of the shared secret used for public key generation. The varint encoding used by output indices gives us 128 1-byte options to use as part of our key:
31-
/*varint analysis for key generation for those unfamiliar with varint encoding (I was)
31+
0x80 - 0xFF
32-
1 = 0x01
32+
33-
127 = 0x7f
33+
I've not come up with any not-completely-arbitrary choice, so here's an arbitrary one: charcode(I) + charcode(D) = 0x49 + 0x44 = 0x8d
34-
128 = 0x8001
34+
35-
129 = 0x8101
35+
encryption key = H(sharedSecret + 0x8d) // "+" is append
36-
255 = 0xff01
36+
37-
256 = 0x8002
37+
38-
16,383 = 0xff7f
38+
//apologies for using javascript, it's the easiest way for me to express the implementation proposal
39-
16,384 = 0x808001
39+
40-
16,385 = 0x818001
40+
41
//---------------------------------------------------------
42-
We have to avoid using any valid varints, as those are used for output indexes. 0x80 - 0xff gives us 128 options using only one byte. I've not come up with any not-completely-arbitrary choice, so here's an arbitrary one: charcode(I) + charcode(D) = 0x49 + 0x44 = 0x8d
42+
//proposal 1.5 (older ideas discarded as subpar and/or unscalable)
43
//xor payment ID with one-time key
44
var receiverKeys = create_address(rand_32()); //for example only
45-
//apologies for using javascript, it's the easiest way at present for me to express the implementation proposal
45+
46
var txkey = random_keypair();
47
var der = generate_key_derivation(receiverKeys.view.pub, txkey.sec);
48
var stealthKey = cn_fast_hash(der + "8d").slice(0,16);
49-
//proposal 1.4.2 (older ideas discarded as subpar and/or unscalable)
49+
var encPayId = hexXor(stealthKey, PayId); //JS can only xor numbers, made up function to xor hex strings
50-
//pad the short ID to 32-bytes, then xor with our one-time key
50+
51
//receiver would:
52
var der = generate_key_derivation(txkey.pub, receiverKeys.view.sec); //txkey.pub from tx_extra
53-
var paddedPayId = payId;
53+
var stealthKey = cn_fast_hash(der + "8d").slice(0,16);
54-
while (paddedPayId.length < 64){paddedPayId += "00";}
54+
var payId = hexXor(stealthKey, encPayId); //encPayId from tx_extra
55
//*compare payID with known set*
56
//---------------------------------------------------------
57-
var stealthKey = cn_fast_hash(der + "8d");
57+
58-
var realPayId = hexXor(stealthKey, paddedPayId); //JS can only xor numbers, made up function to xor hex strings
58+
59
//Feedback welcome,
60
//luigi1111