@@ -4,6 +4,7 @@ const ip = require('ip')
4
4
const isIp = require ( 'is-ip' )
5
5
const protocols = require ( './protocols-table' )
6
6
const bs58 = require ( 'bs58' )
7
+ const base32 = require ( 'hi-base32' )
7
8
const varint = require ( 'varint' )
8
9
9
10
module . exports = Convert
@@ -39,6 +40,10 @@ Convert.toString = function convertToString (proto, buf) {
39
40
40
41
case 421 : // ipfs
41
42
return buf2mh ( buf )
43
+ case 444 : // onion
44
+ return buf2onion ( buf )
45
+ case 445 : // onion3
46
+ return buf2onion ( buf )
42
47
default :
43
48
return buf . toString ( 'hex' ) // no clue. convert to hex
44
49
}
@@ -67,6 +72,10 @@ Convert.toBuffer = function convertToBuffer (proto, str) {
67
72
68
73
case 421 : // ipfs
69
74
return mh2buf ( str )
75
+ case 444 : // onion
76
+ return onion2buf ( str )
77
+ case 445 : // onion3
78
+ return onion32buf ( str )
70
79
default :
71
80
return Buffer . from ( str , 'hex' ) // no clue. convert from hex
72
81
}
@@ -131,3 +140,49 @@ function buf2mh (buf) {
131
140
132
141
return bs58 . encode ( address )
133
142
}
143
+
144
+ function onion2buf ( str ) {
145
+ const addr = str . split ( ':' )
146
+ if ( addr . length !== 2 ) {
147
+ throw new Error ( 'failed to parse onion addr: ' + addr + ' does not contain a port number' )
148
+ }
149
+ if ( addr [ 0 ] . length !== 16 ) {
150
+ throw new Error ( 'failed to parse onion addr: ' + addr [ 0 ] + ' not a Tor onion address.' )
151
+ }
152
+ const buf = Buffer . from ( base32 . decode . asBytes ( addr [ 0 ] . toUpperCase ( ) ) )
153
+
154
+ // onion port number
155
+ const port = parseInt ( addr [ 1 ] , 10 )
156
+ if ( port < 1 || port > 65536 ) {
157
+ throw new Error ( 'Port number is not in range(1, 65536)' )
158
+ }
159
+ const portBuf = port2buf ( port )
160
+ return Buffer . concat ( [ buf , portBuf ] )
161
+ }
162
+
163
+ function onion32buf ( str ) {
164
+ const addr = str . split ( ':' )
165
+ if ( addr . length !== 2 ) {
166
+ throw new Error ( 'failed to parse onion addr: ' + addr + ' does not contain a port number' )
167
+ }
168
+ if ( addr [ 0 ] . length !== 56 ) {
169
+ throw new Error ( 'failed to parse onion addr: ' + addr [ 0 ] + ' not a Tor onion3 address.' )
170
+ }
171
+ const buf = Buffer . from ( base32 . decode . asBytes ( addr [ 0 ] . toUpperCase ( ) ) )
172
+
173
+ // onion port number
174
+ const port = parseInt ( addr [ 1 ] , 10 )
175
+ if ( port < 1 || port > 65536 ) {
176
+ throw new Error ( 'Port number is not in range(1, 65536)' )
177
+ }
178
+ const portBuf = port2buf ( port )
179
+ return Buffer . concat ( [ buf , portBuf ] )
180
+ }
181
+
182
+ function buf2onion ( buf ) {
183
+ const addrBytes = buf . slice ( 0 , buf . length - 2 )
184
+ const portBytes = buf . slice ( buf . length - 2 )
185
+ const addr = base32 . encode ( addrBytes ) . toString ( 'ascii' ) . toLowerCase ( )
186
+ const port = buf2port ( portBytes )
187
+ return addr + ':' + port
188
+ }
0 commit comments