Skip to content

Commit

Permalink
add bitcoind rpc auth generator
Browse files Browse the repository at this point in the history
  • Loading branch information
ramin committed May 17, 2023
1 parent d00456c commit 984a176
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 0 deletions.
60 changes: 60 additions & 0 deletions bitcoind/rpc/rpc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package rpc

import (
"crypto/hmac"
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"fmt"
)

type Credentials struct {
Username string
Password string
Salt string
HMACPassword string
RPCAuth string
}

func (c *Credentials) GenerateSalt(size int) (string, error) {
bytes := make([]byte, size)
if _, err := rand.Read(bytes); err != nil {
return "", err
}
return hex.EncodeToString(bytes), nil
}

func (c *Credentials) GeneratePassword() (string, error) {
bytes := make([]byte, 32)
if _, err := rand.Read(bytes); err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(bytes), nil
}

func (c *Credentials) PasswordToHmac(salt, password string) string {
mac := hmac.New(sha256.New, []byte(salt))
mac.Write([]byte(password))
return hex.EncodeToString(mac.Sum(nil))
}

func (c *Credentials) Generate() (string, error) {
if c.Password == "" {
password, err := c.GeneratePassword()
if err != nil {
return "", err
}
c.Password = password
}

salt, err := c.GenerateSalt(16)
if err != nil {
return "", err
}
c.Salt = salt
c.HMACPassword = c.PasswordToHmac(salt, c.Password)
details := fmt.Sprintf("rpcauth=%s:%s$%s", c.Username, c.Salt, c.HMACPassword)
c.RPCAuth = details
return c.RPCAuth, nil
}
41 changes: 41 additions & 0 deletions bitcoind/rpc/rpc_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package rpc

import "testing"

func TestGenerateSalt(t *testing.T) {
c := Credentials{}
salt, err := c.GenerateSalt(16)
if err != nil {
t.Error(err)
}
if len(salt) != 32 {
t.Errorf("Expected salt to be 32 bytes long, got %d", len(salt))
}
}

func TestGeneratePassword(t *testing.T) {
c := Credentials{}
password, err := c.GeneratePassword()
if err != nil {
t.Error(err)
}
if len(password) != 44 {
t.Errorf("Expected password to be 44 bytes long, got %d", len(password))
}
}

func TestPasswordToHmac(t *testing.T) {
c := Credentials{}
salt, err := c.GenerateSalt(16)
if err != nil {
t.Error(err)
}
password, err := c.GeneratePassword()
if err != nil {
t.Error(err)
}
hmac := c.PasswordToHmac(salt, password)
if len(hmac) != 64 {
t.Errorf("Expected hmac to be 64 bytes long, got %d", len(hmac))
}
}
45 changes: 45 additions & 0 deletions cli/commands/resources/rpc/credentials/credentials.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package credentials

import (
"fmt"

"github.com/edobtc/cloudkit/bitcoind/rpc"

log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

var (
username string
password string
)

func init() {
Cmd.Flags().StringVarP(&username, "username", "u", "", "username")
Cmd.Flags().StringVarP(&password, "password", "p", "", "password")
Cmd.MarkFlagRequired("username")
}

// Cmd is the top level relay
// command to export
var Cmd = &cobra.Command{
Use: "credentials",
Short: "credentials",
Run: func(cmd *cobra.Command, args []string) {
c := rpc.Credentials{
Username: username,
Password: password,
}

data, err := c.Generate()
if err != nil {
log.Error(err)
return
}

fmt.Println("add this to your bitcoin.conf file:")
fmt.Println(data)
fmt.Println("")
fmt.Println("your password is:", c.Password)
},
}
20 changes: 20 additions & 0 deletions cli/commands/resources/rpc/rpc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package rpc

import (
"github.com/edobtc/cloudkit/cli/commands/resources/rpc/credentials"
"github.com/spf13/cobra"
)

// Cmd is the top level relay
// command to export
var Cmd = &cobra.Command{
Use: "rpc",
Short: "rpc",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
},
}

func init() {
Cmd.AddCommand(credentials.Cmd)
}
2 changes: 2 additions & 0 deletions cmd/cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/edobtc/cloudkit/cli/commands/relay"
"github.com/edobtc/cloudkit/cli/commands/resources"
"github.com/edobtc/cloudkit/cli/commands/resources/keys"
"github.com/edobtc/cloudkit/cli/commands/resources/rpc"
"github.com/edobtc/cloudkit/cli/commands/settings"
"github.com/edobtc/cloudkit/cli/commands/status"
"github.com/edobtc/cloudkit/version"
Expand Down Expand Up @@ -48,6 +49,7 @@ func bootstrap() {
bck.AddCommand(config.Cmd)
bck.AddCommand(events.Cmd)
bck.AddCommand(keys.Cmd)
bck.AddCommand(rpc.Cmd)
bck.AddCommand(relay.Cmd)
bck.AddCommand(settings.Cmd)
bck.AddCommand(status.Cmd)
Expand Down

0 comments on commit 984a176

Please sign in to comment.