| 1 | /** |
| 2 | * Golden wire bytes, as hex. |
| 3 | * |
| 4 | * Everything under `backend`, `rows`, `scram`, and `md5` was captured from a |
| 5 | * live PostgreSQL 16 server by `regenerate.ts` in this directory: the server |
| 6 | * produced those bytes in reply to the frames this codec sent, and it |
| 7 | * accepted every parameter, password, and SCRAM proof along the way. The |
| 8 | * `frontend` entries are this codec's own output for representative |
| 9 | * messages, checked against the message formats in the PostgreSQL protocol |
| 10 | * documentation. |
| 11 | * |
| 12 | * A fresh capture reproduces every value except the four that are unique to a |
| 13 | * session: the SCRAM salt and server nonce, and the backend process id in |
| 14 | * `backendKeyData` and `notificationResponse`. |
| 15 | */ |
| 16 | |
| 17 | export const bytes = (hex: string): Uint8Array => { |
| 18 | const result = new Uint8Array(hex.length / 2) |
| 19 | for (let i = 0; i < result.length; i++) { |
| 20 | result[i] = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16) |
| 21 | } |
| 22 | return result |
| 23 | } |
| 24 | |
| 25 | export const frontend = { |
| 26 | sslRequest: "0000000804d2162f", |
| 27 | cancelRequest: "0000001004d2162e0000003f09e5e380", |
| 28 | startupMessage: |
| 29 | "0000005b00030000757365720065666665637400646174616261736500656666656374006170706c69636174696f6e5f6e616d65006566666563742d70672d636f64656300636c69656e745f656e636f64696e6700555446380000", |
| 30 | parse: "500000001773310053454c45435420243100000100000017", |
| 31 | bind: "42000000207031007331000001000100020000000400000001ffffffff00010001", |
| 32 | execute: "450000000b70310000000005", |
| 33 | describeStatement: "440000000853733100", |
| 34 | closePortal: "430000000850703100", |
| 35 | sync: "5300000004", |
| 36 | flush: "4800000004", |
| 37 | terminate: "5800000004", |
| 38 | passwordMessage: "700000000b6d643561626300", |
| 39 | saslInitialResponse: "7000000019534352414d2d5348412d32353600000000036e2c2c", |
| 40 | saslInitialResponseEmpty: "7000000016534352414d2d5348412d32353600ffffffff", |
| 41 | saslResponse: "7000000007010203" |
| 42 | } as const |
| 43 | |
| 44 | export const backend = { |
| 45 | authenticationOk: "520000000800000000", |
| 46 | authenticationCleartextPassword: "520000000800000003", |
| 47 | authenticationMD5Password: "520000000c0000000570e7d45e", |
| 48 | authenticationSASL: "52000000170000000a534352414d2d5348412d3235360000", |
| 49 | authenticationSASLContinue: |
| 50 | "52000000590000000b723d6566666563746e6f6e636530313233343536373839346144344f4d2b625a387865755769306f433133614357742c733d4442526d4e34586939694d4f6f31745a6673692b48673d3d2c693d34303936", |
| 51 | authenticationSASLFinal: |
| 52 | "52000000360000000c763d34674158727358386e69784873545861573056724b31784c763173315a644f52744e757a6e4f79455a72493d", |
| 53 | parameterStatus: "5300000017696e5f686f745f7374616e646279006f666600", |
| 54 | backendKeyData: "4b0000000c0000003f09e5e380", |
| 55 | readyForQuery: "5a0000000549", |
| 56 | rowDescription: "540000002e00026100000000000000000000170004ffffffff0001620000000000000000000019ffffffffffff0001", |
| 57 | dataRowTwoColumns: "4400000013000200000004000000010000000178", |
| 58 | dataRowWithNull: "44000000160002000000080000000000000007ffffffff", |
| 59 | parameterDescription: "740000000a000100000014", |
| 60 | commandComplete: "430000000d53454c454354203100", |
| 61 | parseComplete: "3100000004", |
| 62 | bindComplete: "3200000004", |
| 63 | closeComplete: "3300000004", |
| 64 | portalSuspended: "7300000004", |
| 65 | emptyQueryResponse: "4900000004", |
| 66 | noData: "6e00000004", |
| 67 | errorResponse: |
| 68 | "4500000041534552524f5200564552524f5200433232303132004d6469766973696f6e206279207a65726f0046696e742e63004c3837300052696e74346469760000", |
| 69 | noticeResponse: |
| 70 | "4e0000007f534e4f5449434500564e4f5449434500433030303030004d7461626c6520226566666563745f6d697373696e675f7461626c652220646f6573206e6f742065786973742c20736b697070696e6700467461626c65636d64732e63004c31333236005244726f704572726f724d73674e6f6e4578697374656e740000", |
| 71 | notificationResponse: "41000000240000003f6566666563745f6368616e6e656c007061796c6f6164207465787400" |
| 72 | } as const |
| 73 | |
| 74 | /** |
| 75 | * One `DataRow` message per value, each the reply to `SELECT $1::<type>` with |
| 76 | * binary parameters and binary results. |
| 77 | */ |
| 78 | export const rows = { |
| 79 | bool: "440000000b00010000000101", |
| 80 | int2: "440000000c000100000002cfc7", |
| 81 | int4: "440000000e0001000000047fffffff", |
| 82 | int8Max: "44000000120001000000087fffffffffffffff", |
| 83 | int8Min: "44000000120001000000088000000000000000", |
| 84 | oid: "440000000e000100000004ffffffff", |
| 85 | regclass: "440000000e000100000004ffffffff", |
| 86 | float4: "440000000e0001000000043fc00000", |
| 87 | float8: "4400000012000100000008c008800000000000", |
| 88 | numeric: "440000001800010000000e0003000100000004000109291a85", |
| 89 | numericSmall: "440000001400010000000a0001ffff000000040001", |
| 90 | numericNegative: "440000001c000100000012000500044000000026941538044a1de60c8a", |
| 91 | numericNaN: "440000001200010000000800000000c0000000", |
| 92 | text: "440000001400010000000a68c3a96c6c6f20e29883", |
| 93 | varchar: "440000000d000100000003616263", |
| 94 | bpchar: "440000000c0001000000027879", |
| 95 | name: "4400000013000100000009736f6d655f6e616d65", |
| 96 | bytea: "440000000e0001000000040001feff", |
| 97 | json: "440000001e0001000000147b2261223a5b312c325d2c2262223a6e756c6c7d", |
| 98 | jsonb: "4400000023000100000019017b2261223a205b312c20325d2c202262223a206e756c6c7d", |
| 99 | uuid: "440000001a0001000000106ba7b8109dad11d180b400c04fd430c8", |
| 100 | inet4: "440000001200010000000802200004c0a80001", |
| 101 | inet4Masked: "440000001200010000000802180004c0a80001", |
| 102 | inet6: "440000001e0001000000140380001020010db8000000000000000000000001", |
| 103 | cidr: "4400000012000100000008020801040a000000", |
| 104 | date: "440000000e00010000000400002279", |
| 105 | dateInfinity: "440000000e0001000000047fffffff", |
| 106 | dateNegInfinity: "440000000e00010000000480000000", |
| 107 | time: "44000000120001000000080000000a8bda1c00", |
| 108 | timetz: "440000001600010000000c0000000a8bda1c00ffffe3e0", |
| 109 | timestamp: "44000000120001000000080002bcc0f6ffcbb8", |
| 110 | timestampInfinity: "44000000120001000000087fffffffffffffff", |
| 111 | timestamptz: "44000000120001000000080002bcc0f6ffcbb8", |
| 112 | timestamptzNegInfinity: "44000000120001000000088000000000000000", |
| 113 | int4ArrayWithNulls: |
| 114 | "440000003200010000002800000001000000010000001700000003000000010000000400000001ffffffff00000004fffffffd", |
| 115 | textArrayEmpty: "440000001600010000000c000000000000000000000019", |
| 116 | timestamptzArray: |
| 117 | "440000003a0001000000300000000100000001000004a0000000030000000100000008fffca2fec4c82000ffffffff000000080002bcc0f6fdeb40" |
| 118 | } as const |
| 119 | |
| 120 | /** |
| 121 | * A complete SCRAM-SHA-256 exchange with PostgreSQL 16, for user `effect` |
| 122 | * with password `secret`. The server accepted `clientFinalMessage` and |
| 123 | * replied with `serverFinalMessage`. |
| 124 | */ |
| 125 | export const scram = { |
| 126 | password: "secret", |
| 127 | clientNonce: "effectnonce0123456789", |
| 128 | clientFirstMessage: "n,,n=,r=effectnonce0123456789", |
| 129 | serverFirstMessage: "r=effectnonce01234567894aD4OM+bZ8xeuWi0oC13aCWt,s=DBRmN4Xi9iMOo1tZfsi+Hg==,i=4096", |
| 130 | clientFinalMessage: |
| 131 | "c=biws,r=effectnonce01234567894aD4OM+bZ8xeuWi0oC13aCWt,p=MzbwxN5OtYdVrj5y4YLvTcjQEOgJaNmODnCVqny303A=", |
| 132 | serverFinalMessage: "v=4gAXrsX8nixHsTXaW0VrK1xLv1s1ZdORtNuznOyEZrI=" |
| 133 | } as const |
| 134 | |
| 135 | /** An `AuthenticationMD5Password` challenge and the reply the server accepted. */ |
| 136 | export const md5 = { |
| 137 | user: "effect", |
| 138 | password: "secret", |
| 139 | salt: "70e7d45e", |
| 140 | expected: "md5dc8f3c0ed2dd6e3843d5b7623544d96b" |
| 141 | } as const |