11import crypto from 'crypto'
22import { describe , expect , it } from 'vitest'
3- import { buildKalshiAuthHeaders , generateKalshiSignature } from '@/tools/kalshi/types'
3+ import { generateKalshiSignature } from '@/tools/kalshi/types'
44
55const TIMESTAMP = '1700000000000'
66const PATH = '/trade-api/v2/portfolio/orders'
@@ -11,9 +11,9 @@ function ed25519Pair() {
1111 return { pem : privateKey . export ( { type : 'pkcs8' , format : 'pem' } ) . toString ( ) , publicKey }
1212}
1313
14- function rsaPair ( type : 'pkcs1' | 'pkcs8' ) {
14+ function rsaPkcs8Pair ( ) {
1515 const { privateKey, publicKey } = crypto . generateKeyPairSync ( 'rsa' , { modulusLength : 2048 } )
16- return { pem : privateKey . export ( { type, format : 'pem' } ) . toString ( ) , publicKey }
16+ return { pem : privateKey . export ( { type : 'pkcs8' , format : 'pem' } ) . toString ( ) , publicKey }
1717}
1818
1919function verifiesRsaPss ( publicKey : crypto . KeyObject , signature : string ) : boolean {
@@ -38,57 +38,16 @@ describe('generateKalshiSignature', () => {
3838 ) . toBe ( true )
3939 } )
4040
41- it ( 'signs a PKCS#1 RSA key with RSA-PSS SHA-256' , ( ) => {
42- const { pem, publicKey } = rsaPair ( 'pkcs1' )
43- expect ( verifiesRsaPss ( publicKey , generateKalshiSignature ( pem , TIMESTAMP , 'GET' , PATH ) ) ) . toBe (
44- true
45- )
46- } )
47-
4841 it ( 'signs a PKCS#8 RSA key, whose PEM header matches an Ed25519 one, with RSA-PSS' , ( ) => {
49- const { pem, publicKey } = rsaPair ( 'pkcs8' )
42+ const { pem, publicKey } = rsaPkcs8Pair ( )
5043 expect ( verifiesRsaPss ( publicKey , generateKalshiSignature ( pem , TIMESTAMP , 'GET' , PATH ) ) ) . toBe (
5144 true
5245 )
5346 } )
5447
55- it ( 'signs only the path, dropping the query string' , ( ) => {
56- const { pem, publicKey } = ed25519Pair ( )
57- const signature = generateKalshiSignature ( pem , TIMESTAMP , 'GET' , `${ PATH } ?limit=1` )
58- expect (
59- crypto . verify ( null , Buffer . from ( SIGNED_TEXT ) , publicKey , Buffer . from ( signature , 'base64' ) )
60- ) . toBe ( true )
61- } )
62-
63- it ( 'signs a key pasted with literal \\n sequences on one line' , ( ) => {
64- const { pem, publicKey } = ed25519Pair ( )
65- const signature = generateKalshiSignature ( pem . replace ( / \n / g, '\\n' ) , TIMESTAMP , 'GET' , PATH )
66- expect (
67- crypto . verify ( null , Buffer . from ( SIGNED_TEXT ) , publicKey , Buffer . from ( signature , 'base64' ) )
68- ) . toBe ( true )
69- } )
70-
7148 it ( 'refuses a key of a type Kalshi does not verify' , ( ) => {
7249 const { privateKey } = crypto . generateKeyPairSync ( 'ec' , { namedCurve : 'P-256' } )
7350 const pem = privateKey . export ( { type : 'pkcs8' , format : 'pem' } ) . toString ( )
7451 expect ( ( ) => generateKalshiSignature ( pem , TIMESTAMP , 'GET' , PATH ) ) . toThrow ( / R S A o r E d 2 5 5 1 9 / )
7552 } )
7653} )
77-
78- describe ( 'buildKalshiAuthHeaders' , ( ) => {
79- it ( 'sends the key id, millisecond timestamp, and a signature over them' , ( ) => {
80- const { pem, publicKey } = ed25519Pair ( )
81- const headers = buildKalshiAuthHeaders ( 'key-id' , pem , 'GET' , PATH )
82- expect ( headers [ 'KALSHI-ACCESS-KEY' ] ) . toBe ( 'key-id' )
83- expect ( headers [ 'KALSHI-ACCESS-TIMESTAMP' ] ) . toMatch ( / ^ \d { 13 } $ / )
84- const signed = `${ headers [ 'KALSHI-ACCESS-TIMESTAMP' ] } GET${ PATH } `
85- expect (
86- crypto . verify (
87- null ,
88- Buffer . from ( signed ) ,
89- publicKey ,
90- Buffer . from ( headers [ 'KALSHI-ACCESS-SIGNATURE' ] , 'base64' )
91- )
92- ) . toBe ( true )
93- } )
94- } )
0 commit comments