mirror of
https://github.com/rwinkhart/cmutton.git
synced 2026-08-27 20:36:31 -04:00
Port crypt package
This commit is contained in:
@@ -1,12 +1,10 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
/*
|
// #include <string.h>
|
||||||
typedef struct {
|
// #include <stdlib.h>
|
||||||
char* data;
|
// #include "types.h"
|
||||||
int len;
|
|
||||||
} PascalString;
|
|
||||||
*/
|
|
||||||
import "C"
|
import "C"
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
// getPascalString returns a pascal
|
// getPascalString returns a pascal
|
||||||
// string struct for the input Go string.
|
// string struct for the input Go string.
|
||||||
@@ -28,3 +26,24 @@ func getPascalStringFromBytes(goBytes []byte) C.PascalString {
|
|||||||
len: C.int(len(goBytes)),
|
len: C.int(len(goBytes)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPascalStringFromCString is a helper meant to be used from C.
|
||||||
|
//
|
||||||
|
//export GetPascalStringFromCString
|
||||||
|
func GetPascalStringFromCString(cString *C.char) C.PascalString {
|
||||||
|
return C.PascalString{
|
||||||
|
data: cString,
|
||||||
|
len: C.int(C.strlen(cString)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FreeArray frees the memory allocated by a C-allocated array.
|
||||||
|
//
|
||||||
|
//export FreeArray
|
||||||
|
func FreeArray(items *C.PascalString, count C.int) {
|
||||||
|
linesSlice := (*[1 << 30]C.PascalString)(unsafe.Pointer(items))[:count:count]
|
||||||
|
for i := 0; i < int(count); i++ {
|
||||||
|
C.free(unsafe.Pointer(linesSlice[i].data))
|
||||||
|
}
|
||||||
|
C.free(unsafe.Pointer(items))
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,23 +12,40 @@ to export to C.
|
|||||||
All relevant exported libmutton functions have C functions of the same name.
|
All relevant exported libmutton functions have C functions of the same name.
|
||||||
Functions with multiple return values all have CGO-generated structs to store the return values.
|
Functions with multiple return values all have CGO-generated structs to store the return values.
|
||||||
These structs are named `<FunctionName>_return`, as per CGO.
|
These structs are named `<FunctionName>_return`, as per CGO.
|
||||||
All functions continue to perform the same basic operations, with a couple caveats:
|
All functions perform similar basic operations, with a couple caveats:
|
||||||
- Anything that would normally return a Go error now returns a null-terminated *C.char containing the error string.
|
- Anything that would normally return a Go error now returns a null-terminated *C.char containing the error string.
|
||||||
These are safe to null-terminate because their values are much more predictable than other strings.
|
These are safe to null-terminate because their values are much more predictable than other strings.
|
||||||
Errors are always the *first* return value, so they can always be referenced with `<result>.r0`.
|
Errors are always the *first* return value, so they can always be referenced with `<result>.r0`.
|
||||||
- Anything that would normally return a Go string or byte slice now returns a C.PascalString struct.
|
- Many things that would normally require/return a Go string or byte slice now require/return a C.PascalString struct.
|
||||||
This is to avoid bugs with null-terminated strings.
|
This is to avoid bugs with null-terminated strings.
|
||||||
|
|
||||||
Additionally, since comments tend to fall out of date, please rely on the [Go documentation for libmutton](https://pkg.go.dev/github.com/rwinkhart/libmutton). Documentation for the CGO bindings present in this repo only specify return values.
|
Additionally, since comments tend to fall out of date, please rely on the [Go documentation for libmutton](https://pkg.go.dev/github.com/rwinkhart/libmutton). Documentation for the CGO bindings present in this repo only specify return values.
|
||||||
### Example (libmutton's global.DirInit)
|
### Example (decrypting and printing lines of a libmutton entry)
|
||||||
Build the following example with `gcc <filename> ./cmutton.a`.
|
Build the following example with `gcc <filename> ./cmutton.a`.
|
||||||
```c
|
```c
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include "cmutton.h" // import cmutton
|
#include "cmutton.h" // import cmutton
|
||||||
|
|
||||||
|
static void read_input(const char *prompt, char *buffer, size_t size) {
|
||||||
|
printf("%s", prompt);
|
||||||
|
fflush(stdout);
|
||||||
|
if (fgets(buffer, size, stdin) == NULL) {
|
||||||
|
fprintf(stderr, "Error reading user input\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
// remove trailing newline
|
||||||
|
buffer[strlen(buffer)-1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
char vanityPath[256];
|
||||||
|
char password[256];
|
||||||
|
read_input("Enter vanity path: ", vanityPath, sizeof(vanityPath));
|
||||||
|
read_input("Enter password: ", password, sizeof(password));
|
||||||
|
|
||||||
// use CGO-generated struct to get multiple return values
|
// use CGO-generated struct to get multiple return values
|
||||||
struct DirInit_return result = DirInit(1);
|
struct DecryptFileToSlice_return result = DecryptFileToSlice(GetRealPath(vanityPath), GetPascalStringFromCString(password));
|
||||||
|
|
||||||
// familiar error handling pattern
|
// familiar error handling pattern
|
||||||
if (result.r0 != NULL) {
|
if (result.r0 != NULL) {
|
||||||
@@ -36,17 +53,19 @@ int main() {
|
|||||||
exit(1); // result.r0 not freed since program exits
|
exit(1); // result.r0 not freed since program exits
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < result.r2; i++) {
|
||||||
// print Pascal string using "%.*s" with printf and supplying both length and data
|
// print Pascal string using "%.*s" with printf and supplying both length and data
|
||||||
printf("Old device ID: %.*s\n", result.r1.len, result.r1.data);
|
printf("%.*s\n", result.r1[i].len, result.r1[i].data);
|
||||||
|
}
|
||||||
|
|
||||||
// be sure to free the data!
|
// be sure to free the data!
|
||||||
free(result.r1.data);
|
FreeArray(result.r1, result.r2);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
# Progress
|
# Progress
|
||||||
- [ ] age
|
- [ ] age
|
||||||
- [ ] AllPasswordEntries(forceReage bool) error
|
- [ ] AllPasswordEntries(forceReage bool, rcwPassword []byte) error
|
||||||
- [ ] Entry(vanityPath string, timestamp int64) error
|
- [ ] Entry(vanityPath string, timestamp int64) error
|
||||||
- [ ] TranslateAgeTimestamp(timestamp *int64) uint8
|
- [ ] TranslateAgeTimestamp(timestamp *int64) uint8
|
||||||
- [ ] clip
|
- [ ] clip
|
||||||
@@ -65,25 +84,26 @@ int main() {
|
|||||||
- [ ] EntryIsNotEmpty(entryData []string) bool
|
- [ ] EntryIsNotEmpty(entryData []string) bool
|
||||||
- [ ] EntryRefresh(oldRCWPassword, newRCWPassword []byte, removeOldDir bool) error
|
- [ ] EntryRefresh(oldRCWPassword, newRCWPassword []byte, removeOldDir bool) error
|
||||||
- [ ] GenTOTP(secret string, time time.Time) (string, error)
|
- [ ] GenTOTP(secret string, time time.Time) (string, error)
|
||||||
- [ ] GetOldEntryData(realPath string, field int) ([]string, error)
|
- [ ] GetOldEntryData(realPath string, field int, rcwPassword []byte) ([]string, error)
|
||||||
- [ ] LibmuttonInit(inputCB func(prompt string) string, rcwPassword []byte, ...) error
|
- [ ] LibmuttonInit(inputCB func(prompt string) string, rcwPassword []byte, ...) error
|
||||||
- [ ] RCWSanityCheckGen(password []byte) error
|
- [ ] RCWSanityCheckGen(password []byte) error
|
||||||
- [ ] WriteEntry(realPath string, decSlice []string, passwordIsNew bool) error
|
- [ ] WriteEntry(realPath string, decSlice []string, passwordIsNew bool, rcwPassword []byte) error
|
||||||
- [ ] crypt
|
- [ ] crypt
|
||||||
- [ ] DecryptFileToSlice(realPath string) ([]string, error)
|
- [ ] Address TODOs
|
||||||
- [ ] EncryptBytes(decBytes []byte) []byte
|
- [X] ~~VAR: RetryPassword bool~~ (RCWD not supported)
|
||||||
- [ ] RCWDArgument()
|
- [X] DecryptFileToSlice(realPath string) ([]string, error)
|
||||||
- [ ] VAR: Daemonize bool
|
- [X] EncryptBytes(decBytes []byte) []byte
|
||||||
- [ ] VAR: RetryPassword bool
|
- [X] ~~RCWDArgument()~~ (RCWD not supported)
|
||||||
- [ ] global
|
- [ ] global
|
||||||
|
- [ ] Address TODOs
|
||||||
|
- [X] ~~VAR (CB func): GetPassword~~ (RCWD not supported)
|
||||||
- [X] DirInit(preserveOldCfgDir bool) (string, error)
|
- [X] DirInit(preserveOldCfgDir bool) (string, error)
|
||||||
- [ ] ~~GenDeviceIDList() ([]fs.DirEntry, error)~~ (not for use outside of libmutton)
|
- [X] ~~GenDeviceIDList() ([]fs.DirEntry, error)~~ (not for use outside of libmutton)
|
||||||
- [X] GetCurrentDeviceID() (string, error)
|
- [X] GetCurrentDeviceID() (string, error)
|
||||||
- [X] GetRealAgePath(vanityPath string) string
|
- [X] GetRealAgePath(vanityPath string) string
|
||||||
- [X] GetRealPath(vanityPath string) string
|
- [X] GetRealPath(vanityPath string) string
|
||||||
- [ ] ~~GetSysProcAttr() *syscall.SysProcAttr~~ (not for use outside of libmutton)
|
- [X] ~~GetSysProcAttr() *syscall.SysProcAttr~~ (not for use outside of libmutton)
|
||||||
- [X] GetVanityPath(realPath string) string
|
- [X] GetVanityPath(realPath string) string
|
||||||
- [ ] VAR (CB func): GetPassword
|
|
||||||
- [ ] syncclient
|
- [ ] syncclient
|
||||||
- [ ] AddFolderRemote(vanityPath string) error
|
- [ ] AddFolderRemote(vanityPath string) error
|
||||||
- [ ] GenDeviceID(oldDeviceID, prefix string) (string, string, bool, error)
|
- [ ] GenDeviceID(oldDeviceID, prefix string) (string, string, bool, error)
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
// #include <stdlib.h>
|
||||||
|
// #include "types.h"
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/rwinkhart/libmutton/crypt"
|
||||||
|
"github.com/rwinkhart/rcw/wrappers"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO investigate username+password only entries still having blank lines at the end when decrypted
|
||||||
|
|
||||||
|
// DecryptFileToSlice returns:
|
||||||
|
// r0: err
|
||||||
|
//
|
||||||
|
// r1: decLines (pointer to C-allocated array)
|
||||||
|
//
|
||||||
|
// r2: length decLines array
|
||||||
|
//
|
||||||
|
//export DecryptFileToSlice
|
||||||
|
func DecryptFileToSlice(realPath, rcwPassword C.PascalString) (*C.char, *C.PascalString, C.int) {
|
||||||
|
lines, err := crypt.DecryptFileToSlice(C.GoStringN(realPath.data, realPath.len), []byte(C.GoStringN(rcwPassword.data, rcwPassword.len)))
|
||||||
|
if err != nil {
|
||||||
|
return C.CString(err.Error()), nil, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(lines) == 0 {
|
||||||
|
return nil, nil, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate C array for PascalStrings
|
||||||
|
cLinesPtr := (*C.PascalString)(C.malloc(C.size_t(len(lines)) * C.size_t(C.sizeof_PascalString)))
|
||||||
|
|
||||||
|
// populate the array with the decrypted lines
|
||||||
|
cLinesSlice := (*[1 << 30]C.PascalString)(unsafe.Pointer(cLinesPtr))[:len(lines):len(lines)]
|
||||||
|
for i, line := range lines {
|
||||||
|
cLinesSlice[i] = getPascalString(line)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, cLinesPtr, C.int(len(lines))
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncryptBytes returns:
|
||||||
|
// encBytes
|
||||||
|
//
|
||||||
|
//export EncryptBytes
|
||||||
|
func EncryptBytes(decBytes, rcwPassword C.PascalString) C.PascalString {
|
||||||
|
// use wrappers.Encrypt directly since C bindings do no support the RCWD daemon
|
||||||
|
encBytes := wrappers.Encrypt([]byte(C.GoStringN(decBytes.data, decBytes.len)), []byte(C.GoStringN(rcwPassword.data, rcwPassword.len)))
|
||||||
|
return getPascalStringFromBytes(encBytes)
|
||||||
|
}
|
||||||
@@ -1,12 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
/*
|
// #include <stdlib.h>
|
||||||
#include <stdlib.h>
|
// #include "types.h"
|
||||||
typedef struct {
|
|
||||||
char* data;
|
|
||||||
int len;
|
|
||||||
} PascalString;
|
|
||||||
*/
|
|
||||||
import "C"
|
import "C"
|
||||||
import (
|
import (
|
||||||
"github.com/rwinkhart/libmutton/global"
|
"github.com/rwinkhart/libmutton/global"
|
||||||
|
|||||||
@@ -2,9 +2,17 @@ module cmutton
|
|||||||
|
|
||||||
go 1.25.6
|
go 1.25.6
|
||||||
|
|
||||||
require github.com/rwinkhart/libmutton v0.4.3-0.20260111043639-f82b35bc4398
|
require (
|
||||||
|
github.com/rwinkhart/libmutton v0.4.3-0.20260111043639-f82b35bc4398
|
||||||
|
github.com/rwinkhart/rcw v0.2.4
|
||||||
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||||
github.com/rwinkhart/go-boilerplate v0.1.1 // indirect
|
github.com/rwinkhart/go-boilerplate v0.1.1 // indirect
|
||||||
|
github.com/rwinkhart/peercred-mini v0.1.2 // indirect
|
||||||
|
golang.org/x/crypto v0.46.0 // indirect
|
||||||
golang.org/x/sys v0.40.0 // indirect
|
golang.org/x/sys v0.40.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
replace github.com/rwinkhart/libmutton => ../libmutton
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
|
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||||
|
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||||
github.com/rwinkhart/go-boilerplate v0.1.1 h1:C+yyscGWeqvNpR91iw0i91zqX0LcxnCr1VOyT7iM4JY=
|
github.com/rwinkhart/go-boilerplate v0.1.1 h1:C+yyscGWeqvNpR91iw0i91zqX0LcxnCr1VOyT7iM4JY=
|
||||||
github.com/rwinkhart/go-boilerplate v0.1.1/go.mod h1:/NVRKGslU20E5xU5YOgXzWxA6aa94BMtv5MtHRTb5Ek=
|
github.com/rwinkhart/go-boilerplate v0.1.1/go.mod h1:/NVRKGslU20E5xU5YOgXzWxA6aa94BMtv5MtHRTb5Ek=
|
||||||
github.com/rwinkhart/libmutton v0.4.3-0.20260111043639-f82b35bc4398 h1:QufX3nG3H1N986Xh7NZWsVELxmGms1yhNP7/fejBeHY=
|
github.com/rwinkhart/peercred-mini v0.1.2 h1:4cGWDbv0whvLeVvbUdx84V/9p+2fS+DEXgrA1KxlRFo=
|
||||||
github.com/rwinkhart/libmutton v0.4.3-0.20260111043639-f82b35bc4398/go.mod h1:qInUv19lzX1adFNI6Ih/IEVy+pktSTh/yA7cRTdVPH8=
|
github.com/rwinkhart/peercred-mini v0.1.2/go.mod h1:LLHG7YshHEpbpJJP+Il9nx2dnGj5O3VGE32rWmflj0c=
|
||||||
|
github.com/rwinkhart/rcw v0.2.4 h1:FrRSsl+ui1WLmDwqjLSROtFPKqSeGLEfF2SPENt4qP0=
|
||||||
|
github.com/rwinkhart/rcw v0.2.4/go.mod h1:nhW4RAHvEjW2QcOlqEdWqRQOFJLjoOGSPkSRZlMjU3s=
|
||||||
|
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
|
||||||
|
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
|
||||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
||||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
|
|||||||
Reference in New Issue
Block a user