44// sign messages using Ed25519 private keys in the standard Solana keypair format.
55//
66// Usage:
7- // go-sol-sign -keypair <path> -message <message> [-format base64|hex]
7+ // go-sol-sign -keypair <path> -message <message> [-format base64|hex|base58 ]
88//
99// Examples:
1010// go-sol-sign -keypair ~/.config/solana/id.json -message "Hello World"
1111// go-sol-sign -keypair ./keypair.json -message "Test" -format hex
12+ // go-sol-sign -private-key "base58key" -message "Test" -format base58
1213package main
1314
1415import (
@@ -40,7 +41,7 @@ func main() {
4041 privateKey = flag .String ("private-key" , "" , "Private key as base58 string (alternative to -keypair)" )
4142 message = flag .String ("message" , "" , "Message to sign" )
4243 messageFile = flag .String ("message-file" , "" , "Path to file containing message to sign" )
43- outputFormat = flag .String ("format" , "base64" , "Output format: base64, hex" )
44+ outputFormat = flag .String ("format" , "base64" , "Output format: base64, hex, base58 " )
4445 version = flag .Bool ("version" , false , "Show version information" )
4546 verbose = flag .Bool ("verbose" , false , "Enable verbose output" )
4647 )
@@ -76,7 +77,7 @@ func main() {
7677 }
7778
7879 if * message != "" {
79- messageText = * message
80+ messageText = processEscapeSequences ( * message )
8081 } else if * messageFile != "" {
8182 data , err := os .ReadFile (* messageFile )
8283 if err != nil {
@@ -148,11 +149,26 @@ func main() {
148149 fmt .Println (base64 .StdEncoding .EncodeToString (signature ))
149150 case "hex" :
150151 fmt .Println (hex .EncodeToString (signature ))
152+ case "base58" :
153+ fmt .Println (base58Encode (signature ))
151154 default :
152- log .Fatalf ("Unknown format: %s. Supported formats: base64, hex" , * outputFormat )
155+ log .Fatalf ("Unknown format: %s. Supported formats: base64, hex, base58 " , * outputFormat )
153156 }
154157}
155158
159+ // processEscapeSequences converts escape sequences like \n, \t, etc. to actual characters
160+ func processEscapeSequences (input string ) string {
161+ // Handle common escape sequences
162+ result := input
163+ result = strings .ReplaceAll (result , "\\ n" , "\n " )
164+ result = strings .ReplaceAll (result , "\\ t" , "\t " )
165+ result = strings .ReplaceAll (result , "\\ r" , "\r " )
166+ result = strings .ReplaceAll (result , "\\ \\ " , "\\ " )
167+ result = strings .ReplaceAll (result , "\\ \" " , "\" " )
168+ result = strings .ReplaceAll (result , "\\ '" , "'" )
169+ return result
170+ }
171+
156172// printUsage displays usage information
157173func printUsage () {
158174 fmt .Printf ("%s v%s - %s\n \n " , ToolName , Version , ToolDescription )
@@ -167,14 +183,15 @@ func printUsage() {
167183 fmt .Println (" -message-file string Path to file containing message" )
168184 fmt .Println ("" )
169185 fmt .Println ("Other Options:" )
170- fmt .Println (" -format string Output format: base64, hex (default: base64)" )
186+ fmt .Println (" -format string Output format: base64, hex, base58 (default: base64)" )
171187 fmt .Println (" -verbose Enable verbose output" )
172188 fmt .Println (" -version Show version information" )
173189 fmt .Println ("" )
174190 fmt .Println ("Examples:" )
175191 fmt .Printf (" %s -keypair ~/.config/solana/id.json -message \" Hello World\" \n " , ToolName )
176192 fmt .Printf (" %s -private-key 3yD2... -message \" Test\" -format hex\n " , ToolName )
177193 fmt .Printf (" %s -keypair ./keypair.json -message-file ./message.txt\n " , ToolName )
194+ fmt .Printf (" %s -private-key 3yD2... -message \" Test\" -format base58\n " , ToolName )
178195 fmt .Printf (" %s -version\n " , ToolName )
179196}
180197
@@ -294,3 +311,46 @@ func base58Decode(s string) ([]byte, error) {
294311
295312 return result , nil
296313}
314+
315+ // Simple base58 encoder for Solana signatures
316+ func base58Encode (input []byte ) string {
317+ const alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
318+
319+ if len (input ) == 0 {
320+ return ""
321+ }
322+
323+ // Count leading zeros
324+ leadingZeros := 0
325+ for i := 0 ; i < len (input ) && input [i ] == 0 ; i ++ {
326+ leadingZeros ++
327+ }
328+
329+ // Convert to base58
330+ var result []byte
331+ for i := leadingZeros ; i < len (input ); i ++ {
332+ carry := int (input [i ])
333+ for j := 0 ; j < len (result ); j ++ {
334+ carry += int (result [j ]) * 256
335+ result [j ] = byte (carry % 58 )
336+ carry /= 58
337+ }
338+
339+ for carry > 0 {
340+ result = append (result , byte (carry % 58 ))
341+ carry /= 58
342+ }
343+ }
344+
345+ // Convert to alphabet characters
346+ var encoded []byte
347+ for i := 0 ; i < leadingZeros ; i ++ {
348+ encoded = append (encoded , '1' )
349+ }
350+
351+ for i := len (result ) - 1 ; i >= 0 ; i -- {
352+ encoded = append (encoded , alphabet [result [i ]])
353+ }
354+
355+ return string (encoded )
356+ }
0 commit comments