Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update to keyforge and add sign and verify #113

Merged
merged 4 commits into from
Sep 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.PHONY: all
all: clean build-node build-keygen build-manager
all: clean build-node build-keyforge build-manager

.PHONY: test
test:
Expand All @@ -14,10 +14,10 @@ build-node:
cd cmd/node && go build -o ../../dist/b7s
@echo "\n✅ Done.\n"

.PHONY: build-keygen
build-keygen:
.PHONY: build-keyforge
build-keyforge:
@echo "\n🛠 Building node keygen...\n"
cd cmd/keygen && go build -o ../../dist/b7s-keygen
cd cmd/keyforge && go build -o ../../dist/b7s-keyforge
@echo "\n✅ Done.\n"

.PHONY: build-manager
Expand Down
55 changes: 55 additions & 0 deletions cmd/keyforge/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
## KeyForge

The `keyforge` utility is used for managing cryptographic keys and signing/verifying messages or data. It provides the following options:

### Generate Keys

Generate a new keypair and save it to a file:

$ ./keyforge -o

### Sign and Verify

Sign and verify messages or data using your generated keys:

#### Sign a Message

Sign a message and save the signature:

$ ./keyforge -s "Your message" -o

#### Sign a File

Sign a file and save the signature:

$ ./keyforge -f -o

#### Verify a Signature

Verify a message or file's signature using the \`keyforge\` utility:

$ ./keyforge -pubkey -message "Original message" -signature

#### Verify a Signature with PeerID

Verify a message or file's signature using a PeerID with the \`keyforge\` utility:

$ ./keyforge -peerid -message "Original message" -signature

#### Verify a Signature with OpenSSL

Verify a message or file's signature using OpenSSL:

##### Create a Signature

Use OpenSSL to create a signature:

$ openssl dgst -sha256 -sign -out message.sig

##### Verify a Signature

Use OpenSSL to verify a signature:

$ openssl dgst -sha256 -verify -signature message.sig -in

These commands enable you to manage cryptographic keys and perform signing and verification operations, including using OpenSSL for verification, conveniently within the Blockless b7s Node network.
86 changes: 86 additions & 0 deletions cmd/keyforge/key_management.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package main

import (
"encoding/base64"
"io/ioutil"
"log"
"os"
"path/filepath"

"github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/peer"
)

// LoadOrCreateKeys loads existing keys or creates new ones if not present
func LoadOrCreateKeys(privKeyFile string, outputDir string) (crypto.PrivKey, crypto.PubKey, error) {
var priv crypto.PrivKey
var pub crypto.PubKey
var err error

if _, err := os.Stat(privKeyFile); os.IsNotExist(err) {
priv, pub, err = crypto.GenerateKeyPair(crypto.Ed25519, 0)
if err != nil {
return nil, nil, err
}
} else {
privBytes, err := ioutil.ReadFile(privKeyFile)
if err != nil {
return nil, nil, err
}

priv, err = crypto.UnmarshalPrivateKey(privBytes)
if err != nil {
return nil, nil, err
}
pub = priv.GetPublic()
}

privPayload, err := crypto.MarshalPrivateKey(priv)
if err != nil {
log.Fatalf("Could not marshal private key: %s", err)
}

pubPayload, err := crypto.MarshalPublicKey(pub)
if err != nil {
log.Fatalf("Could not marshal public key: %s", err)
}

identity, err := peer.IDFromPublicKey(pub)
if err != nil {
log.Fatalf("Could not generate identity: %s", err)
}

pubKeyFile := filepath.Join(outputDir, pubKeyName)
err = ioutil.WriteFile(pubKeyFile, pubPayload, pubKeyPermissions)
if err != nil {
log.Fatalf("Could not write public key to file: %s", err)
}

pubKeyTextFile := filepath.Join(outputDir, pubKeyTxtName)
pubKeyBase64 := base64.StdEncoding.EncodeToString(pubPayload)
err = ioutil.WriteFile(pubKeyTextFile, []byte(pubKeyBase64), pubKeyPermissions)
if err != nil {
log.Fatalf("Could not write public key text to file: %s", err)
}

identityFile := filepath.Join(outputDir, identityName)
err = ioutil.WriteFile(identityFile, []byte(identity.Pretty()), pubKeyPermissions)
if err != nil {
log.Fatalf("Could not write identity to file: %s", err)
}

privKeyFile = filepath.Join(outputDir, privKeyName)
err = ioutil.WriteFile(privKeyFile, privPayload, privKeyPermissions)
if err != nil {
log.Fatalf("Could not write private key to file: %s", err)
}

// Write peer ID to file
peerIDFile := filepath.Join(outputDir, peerIDFileName)
err = ioutil.WriteFile(peerIDFile, []byte(identity.Pretty()), pubKeyPermissions)
if err != nil {
log.Fatalf("Could not write peer ID to file: %s", err)
}

return priv, pub, nil
}
67 changes: 67 additions & 0 deletions cmd/keyforge/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package main

import (
"log"
"os"
"path/filepath"

"github.com/spf13/pflag"
)

const (
privKeyName = "priv.bin"
pubKeyName = "pub.bin"
pubKeyTxtName = "pubkey.txt"
identityName = "identity"
peerIDFileName = "peerid.txt"
privKeyPermissions = 0600
pubKeyPermissions = 0644

)

func main() {
var (
flagOutputDir string
flagString string
flagFile string
flagPublicKey string
flagMessage string
flagSignature string
flagPeerID string
)

pflag.StringVar(&flagPeerID, "peerid", "", "PeerID for verification")
pflag.StringVarP(&flagOutputDir, "output", "o", ".", "directory where keys should be stored")
pflag.StringVarP(&flagString, "string", "s", "", "string to sign and verify")
pflag.StringVarP(&flagFile, "file", "f", "", "file to sign and verify")
pflag.StringVar(&flagPublicKey, "pubkey", "", "Base64 encoded public key for verification")
pflag.StringVar(&flagMessage, "message", "", "The original message to verify")
pflag.StringVar(&flagSignature, "signature", "", "Base64 encoded signature to verify")

pflag.Parse()

// Initialize output directory
err := os.MkdirAll(flagOutputDir, os.ModePerm)
if err != nil {
log.Fatalf("Could not create output directory: %s", err)
}

privKeyFile := filepath.Join(flagOutputDir, privKeyName)

priv, pub, err := LoadOrCreateKeys(privKeyFile, flagOutputDir)
if err != nil {
log.Fatalf("Error loading or creating keys: %s", err)
}

if flagString != "" || flagFile != "" {
HandleSignAndVerify(priv, pub, flagString, flagFile, flagOutputDir)
}

if flagPublicKey != "" && flagMessage != "" && flagSignature != "" {
VerifyGivenSignature(flagPublicKey, flagMessage, flagSignature)
}

if flagPeerID != "" && flagMessage != "" && flagSignature != "" {
VerifyGivenSignatureWithPeerID(flagPeerID, flagMessage, flagSignature)
}
}
122 changes: 122 additions & 0 deletions cmd/keyforge/sign_verify.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package main

import (
"encoding/base64"
"fmt"
"io/ioutil"
"log"
"path/filepath"

"github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/peer"
)

// HandleSignAndVerify performs the signing and verification based on the provided keys and flags
func HandleSignAndVerify(priv crypto.PrivKey, pub crypto.PubKey, flagString string, flagFile string, flagOutput string) {
// Sign and verify string
if flagString != "" {
signature, err := priv.Sign([]byte(flagString))
if err != nil {
log.Fatalf("Could not sign string: %s", err)
}

isValid, err := pub.Verify([]byte(flagString), signature)
if err != nil {
log.Fatalf("Could not verify string: %s", err)
}

signatureStr := base64.StdEncoding.EncodeToString(signature)
if isValid {
fmt.Printf("String signature verified successfully. Signature: %s\n", signatureStr)
} else {
fmt.Println("String signature verification failed.")
}
}

// Sign and verify file
if flagFile != "" {
fileData, err := ioutil.ReadFile(flagFile)
if err != nil {
log.Fatalf("Could not read file: %s", err)
}

fileSignature, err := priv.Sign(fileData)
if err != nil {
log.Fatalf("Could not sign file: %s", err)
}

isFileValid, err := pub.Verify(fileData, fileSignature)
if err != nil {
log.Fatalf("Could not verify file: %s", err)
}

signatureFileStr := base64.StdEncoding.EncodeToString(fileSignature)
if isFileValid {
fmt.Printf("File signature verified successfully. Signature: %s\n", signatureFileStr)
} else {
fmt.Println("File signature verification failed.")
}

if flagOutput != "" {
signatureFilePath := filepath.Join(flagOutput, "file_signature.enc.txt")
err := ioutil.WriteFile(signatureFilePath, []byte(signatureFileStr), 0644)
if err != nil {
log.Fatalf("Could not write signature to file: %s", err)
}
}
}
}

// VerifyGivenSignature verifies a message with a given signature and public key
func VerifyGivenSignature(encodedPubKey string, message string, encodedSignature string) {
pubKeyBytes, err := base64.StdEncoding.DecodeString(encodedPubKey)
if err != nil {
log.Fatalf("Could not decode public key: %s", err)
}

pubKey, err := crypto.UnmarshalPublicKey(pubKeyBytes)
if err != nil {
log.Fatalf("Could not unmarshal public key: %s", err)
}

signatureBytes, err := base64.StdEncoding.DecodeString(encodedSignature)
if err != nil {
log.Fatalf("Could not decode signature: %s", err)
}

isValid, err := pubKey.Verify([]byte(message), signatureBytes)
if err != nil {
log.Fatalf("Could not verify string: %s", err)
}

if isValid {
fmt.Println("Signature verified successfully.")
} else {
fmt.Println("Signature verification failed.")
}
}

// VerifyGivenSignatureWithPeerID verifies a message with a given signature and PeerID
func VerifyGivenSignatureWithPeerID(peerIDStr string, message string, encodedSignature string) {
log.Println("Verifying signature with peerid")
peerID, err := peer.Decode(peerIDStr)
if err != nil {
log.Fatalf("Could not decode PeerID: %s", err)
}

pubKey, err := peerID.ExtractPublicKey()
if err != nil || pubKey == nil {
log.Fatalf("Could not extract public key from PeerID: %s", err)
}

pubKeyBytes, err := crypto.MarshalPublicKey(pubKey)
if err != nil {
log.Fatalf("Could not marshal public key to bytes: %s", err)
}

// This will give you a base64 string representation of the public key
pubKeyBase64 := base64.StdEncoding.EncodeToString(pubKeyBytes)
log.Printf("Extracted public key from PeerID (Base64): %s", pubKeyBase64)

VerifyGivenSignature(pubKeyBase64, message, encodedSignature)
}
23 changes: 0 additions & 23 deletions cmd/keygen/README.md

This file was deleted.

Loading