Skip to content

Commit 11f6c31

Browse files
authored
Commit first update structure.
Update one. 17-NOV-2023. - Setting main library linking programs to the official Keycard Go API. - Also create ipfs_link API - TODO: security harden against memory leaking and lifting malware. Hash all strings in local binary before passing to external libraries, processes and threads.
1 parent 7cf2cbd commit 11f6c31

File tree

3 files changed

+243
-18
lines changed

3 files changed

+243
-18
lines changed

src/libb/ipfs_link.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package ipfs_link
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"os/exec"
7+
"strings"
8+
)
9+
10+
// AddFileToIPFS adds a file to IPFS and returns the CID (Content Identifier)
11+
func AddFileToIPFS(filePath string) (string, error) {
12+
cmd := exec.Command("ipfs", "add", filePath)
13+
14+
var out bytes.Buffer
15+
cmd.Stdout = &out
16+
err := cmd.Run()
17+
if err != nil {
18+
return "", fmt.Errorf("error adding file to IPFS: %w", err)
19+
}
20+
21+
output := out.String()
22+
// Extract CID from the output
23+
lines := strings.Split(output, "\n")
24+
if len(lines) < 2 {
25+
return "", fmt.Errorf("unexpected output from IPFS add")
26+
}
27+
parts := strings.Fields(lines[1])
28+
if len(parts) < 2 {
29+
return "", fmt.Errorf("unexpected output format from IPFS add")
30+
}
31+
cid := parts[1]
32+
33+
return cid, nil
34+
}
35+
36+
// GetFileFromIPFS retrieves a file from IPFS using its CID
37+
func GetFileFromIPFS(cid, outputPath string) error {
38+
cmd := exec.Command("ipfs", "get", cid, "-o", outputPath)
39+
40+
err := cmd.Run()
41+
if err != nil {
42+
return fmt.Errorf("error retrieving file from IPFS: %w", err)
43+
}
44+
45+
return nil
46+
}

src/libb/keycard_link.go

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,74 @@
1-
//
2-
// Library:
3-
// /src/libb/***
4-
// Program:
5-
// Keycard link between IPFSS and the official Keycard Go API
6-
// Possibly place the Go API in /src/libb/API or use git to retrieve the API at build for efficiency
1+
package keycard_link
72

3+
import (
4+
"bufio"
5+
"fmt"
6+
"os"
87

9-
package main
8+
// Import the keycard-go package
9+
keycard "github.com/status-im/keycard-go"
10+
)
1011

11-
import package (
12+
// askPassphrase prompts the user for a passphrase and returns it
13+
func askPassphrase() (string, error) {
14+
reader := bufio.NewReader(os.Stdin)
15+
fmt.Print("Enter a strong but memorable passphrase: ")
16+
passphrase, err := reader.ReadString('\n')
17+
if err != nil {
18+
return "", err
19+
}
20+
return passphrase, nil
21+
}
22+
23+
// callKeycardAPI signs the given passphrase using the Keycard API
24+
func callKeycardAPI(passphrase string) (string, error) {
25+
// Here, you'll need to implement the logic to interact with the Keycard API.
26+
// This will involve establishing a connection to the Keycard usinga PCSC reader and sending
27+
// the passphrase for signing. The specifics will depend on the Keycard API's functionality.
28+
//
29+
// As a placeholder:
30+
signature := "signed_" + passphrase // Replace this with actual Keycard API interaction
31+
return signature, nil
32+
}
33+
34+
// EncryptFile encrypts the given file using GPG with a passphrase
35+
func EncryptFile(filename string) error {
36+
passphrase, err := askPassphrase()
37+
if err != nil {
38+
return fmt.Errorf("error getting passphrase: %w", err)
39+
}
40+
41+
signature, err := callKeycardAPI(passphrase)
42+
if err != nil {
43+
return fmt.Errorf("error signing passphrase: %w", err)
44+
}
45+
46+
// Here, you'll implement the GPG encryption logic using the signed passphrase
47+
// as the encryption key. This might involve calling an external GPG command
48+
// or using a Go package that provides GPG functionality.
49+
50+
// Placeholder for GPG encryption:
51+
fmt.Printf("File %s encrypted with signature %s\n", filename, signature)
52+
53+
return nil
54+
}
55+
56+
// DecryptFile decrypts the given file using GPG with a passphrase
57+
func DecryptFile(filename string) error {
58+
passphrase, err := askPassphrase()
59+
if err != nil {
60+
return fmt.Errorf("error getting passphrase: %w", err)
61+
}
62+
63+
signature, err := callKeycardAPI(passphrase)
64+
if err != nil {
65+
return fmt.Errorf("error signing passphrase: %w", err)
66+
}
1267

13-
)
68+
// Implement the GPG decryption logic here, similar to EncryptFile.
1469

15-
func main (){
70+
// Placeholder for GPG decryption:
71+
fmt.Printf("File %s decrypted with signature %s\n", filename, signature)
1672

73+
return nil
1774
}

src/main.go

Lines changed: 130 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,137 @@
1-
package main
1+
package main
22

3-
import package (
4-
libb/keycard_link.go
5-
libb/ipfs_link.go
3+
import (
4+
"fmt"
5+
"os"
66

7+
"yourproject/src/libb/keycard_link"
8+
"yourproject/src/libb/ipfs_link"
9+
)
710

8-
)
11+
func main() {
12+
checkDependencies()
13+
// Example: Parsing command-line arguments
14+
// You might want to use a more robust way for parsing arguments (like the `flag` package)
15+
if len(os.Args) < 2 {
16+
fmt.Println("Usage: main.go [command]")
17+
os.Exit(1)
18+
}
19+
20+
command := os.Args[1]
21+
22+
switch command {
23+
case "encrypt":
24+
if len(os.Args) != 3 {
25+
fmt.Println("Usage: main.go encrypt [filename]")
26+
os.Exit(1)
27+
}
28+
filename := os.Args[2]
29+
err := encryptFile(filename)
30+
if err != nil {
31+
fmt.Printf("Error encrypting file: %s\n", err)
32+
os.Exit(1)
33+
}
34+
35+
case "decrypt":
36+
if len(os.Args) != 3 {
37+
fmt.Println("Usage: main.go decrypt [filename]")
38+
os.Exit(1)
39+
}
40+
filename := os.Args[2]
41+
err := decryptFile(filename)
42+
if err != nil {
43+
fmt.Printf("Error decrypting file: %s\n", err)
44+
os.Exit(1)
45+
}
46+
47+
default:
48+
fmt.Println("Invalid command")
49+
os.Exit(1)
50+
}
51+
}
52+
func askUserYN(question string) bool {
53+
reader := bufio.NewReader(os.Stdin)
54+
for {
55+
fmt.Printf("%s (y/n): ", question)
56+
response, err := reader.ReadString('\n')
57+
if err != nil {
58+
fmt.Println("Error reading response. Please try again.")
59+
continue
60+
}
61+
response = strings.TrimSpace(strings.ToLower(response))
62+
63+
if response == "y" || response == "yes" {
64+
return true
65+
} else if response == "n" || response == "no" {
66+
return false
67+
} else {
68+
fmt.Println("Invalid response. Please answer 'y' for yes or 'n' for no.")
69+
}
70+
}
71+
}
72+
73+
func checkAndInstallDependencies() error {
74+
dependencies := []string{"git", "ipfs"}
75+
76+
for _, dep := range dependencies {
77+
_, err := exec.LookPath(dep)
78+
if err != nil {
79+
if askUserYN(fmt.Sprintf("'%s' is not installed. Do you want to install it?", dep)) {
80+
err := installDependency(dep)
81+
if err != nil {
82+
return fmt.Errorf("error installing %s: %w", dep, err)
83+
}
84+
}
85+
}
86+
}
87+
return nil
88+
}
89+
90+
func installDependency(dep string) error {
91+
// Implement the logic to install the dependency.
92+
// This is an example using apt-get, adjust according to your system's package manager.
93+
cmd := exec.Command("sudo", "pacman","-S", dep)
94+
cmd.Stdout = os.Stdout
95+
cmd.Stderr = os.Stderr
96+
return cmd.Run()
97+
}
98+
99+
func encryptFile(filename string) error {
100+
encryptedFilePath, err := keycard_link.EncryptFile(filename)
101+
if err != nil {
102+
return fmt.Errorf("error encrypting file: %w", err)
103+
}
104+
fmt.Printf("File encrypted successfully: %s\n", encryptedFilePath)
105+
106+
if askUserYN("Do you want to upload the file to IPFS? [y/n]: ") {
107+
cid, err := ipfs_link.AddFileToIPFS(encryptedFilePath)
108+
if err != nil {
109+
return fmt.Errorf("error uploading file to IPFS: %w", err)
110+
}
111+
fmt.Printf("File uploaded to IPFS with CID: %s\n", cid)
112+
}
113+
114+
return nil // Return nil if successful, or an error if something goes wrong
115+
}
116+
117+
func decryptFile(filename string) error {
118+
// Retrieve the file from IPFS using ipfs_link library
119+
err := ipfs_link.GetFileFromIPFS(/* ... */)
120+
if err != nil {
121+
return fmt.Errorf("error retrieving file from IPFS: %w", err)
122+
}
123+
124+
decryptedData, err := keycard_link.DecryptFile(/* ... */)
125+
if err != nil {
126+
return fmt.Errorf("error decrypting file: %w", err)
127+
}
128+
129+
// Save the decrypted data to a file
130+
// ...
131+
132+
return nil // Return nil if successful, or an error if something goes wrong
133+
}
9134

10-
func main(){
11135

12136

13-
}
14137

15-
func etc etc......

0 commit comments

Comments
 (0)