@@ -4,7 +4,7 @@ import * as https from 'https';
4
4
import { makeDestroyable , DestroyableServer } from 'destroyable-server' ;
5
5
6
6
import { expect } from 'chai' ;
7
- import { getDeferred } from './test-util' ;
7
+ import { getDeferred , streamToBuffer } from './test-util' ;
8
8
9
9
import {
10
10
getTlsFingerprintData ,
@@ -89,4 +89,41 @@ describe("Read-TLS-Fingerprint", () => {
89
89
] ) ;
90
90
} ) ;
91
91
92
+ it ( "calculates the same fingerprint as ja3.zone" , async ( ) => {
93
+ server = makeDestroyable ( new net . Server ( ) ) ;
94
+
95
+ server . listen ( ) ;
96
+ await new Promise ( ( resolve ) => server . on ( 'listening' , resolve ) ) ;
97
+
98
+ let incomingSocketPromise = getDeferred < net . Socket > ( ) ;
99
+ server . on ( 'connection' , ( socket ) => incomingSocketPromise . resolve ( socket ) ) ;
100
+
101
+ const port = ( server . address ( ) as net . AddressInfo ) . port ;
102
+ https . request ( {
103
+ host : 'localhost' ,
104
+ port
105
+ } ) . on ( 'error' , ( ) => { } ) ; // Socket will fail, since server never responds, that's OK
106
+
107
+ const incomingSocket = await incomingSocketPromise ;
108
+ const ourFingerprint = await getTlsFingerprintAsJa3 ( incomingSocket ) ;
109
+
110
+ const remoteFingerprint = await new Promise ( ( resolve , reject ) => {
111
+ const response = https . get ( 'https://check.ja3.zone/' ) ;
112
+ response . on ( 'response' , async ( resp ) => {
113
+ if ( resp . statusCode !== 200 ) reject ( new Error ( `Unexpected ${ resp . statusCode } from ja3.zon` ) ) ;
114
+
115
+ try {
116
+ const rawData = await streamToBuffer ( resp ) ;
117
+ const data = JSON . parse ( rawData . toString ( ) ) ;
118
+ resolve ( data . hash ) ;
119
+ } catch ( e ) {
120
+ reject ( e ) ;
121
+ }
122
+ } ) ;
123
+ response . on ( 'error' , reject ) ;
124
+ } ) ;
125
+
126
+ expect ( ourFingerprint ) . to . equal ( remoteFingerprint ) ;
127
+ } ) ;
128
+
92
129
} ) ;
0 commit comments