Initial: fixing internal package metadata
This commit is contained in:
1
internal/actions/apikey/apikey.go
Executable file
1
internal/actions/apikey/apikey.go
Executable file
@@ -0,0 +1 @@
|
||||
package apikey
|
||||
600
internal/actions/decrypt/decrypt.go
Executable file
600
internal/actions/decrypt/decrypt.go
Executable file
@@ -0,0 +1,600 @@
|
||||
package decrypt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/cloudflare/circl/kem/kyber/kyber768"
|
||||
"golang.org/x/crypto/argon2"
|
||||
cc20 "golang.org/x/crypto/chacha20poly1305"
|
||||
"golang.org/x/crypto/curve25519"
|
||||
"golang.org/x/crypto/hkdf"
|
||||
"sources.truenas.cloud/code/syscrypt"
|
||||
"sources.truenas.cloud/code/syscrypt/internal/utils"
|
||||
"sources.truenas.cloud/code/syscrypt/internal/vars"
|
||||
)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
func Validate() {
|
||||
|
||||
utils.ClearTerminal()
|
||||
|
||||
decryptAllowedFlags := map[string]struct{}{
|
||||
"-C": {},
|
||||
"-k": {},
|
||||
"-i": {},
|
||||
"-c": {},
|
||||
"-o": {},
|
||||
"-A": {},
|
||||
"-P": {},
|
||||
}
|
||||
|
||||
utils.ValidateAllowedFlags(decryptAllowedFlags)
|
||||
|
||||
decryptRequiredFlags := map[string]bool{
|
||||
"-k": true,
|
||||
"-i": true,
|
||||
}
|
||||
|
||||
_ = decryptRequiredFlags
|
||||
|
||||
//utils.ValidateRequiredFlags(decryptRequiredFlags, "decrypt")
|
||||
|
||||
// -- Keys
|
||||
|
||||
isKeySet, keyHasValue := utils.IsFlagPassed("k")
|
||||
keyValue, _ := utils.GetFlagValue("k")
|
||||
keyIsValidPath := utils.IsValidPath(keyValue)
|
||||
keyExists := utils.FileExists(keyValue)
|
||||
keyIsValidJson, _ := utils.ValidateJSON(keyValue)
|
||||
|
||||
if isKeySet && !keyHasValue {
|
||||
msg := fmt.Sprintf("%s: -k KEY: requires a value.\n", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if isKeySet && !keyIsValidPath {
|
||||
msg := fmt.Sprintf("%s: -k KEY: requires a valid file path.\n", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if isKeySet && !keyExists {
|
||||
msg := fmt.Sprintf("%s: -k KEY: key file does not exist.\n", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if !keyIsValidJson {
|
||||
msg := fmt.Sprintf("%s: -k KEY: Invalid JSON format.\n", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var privateKeyPrefix string
|
||||
|
||||
privateKey, _ := utils.FetchFileKey(keyValue, "key")
|
||||
privateKeyParts := strings.Split(privateKey, "--")
|
||||
if len(privateKeyParts) != 2 {
|
||||
msg := fmt.Sprintf("%s: -k KEY: Mismatch: Invalid Prefix '%s'. Invalid Length.\n", vars.CommandFlag, privateKeyParts[0]+vars.EndAnchor)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
privateKeyStart := privateKeyParts[0]
|
||||
privateKeyPrefix = strings.ReplaceAll(vars.PrivateKeyPrefixLabel, "--", "")
|
||||
|
||||
var match bool
|
||||
if privateKeyStart == privateKeyPrefix {
|
||||
match = true
|
||||
} else {
|
||||
match = false
|
||||
}
|
||||
|
||||
if !match {
|
||||
msg := fmt.Sprintf("%s: -k KEY: Mismatch: Invalid Prefix '%s'\n", vars.CommandFlag, privateKeyStart+vars.EndAnchor)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// -- Input
|
||||
|
||||
isInputSet, inputHasValue := utils.IsFlagPassed("i")
|
||||
inputValue, _ := utils.GetFlagValue("i")
|
||||
inputIsValidPath := utils.IsValidPath(inputValue)
|
||||
inputExists := utils.FileExists(inputValue)
|
||||
|
||||
if isInputSet && !inputHasValue {
|
||||
msg := fmt.Sprintf("%s: -i INPUT: Requires a value.\n", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if isInputSet && !inputIsValidPath {
|
||||
msg := fmt.Sprintf("%s: -i INPUT: Requires a valid file path.\n", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if !inputExists {
|
||||
msg := fmt.Sprintf("%s: -i INPUT: File does not exist.\n%s", vars.CommandFlag, inputValue)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
inputFileMode := utils.GetFileMode(inputValue)
|
||||
|
||||
if inputFileMode == 0 {
|
||||
msg := fmt.Sprintf("%s: -i INPUT: File does not appear to be a valid encrypted file.\n", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var apiValue string
|
||||
var apiIsValidPath bool
|
||||
var apiExists bool
|
||||
var apiIsValidJson bool
|
||||
var password string
|
||||
|
||||
isAPISet, apiHasValue := utils.IsFlagPassed("A")
|
||||
if isAPISet {
|
||||
apiValue, _ = utils.GetFlagValue("A")
|
||||
apiIsValidPath = utils.IsValidPath(apiValue)
|
||||
apiExists = utils.FileExists(apiValue)
|
||||
apiIsValidJson, _ = utils.ValidateJSON(apiValue)
|
||||
}
|
||||
|
||||
_ = apiHasValue
|
||||
_ = apiExists
|
||||
_ = apiIsValidJson
|
||||
|
||||
var lockValidationRequired bool
|
||||
|
||||
switch inputFileMode {
|
||||
case 1: // classic - do nothing
|
||||
lockValidationRequired = false
|
||||
case 2: // classic locked - apikey and password required
|
||||
lockValidationRequired = true
|
||||
|
||||
case 3: // hybrid - do nothing
|
||||
lockValidationRequired = false
|
||||
case 4: // hybrid locked - apikey and password required
|
||||
lockValidationRequired = true
|
||||
default:
|
||||
lockValidationRequired = false
|
||||
msg := fmt.Sprintf("%s: -i INPUT: Unable to determine encryption mode. Invalid File.\n%s\n", vars.CommandFlag, inputValue)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if isAPISet && lockValidationRequired {
|
||||
//
|
||||
|
||||
if !isAPISet {
|
||||
msg := fmt.Sprintf("%s: LOCKED FILE: -A APIKEY: flag is required.\n", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if isAPISet && !apiHasValue {
|
||||
msg := fmt.Sprintf("%s: LOCKED FILE: -A APIKEY: requires a value.\n", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if isAPISet && !apiIsValidPath {
|
||||
msg := fmt.Sprintf("%s: LOCKED FILE: -A APIKEY: requires a valid file path.\n", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
password := utils.PromptPassword()
|
||||
|
||||
_ = password
|
||||
|
||||
//
|
||||
}
|
||||
|
||||
_ = apiIsValidPath
|
||||
_ = password
|
||||
|
||||
// -- Output
|
||||
|
||||
isOutputSet, outputHasValue := utils.IsFlagPassed("o")
|
||||
outputValue, _ := utils.GetFlagValue("o")
|
||||
outputIsValidPath := utils.IsValidPath(outputValue)
|
||||
outputExists := utils.FileExists(outputValue)
|
||||
|
||||
if isOutputSet && !outputHasValue {
|
||||
msg := fmt.Sprintf("%s: -o OUTPUT: requires a value.\n", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if isOutputSet && !outputIsValidPath {
|
||||
msg := fmt.Sprintf("%s: -o OUTPUT: requires a valid file path.\n", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// confirm overwrite.....
|
||||
|
||||
if isOutputSet && outputExists {
|
||||
utils.ConfirmOverwrite(outputValue)
|
||||
}
|
||||
|
||||
// Get Private Key
|
||||
|
||||
privateKey, err := utils.FetchFileKey(keyValue, "key")
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("%s: -k KEY: Error: %s", vars.CommandFlag, err)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
keyBytes, err := os.ReadFile(keyValue)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("%s: -k KEY: Could not read key file.\n%s\n", vars.CommandFlag, err)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var pKey syscrypt.PrivateKeyWrapper
|
||||
err = json.Unmarshal(keyBytes, &pKey)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("%s: -k KEY: File is not a valid syscrypt key file. %v\n", vars.CommandFlag, err)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
DecryptFile(outputValue, inputValue, pKey)
|
||||
|
||||
_ = err
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
func validateFile(inputValue string) (encryptionType bool, isLocked bool, isArmored bool) {
|
||||
|
||||
//switch mode {
|
||||
//case 0x01:
|
||||
// fmt.Printf("classic")
|
||||
//case 0x02:
|
||||
// fmt.Printf("classic with lock")
|
||||
//case 0x03:
|
||||
// fmt.Printf("post quantum")
|
||||
//case 0x04:
|
||||
// fmt.Printf("post quantum with lock")
|
||||
//default:
|
||||
// fmt.Printf("invalid")
|
||||
//}
|
||||
|
||||
return false, false, false
|
||||
|
||||
//file, err := os.Open(inputValue)
|
||||
//if err != nil {
|
||||
// fmt.Printf("Error: cannot open %s\n", inputValue)
|
||||
// os.Exit(1)
|
||||
//}
|
||||
//defer file.Close()
|
||||
|
||||
//header := make([]byte, 1)
|
||||
//_, err = file.Read(header)
|
||||
//if err != nil {
|
||||
// fmt.Println("Error: file is empty or unreadable")
|
||||
// os.Exit(1)
|
||||
//}
|
||||
|
||||
//file, err := os.Open(filePath)
|
||||
//if err != nil {
|
||||
// return false, false, err
|
||||
//}
|
||||
//defer file.Close()
|
||||
|
||||
//buffer := make([]byte, 512)
|
||||
//n, err := file.Read(buffer)
|
||||
//if err != nil && n == 0 {
|
||||
// return false, false, err
|
||||
//}
|
||||
|
||||
//preview := string(buffer[:n])
|
||||
//nPreview := strings.ReplaceAll(preview, vars.PrivateKeyHeader+"\n", "")
|
||||
//nPreview = strings.ReplaceAll(nPreview, vars.PrivateKeyFooter+"\n", "")
|
||||
//isBase64 := IsValidBase64WithLines(preview)
|
||||
|
||||
//if strings.HasPrefix(preview, vars.PrivateKeyHeader) {
|
||||
// isArmored = true
|
||||
//} else {
|
||||
// isArmored = false
|
||||
//}
|
||||
|
||||
//mode := header[0]
|
||||
|
||||
//switch mode {
|
||||
//case 0x01:
|
||||
// return 1 // Classical Encryption
|
||||
//case 0x02:
|
||||
// return 2 // Classical Encryption [with lock]
|
||||
//case 0x03:
|
||||
// return 3 // Post Quantum Encryption
|
||||
//case 0x04:
|
||||
// return 4 // Post Quantum Encryption [with lock]
|
||||
//default:
|
||||
// return 5 // Invalid or Armored
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
func DecryptFile(out string, input string, priv syscrypt.PrivateKeyWrapper) {
|
||||
|
||||
outputValue, _ := utils.GetFlagValue("o")
|
||||
inputValue, _ := utils.GetFlagValue("i")
|
||||
|
||||
isOutputSet, outputHasValue := utils.IsFlagPassed("o")
|
||||
isOutputValidPath := utils.IsValidPath(outputValue)
|
||||
outputExists := utils.FileExists(outputValue)
|
||||
passValue, _ := utils.GetFlagValue("P")
|
||||
apiValue, _ := utils.GetFlagValue("A")
|
||||
|
||||
raw, _ := os.ReadFile(input)
|
||||
var blob []byte
|
||||
|
||||
if strings.Contains(string(raw), vars.PrivateKeyHeader) {
|
||||
c := strings.ReplaceAll(string(raw), vars.PrivateKeyHeader, "")
|
||||
c = strings.ReplaceAll(c, vars.PrivateKeyFooter, "")
|
||||
c = strings.ReplaceAll(c, "\n", "")
|
||||
c = strings.ReplaceAll(c, "\r", "")
|
||||
blob, _ = base64.StdEncoding.DecodeString(strings.TrimSpace(c))
|
||||
} else {
|
||||
|
||||
blob = raw
|
||||
|
||||
}
|
||||
|
||||
// unblind header
|
||||
|
||||
ephPubX := blob[2:34]
|
||||
mode := blob[0] ^ ephPubX[0]
|
||||
serialSize := int(blob[1] ^ ephPubX[1])
|
||||
|
||||
serialOffset := 34
|
||||
dataPtr := serialOffset + serialSize
|
||||
|
||||
recoveredSerial := make([]byte, serialSize)
|
||||
for i := 0; i < serialSize; i++ {
|
||||
recoveredSerial[i] = blob[serialOffset+i] ^ ephPubX[(i+2)%32]
|
||||
}
|
||||
|
||||
if priv.PrivateKey.Serial != string(recoveredSerial) {
|
||||
fmt.Printf("Access Denied: Serial Mismatch or invalid key type.\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
isHybrid := (mode == 0x03 || mode == 0x04)
|
||||
isLocked := (mode == 0x02 || mode == 0x04)
|
||||
|
||||
// Password Verification for Locked files
|
||||
var passKey []byte
|
||||
|
||||
if isLocked {
|
||||
//
|
||||
apiKey, err := utils.FetchFileKey(apiValue, "key")
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
passKey = argon2.IDKey([]byte(passValue), []byte(apiKey), 1, 64*1024, 4, 32)
|
||||
|
||||
vH := hkdf.New(sha256.New, passKey, nil, []byte("syscrypt-pass-verify"))
|
||||
vK := make([]byte, 32)
|
||||
io.ReadFull(vH, vK)
|
||||
vAead, _ := cc20.New(vK)
|
||||
res, err := vAead.Open(nil, make([]byte, 12), blob[dataPtr:dataPtr+vars.PassTagSize], nil)
|
||||
if err != nil || !bytes.Equal(res, []byte("SYSC-PASS-OK")) {
|
||||
fmt.Printf("Invalid Master Password.")
|
||||
os.Exit(1)
|
||||
}
|
||||
dataPtr += vars.PassTagSize
|
||||
//
|
||||
}
|
||||
|
||||
// Slice Hybrid & Data
|
||||
|
||||
var kyberCT []byte
|
||||
if isHybrid {
|
||||
kyberCT = blob[dataPtr : dataPtr+vars.KyberCTSize]
|
||||
dataPtr += vars.KyberCTSize
|
||||
}
|
||||
|
||||
nonce := blob[dataPtr : dataPtr+12]
|
||||
ciphertext := blob[dataPtr+12:]
|
||||
|
||||
// Final Key Reconstruction
|
||||
|
||||
cleanPrivX := strings.TrimPrefix(priv.PrivateKey.Key, vars.PrivateKeyPrefixLabel)
|
||||
myPrivX, _ := hex.DecodeString(cleanPrivX)
|
||||
sharedX, _ := curve25519.X25519(myPrivX, ephPubX)
|
||||
|
||||
var sharedML []byte
|
||||
if isHybrid {
|
||||
scheme := kyber768.Scheme()
|
||||
cleanML := strings.TrimPrefix(priv.PrivateKey.MLKEMKey, vars.PQPrivateKeyPrefixLabel)
|
||||
skBytes, _ := hex.DecodeString(cleanML)
|
||||
skK, _ := scheme.UnmarshalBinaryPrivateKey(skBytes)
|
||||
sharedML, _ = scheme.Decapsulate(skK, kyberCT)
|
||||
}
|
||||
|
||||
combined := append(sharedX, sharedML...)
|
||||
if isLocked {
|
||||
combined = append(combined, passKey...)
|
||||
}
|
||||
|
||||
h := hkdf.New(sha256.New, combined, nil, []byte("syscrypt-v1-hybrid"))
|
||||
symmK := make([]byte, 32)
|
||||
io.ReadFull(h, symmK)
|
||||
aead, _ := cc20.New(symmK)
|
||||
plaintext, err := aead.Open(nil, nonce, ciphertext, nil)
|
||||
if err != nil {
|
||||
fmt.Printf("Decryption failed")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if isOutputSet {
|
||||
os.WriteFile(outputValue, plaintext, 0644)
|
||||
fmt.Printf("Successfully decrypted file to: %s\n", outputValue)
|
||||
}
|
||||
|
||||
if !isOutputSet {
|
||||
fmt.Printf("%s\n", plaintext)
|
||||
}
|
||||
|
||||
_ = inputValue
|
||||
_ = isOutputSet
|
||||
_ = outputHasValue
|
||||
_ = isOutputValidPath
|
||||
_ = outputExists
|
||||
_ = dataPtr
|
||||
_ = kyberCT
|
||||
_ = nonce
|
||||
_ = ciphertext
|
||||
_ = sharedX
|
||||
|
||||
//outputValue, _ := utils.GetFlagValue("o")
|
||||
//inputValue, _ := utils.GetFlagValue("i")
|
||||
|
||||
//isOutputSet, outputHasValue := utils.IsFlagPassed("o")
|
||||
//outputValue, _ := utils.GetFlagValue("k")
|
||||
//outputIsValidPath := utils.IsValidPath(outValue)
|
||||
//outputExists := utils.FileExists(outputValue)
|
||||
|
||||
/*
|
||||
|
||||
rawInput, err := os.ReadFile(inputValue)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: Unable to read %s\n", inputValue)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var blob []byte
|
||||
inputStr := string(rawInput)
|
||||
|
||||
if strings.Contains(inputStr, vars.PrivateKeyHeader) {
|
||||
content := strings.ReplaceAll(inputStr, vars.PrivateKeyHeader, "")
|
||||
content = strings.ReplaceAll(content, vars.PrivateKeyFooter, "")
|
||||
content = strings.ReplaceAll(content, "\n", "")
|
||||
content = strings.ReplaceAll(content, "\r", "")
|
||||
content = strings.TrimSpace(content)
|
||||
blob, err = base64.StdEncoding.DecodeString(content)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: Malformed Armored Base64 data.\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
blob = rawInput
|
||||
|
||||
}
|
||||
|
||||
if len(blob) < 35 {
|
||||
fmt.Printf("Error: -i INPUT: File is too small to be a valid syscrypt encrypted message.\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
mode := blob[0]
|
||||
serialSize := int(blob[1])
|
||||
|
||||
ephOffset := 2 + serialSize
|
||||
headerOffset := ephOffset + 32
|
||||
|
||||
if len(blob) < headerOffset {
|
||||
fmt.Printf("Error: Header truncated or invalid serial length.\n")
|
||||
}
|
||||
|
||||
maskedSerial := blob[2:ephOffset]
|
||||
ephPubX := blob[ephOffset:headerOffset]
|
||||
|
||||
recoveredBytes := make([]byte, serialSize)
|
||||
for i := 0; i < serialSize; i++ {
|
||||
recoveredBytes[i] = maskedSerial[i] ^ ephPubX[i%32]
|
||||
}
|
||||
fileSerial := string(recoveredBytes)
|
||||
|
||||
if fileSerial != priv.PrivateKey.Serial {
|
||||
fmt.Printf("Error: File requires key [%s], but you provided [%s]\n", fileSerial, priv.PrivateKey.Serial)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var kyberCT, nonce, ciphertext []byte
|
||||
isHybrid := mode == 0x03 || mode == 0x04
|
||||
isLocked := mode == 0x02 || mode == 0x04
|
||||
|
||||
if isHybrid {
|
||||
kyberCT = blob[headerOffset : headerOffset+1088]
|
||||
nonce = blob[headerOffset+1088 : headerOffset+1100]
|
||||
ciphertext = blob[headerOffset+1100:]
|
||||
} else {
|
||||
nonce = blob[headerOffset : headerOffset+12]
|
||||
ciphertext = blob[headerOffset+12:]
|
||||
}
|
||||
|
||||
cleanPriv := strings.TrimPrefix(priv.PrivateKey.Key, vars.PrivateKeyPrefixLabel)
|
||||
myPrivX, _ := hex.DecodeString(cleanPriv)
|
||||
sharedX, _ := curve25519.X25519(myPrivX, ephPubX)
|
||||
|
||||
var sharedML []byte
|
||||
if isHybrid {
|
||||
scheme := kyber768.Scheme()
|
||||
skBytes, _ := hex.DecodeString(priv.PrivateKey.MLKEMKey)
|
||||
skK, _ := scheme.UnmarshalBinaryPrivateKey(skBytes)
|
||||
sharedML, _ = scheme.Decapsulate(skK, kyberCT)
|
||||
}
|
||||
|
||||
combined := append(sharedX, sharedML...)
|
||||
if isLocked {
|
||||
apiValue, _ := utils.GetFlagValue("A")
|
||||
passValue, _ := utils.GetFlagValue("P")
|
||||
|
||||
passKey := argon2.IDKey([]byte(passValue), []byte(apiKey), 1, 64*1024, 4, 32)
|
||||
combined = append(combined, passKey...)
|
||||
defer utils.Zeroize(passKey)
|
||||
}
|
||||
|
||||
h := hkdf.New(sha256.New, combined, nil, []byte("syscrypt-v1-hybrid"))
|
||||
symmKey := make([]byte, 32)
|
||||
io.ReadFull(h, symmKey)
|
||||
defer utils.Zeroize(symmKey)
|
||||
|
||||
aead, _ := cc20.New(symmKey)
|
||||
plaintext, err := aead.Open(nil, nonce, ciphertext, nil)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: Decryption failed. Potentional data corruption or wrong password.")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if isOutputSet && outputIsValidPath {
|
||||
|
||||
err = os.WriteFile(outputValue, plaintext, 0644)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: Unable to write decrypted file %s\n", outputValue)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
} else {
|
||||
/// do stuff that isnt output
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
829
internal/actions/encrypt/encrypt.go
Executable file
829
internal/actions/encrypt/encrypt.go
Executable file
@@ -0,0 +1,829 @@
|
||||
package encrypt
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/cloudflare/circl/kem/kyber/kyber768"
|
||||
"golang.org/x/crypto/argon2"
|
||||
cc20 "golang.org/x/crypto/chacha20poly1305"
|
||||
"golang.org/x/crypto/curve25519"
|
||||
"golang.org/x/crypto/hkdf"
|
||||
"sources.truenas.cloud/code/syscrypt"
|
||||
"sources.truenas.cloud/code/syscrypt/internal/utils"
|
||||
"sources.truenas.cloud/code/syscrypt/internal/vars"
|
||||
)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
func Validate() {
|
||||
|
||||
encryptAllowedFlags := map[string]struct{}{
|
||||
"-C": {},
|
||||
"-L": {},
|
||||
"-a": {},
|
||||
"-k": {},
|
||||
"-i": {},
|
||||
"-c": {},
|
||||
"-o": {},
|
||||
"-A": {},
|
||||
"-P": {},
|
||||
"-PQ": {},
|
||||
}
|
||||
|
||||
for _, arg := range os.Args {
|
||||
if arg == "-L" {
|
||||
encryptAllowedFlags["-A"] = struct{}{}
|
||||
encryptAllowedFlags["-P"] = struct{}{}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
utils.ValidateAllowedFlags(encryptAllowedFlags)
|
||||
|
||||
encryptRequiredFlags := map[string]bool{
|
||||
"-k": true,
|
||||
"-i": true,
|
||||
"-o": true,
|
||||
}
|
||||
|
||||
for _, arg := range os.Args {
|
||||
if arg == "-L" {
|
||||
encryptRequiredFlags["-A"] = true
|
||||
encryptRequiredFlags["-P"] = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
//utils.ValidateRequiredFlags(encryptRequiredFlags, "encrypt")
|
||||
|
||||
isKeySet, keyHasValue := utils.IsFlagPassed("k")
|
||||
keyValue, _ := utils.GetFlagValue("k")
|
||||
keyIsValidPath := utils.IsValidPath(keyValue)
|
||||
|
||||
isInputSet, inputHasValue := utils.IsFlagPassed("i")
|
||||
inputValue, _ := utils.GetFlagValue("i")
|
||||
inputIsValidPath := utils.IsValidPath(inputValue)
|
||||
|
||||
isOutputSet, outputHasValue := utils.IsFlagPassed("o")
|
||||
outputValue, _ := utils.GetFlagValue("o")
|
||||
outputIsValidPath := utils.IsValidPath(outputValue)
|
||||
outputFileExists := utils.FileExists(outputValue)
|
||||
|
||||
isArmoredSet, armoredHasValue := utils.IsFlagPassed("a")
|
||||
|
||||
isLockSet, lockHasValue := utils.IsFlagPassed("L")
|
||||
lockValue, _ := utils.GetFlagValue("L")
|
||||
|
||||
_ = lockValue
|
||||
|
||||
isAPISet, _ := utils.IsFlagPassed("A")
|
||||
apiValue, _ := utils.GetFlagValue("A")
|
||||
apiIsValidPath := utils.IsValidPath(apiValue)
|
||||
apiFileExists := utils.FileExists(apiValue)
|
||||
|
||||
//isPassSet, _ := utils.IsFlagPassed("P")
|
||||
//passValue, _ := utils.GetFlagValue("P")
|
||||
//passIsValidPath := utils.IsValidPath(passValue)
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
// -- Key
|
||||
|
||||
if isKeySet && !keyHasValue {
|
||||
msg := fmt.Sprintf("%s: -k KEY: Requires a value.\n", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if isKeySet && !keyIsValidPath {
|
||||
msg := fmt.Sprintf("%s: -k KEY: Requires a valid file path.\n", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
keyExists := utils.FileExists(keyValue)
|
||||
if !keyExists {
|
||||
msg := fmt.Sprintf("%s: -k KEY: Key file does not exist.\n%s\n", vars.CommandFlag, keyValue)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// -- Input
|
||||
|
||||
if isInputSet && !inputHasValue {
|
||||
msg := fmt.Sprintf("%s: -i INPUT: Requires a value.\n", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if isInputSet && !inputIsValidPath {
|
||||
msg := fmt.Sprintf("%s: -i INPUT: Requires a valid file path.\n", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
inputExists := utils.FileExists(inputValue)
|
||||
if !inputExists {
|
||||
msg := fmt.Sprintf("%s: -i INPUT: Input file does not exist \n%s\n", vars.CommandFlag, inputValue)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// -- Output
|
||||
|
||||
if isOutputSet && !outputHasValue {
|
||||
msg := fmt.Sprintf("%s: -o OUTPUT: Requires a value.\n", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if isOutputSet && !outputIsValidPath {
|
||||
msg := fmt.Sprintf("%s: -o OUTPUT: Requires a valid file path.\n", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// -- Armored
|
||||
|
||||
if isArmoredSet && armoredHasValue {
|
||||
msg := fmt.Sprintf("%s: -a ARMORED: Armored does not support a value.\n", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// -- Lock
|
||||
|
||||
if isLockSet && lockHasValue {
|
||||
msg := fmt.Sprintf("%s: -L LOCK: Lock does not support a value.\n", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if isLockSet && !isAPISet {
|
||||
msg := fmt.Sprintf("%s: -L LOCK: Lock requires the -A APIKEY flag and value to be set.", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
//if isLockSet && !isPassSet {
|
||||
// msg := fmt.Sprintf("%s: -L LOCK: Lock requires the -P MASTER PASSWORD flag and value to be set.", vars.CommandFlag)
|
||||
// utils.HandleFailure(msg)
|
||||
// os.Exit(1)
|
||||
//}
|
||||
|
||||
// -- API
|
||||
|
||||
if isLockSet && apiValue == "" {
|
||||
msg := fmt.Sprintf("%s: -A APIKEY: Requires a value.\n", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if isLockSet && !apiIsValidPath {
|
||||
msg := fmt.Sprintf("%s: -A APIKEY: Requires a valid file path.\n", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if isLockSet && !apiFileExists {
|
||||
msg := fmt.Sprintf("%s: -A APIKEY: Key file does not exist.\n%s\n", vars.CommandFlag, apiValue)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// -- Password
|
||||
|
||||
//if isLockSet && passValue == "" {
|
||||
// msg := fmt.Sprintf("%s: -P MASTER PASSWORD: Requires a value.\n", vars.CommandFlag)
|
||||
// utils.HandleFailure(msg)
|
||||
// os.Exit(1)
|
||||
//}
|
||||
|
||||
if isLockSet {
|
||||
//masterPass := config.MasterPass
|
||||
//masterPassIsValidPath := utils.IsValidPath(masterPass)
|
||||
|
||||
//if masterPass == "" {
|
||||
// msg := fmt.Sprintf("%s: Unable to determine location of the Master Password file.\nUnable to continue.\n"+
|
||||
// "Please run syscrypt -c keygen again to generate the default keys.", vars.CommandFlag)
|
||||
// utils.HandleFailure(msg)
|
||||
// os.Exit(1)
|
||||
//}
|
||||
|
||||
//if !masterPassIsValidPath {
|
||||
// msg := fmt.Sprintf("%s: Invalid Master Password location.\n%s"+
|
||||
// "Please run syscrypt -c keygen again to generate the default keys.", vars.CommandFlag, masterPass)
|
||||
// utils.HandleFailure(msg)
|
||||
// os.Exit(1)
|
||||
//}
|
||||
}
|
||||
|
||||
//if isLockSet && !passIsValidPath {
|
||||
// msg := fmt.Sprintf("%s: -P MASTER PASSWORD: Requires a valid file path.\n", vars.CommandFlag)
|
||||
// utils.HandleFailure(msg)
|
||||
// os.Exit(1)
|
||||
//}
|
||||
|
||||
if outputFileExists {
|
||||
utils.ConfirmOverwrite(outputValue)
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
fmt.Printf("\n\n")
|
||||
fmt.Printf("keyset: %v\n", isKeySet)
|
||||
fmt.Printf("keyvalue: %v\n", keyValue)
|
||||
fmt.Printf("keyvalidpath: %v\n", keyIsValidPath)
|
||||
fmt.Printf("\n")
|
||||
|
||||
fmt.Printf("inputset: %v\n", isInputSet)
|
||||
fmt.Printf("inputvalue: %v\n", inputValue)
|
||||
fmt.Printf("inputvalidpath: %v\n", inputIsValidPath)
|
||||
fmt.Printf("\n")
|
||||
|
||||
fmt.Printf("outputset: %v\n", isOutputSet)
|
||||
fmt.Printf("outputvalue: %v\n", outputValue)
|
||||
fmt.Printf("outputvalidpath: %v\n", outputIsValidPath)
|
||||
fmt.Printf("\n")
|
||||
|
||||
// Open Files
|
||||
|
||||
keyBytes, err := os.ReadFile(keyValue)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: Could not read key file at %s\n", keyValue)
|
||||
}
|
||||
|
||||
var pub syscrypt.PublicKeyWrapper
|
||||
err = json.Unmarshal(keyBytes, &pub)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: key file is not a valid syscrypt JSON: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
EncryptFile(outputValue, inputValue, pub)
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
func zeroize(data []byte) {
|
||||
for i := range data {
|
||||
data[i] = 0
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const PassTagSize = 28
|
||||
|
||||
// func EncryptFile(dst io.Writer, src io.Reader, pub syscrypt.PublicKeyWrapper) {
|
||||
func EncryptFile(outputValue string, inputValue string, pub syscrypt.PublicKeyWrapper) {
|
||||
|
||||
// Get Values
|
||||
|
||||
isLockSet, _ := utils.IsFlagPassed("L")
|
||||
isArmoredSet, _ := utils.IsFlagPassed("a")
|
||||
keyValue, _ := utils.GetFlagValue("k")
|
||||
passValue, _ := utils.GetFlagValue("P")
|
||||
apiIsSet, _ := utils.IsFlagPassed("A")
|
||||
apiValue, _ := utils.GetFlagValue("A")
|
||||
serialKey, _ := utils.FetchFileKey(keyValue, "serial")
|
||||
|
||||
src, _ := os.Open(inputValue)
|
||||
plaintext, _ := io.ReadAll(src)
|
||||
src.Close()
|
||||
|
||||
// Keys
|
||||
|
||||
cleanPubX := strings.TrimPrefix(pub.PublicKey.Key, vars.DefaultPrefixLabel)
|
||||
recipientPubX, _ := hex.DecodeString(cleanPubX)
|
||||
ephPrivX := make([]byte, 32)
|
||||
io.ReadFull(rand.Reader, ephPrivX)
|
||||
ephPubX, _ := curve25519.X25519(ephPrivX, curve25519.Basepoint)
|
||||
sharedX, _ := curve25519.X25519(ephPrivX, recipientPubX)
|
||||
|
||||
var kyberCT []byte
|
||||
var sharedML []byte
|
||||
|
||||
isHybrid := pub.PublicKey.MLKEMKey != ""
|
||||
|
||||
if isHybrid {
|
||||
scheme := kyber768.Scheme()
|
||||
cleanML := strings.TrimPrefix(pub.PublicKey.MLKEMKey, vars.PQPublicKeyPrefixLabel)
|
||||
pkBytes, err := hex.DecodeString(cleanML)
|
||||
if err != nil {
|
||||
fmt.Printf("Hex Decode Error: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
pkK, err := scheme.UnmarshalBinaryPublicKey(pkBytes)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: kyber key unmarshal fail: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
kyberCT, sharedML, err = scheme.Encapsulate(pkK)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: Kyber encapsulation failed: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Password Tag Generation
|
||||
|
||||
var passKey, passVerifyTag []byte
|
||||
if isLockSet {
|
||||
apiKey, _ := utils.FetchFileKey(apiValue, "key")
|
||||
passKey = argon2.IDKey([]byte(passValue), []byte(apiKey), 1, 64*1024, 4, 32)
|
||||
|
||||
vH := hkdf.New(sha256.New, passKey, nil, []byte("syscrypt-pass-verify"))
|
||||
vKey := make([]byte, 32)
|
||||
io.ReadFull(vH, vKey)
|
||||
vAead, _ := cc20.New(vKey)
|
||||
vNonce := make([]byte, 12)
|
||||
passVerifyTag = vAead.Seal(nil, vNonce, []byte("SYSC-PASS-OK"), nil)
|
||||
}
|
||||
|
||||
// Final Symmetric Key
|
||||
|
||||
combined := append(sharedX, sharedML...)
|
||||
if isLockSet {
|
||||
combined = append(combined, passKey...)
|
||||
}
|
||||
|
||||
h := hkdf.New(sha256.New, combined, nil, []byte("syscrypt-v1-hybrid"))
|
||||
symmKey := make([]byte, 32)
|
||||
io.ReadFull(h, symmKey)
|
||||
aead, _ := cc20.New(symmKey)
|
||||
for i := range symmKey {
|
||||
symmKey[i] = 0
|
||||
}
|
||||
|
||||
nonce := make([]byte, 12)
|
||||
io.ReadFull(rand.Reader, nonce)
|
||||
ciphertext := aead.Seal(nil, nonce, plaintext, nil)
|
||||
|
||||
// Blinded Header Assembly
|
||||
|
||||
serialBytes := []byte(serialKey)
|
||||
serialSize := len(serialBytes)
|
||||
|
||||
var mode byte
|
||||
if isHybrid && isLockSet {
|
||||
mode = 0x04
|
||||
} else if isHybrid {
|
||||
mode = 0x03
|
||||
} else if isLockSet {
|
||||
mode = 0x02
|
||||
} else {
|
||||
mode = 0x01
|
||||
}
|
||||
|
||||
var finalBlob []byte
|
||||
finalBlob = append(finalBlob, mode^ephPubX[0])
|
||||
finalBlob = append(finalBlob, byte(serialSize)^ephPubX[1])
|
||||
finalBlob = append(finalBlob, ephPubX...)
|
||||
|
||||
for i := 0; i < serialSize; i++ {
|
||||
finalBlob = append(finalBlob, serialBytes[i]^ephPubX[(i+2)%32])
|
||||
}
|
||||
|
||||
if isLockSet {
|
||||
finalBlob = append(finalBlob, passVerifyTag...)
|
||||
}
|
||||
|
||||
if isHybrid {
|
||||
finalBlob = append(finalBlob, kyberCT...)
|
||||
}
|
||||
|
||||
finalBlob = append(finalBlob, nonce...)
|
||||
finalBlob = append(finalBlob, ciphertext...)
|
||||
|
||||
dst, err := os.Create(outputValue)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: Unable to create output file %s", outputValue)
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
if isArmoredSet {
|
||||
dst.WriteString(vars.PrivateKeyHeader + "\n")
|
||||
enc := base64.StdEncoding.EncodeToString(finalBlob)
|
||||
|
||||
for i := 0; i < len(enc); i += 64 {
|
||||
end := i + 64
|
||||
if end > len(enc) {
|
||||
end = len(enc)
|
||||
}
|
||||
dst.WriteString(enc[i:end] + "\n")
|
||||
}
|
||||
dst.WriteString(vars.PrivateKeyFooter + "\n")
|
||||
|
||||
} else {
|
||||
|
||||
dst.Write(finalBlob)
|
||||
|
||||
}
|
||||
|
||||
_ = apiIsSet
|
||||
|
||||
fmt.Printf("Success: file saved at: %s\n", outputValue)
|
||||
|
||||
/*
|
||||
|
||||
// 1. Setup Flags
|
||||
|
||||
isLockSet, _ := utils.IsFlagPassed("L")
|
||||
isAPISet, _ := utils.IsFlagPassed("A")
|
||||
isArmoredSet, _ := utils.IsFlagPassed("a")
|
||||
keyValue, _ := utils.GetFlagValue("k")
|
||||
apiValue, _ := utils.GetFlagValue("A")
|
||||
passValue, _ := utils.GetFlagValue("P")
|
||||
|
||||
// 2. Read Plaintext
|
||||
|
||||
src, _ := os.Open(inputValue)
|
||||
plaintext, _ := io.ReadAll(src)
|
||||
src.Close()
|
||||
|
||||
// 3. Classical Key Exchange (X25519)
|
||||
|
||||
cleanPubX := strings.TrimPrefix(pub.PublicKey.Key, "syscrypt-")
|
||||
recipientPubX, _ := hex.DecodeString(cleanPubX)
|
||||
|
||||
ephPrivX := make([]byte, 32)
|
||||
io.ReadFull(rand.Reader, ephPrivX)
|
||||
ephPubX, _ := curve25519.X25519(ephPrivX, curve25519.Basepoint)
|
||||
sharedX, _ := curve25519.X25519(ephPrivX, recipientPubX)
|
||||
|
||||
// 4. Post-Quantum Key Exchange (Kyber768)
|
||||
|
||||
//var kyberCT, sharedML []byte
|
||||
//isHybrid := pub.PublicKey.MLKEMKey != ""
|
||||
|
||||
var kyberCT []byte
|
||||
var sharedML []byte
|
||||
isHybrid := pub.PublicKey.MLKEMKey != ""
|
||||
|
||||
if isHybrid {
|
||||
scheme := kyber768.Scheme()
|
||||
cleanML := strings.TrimPrefix(pub.PublicKey.MLKEMKey, "syscrypt-pq-")
|
||||
pkBytes, err := hex.DecodeString(cleanML)
|
||||
if err != nil {
|
||||
fmt.Printf("Hex Decode Error: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
pkK, err := scheme.UnmarshalBinaryPublicKey(pkBytes)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: kyber key unmarshal failed: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
var encapErr error
|
||||
kyberCT, sharedML, encapErr = scheme.Encapsulate(pkK)
|
||||
if encapErr != nil {
|
||||
fmt.Printf("Error: Kyber encapsulation failed: %v\n", encapErr)
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 5. Entropy Binding
|
||||
|
||||
combined := append(sharedX, sharedML...)
|
||||
if isLockSet {
|
||||
var apiKey string
|
||||
if isAPISet {
|
||||
apiKey, _ = utils.FetchFileKey(apiValue, "key")
|
||||
}
|
||||
passKey := argon2.IDKey([]byte(passValue), []byte(apiKey), 1, 64*1024, 4, 32)
|
||||
combined = append(combined, passKey...)
|
||||
}
|
||||
|
||||
// 6. Key Derivation & Encryption
|
||||
|
||||
h := hkdf.New(sha256.New, combined, nil, []byte("syscrypt-v1-hybrid"))
|
||||
symmetricKey := make([]byte, 32)
|
||||
io.ReadFull(h, symmetricKey)
|
||||
|
||||
aead, _ := cc20.New(symmetricKey)
|
||||
for i := range symmetricKey {
|
||||
symmetricKey[i] = 0
|
||||
}
|
||||
|
||||
nonce := make([]byte, aead.NonceSize())
|
||||
io.ReadFull(rand.Reader, nonce)
|
||||
ciphertext := aead.Seal(nil, nonce, plaintext, nil)
|
||||
|
||||
// 7. Metadata/Serial Masking
|
||||
|
||||
serialKey, _ := utils.FetchFileKey(keyValue, "serial")
|
||||
serialBytes := []byte(serialKey)
|
||||
serialSize := len(serialBytes)
|
||||
maskedSerial := make([]byte, serialSize)
|
||||
for i := 0; i < serialSize; i++ {
|
||||
maskedSerial[i] = serialBytes[i] ^ ephPubX[i%32]
|
||||
}
|
||||
|
||||
// 8. Determine Mode
|
||||
|
||||
var mode byte
|
||||
if isHybrid && isLockSet {
|
||||
mode = 0x04
|
||||
} else if isHybrid {
|
||||
mode = 0x03
|
||||
} else if isLockSet {
|
||||
mode = 0x02
|
||||
} else {
|
||||
mode = 0x01
|
||||
}
|
||||
|
||||
// 9. Final Assembly
|
||||
|
||||
var finalBlob []byte
|
||||
finalBlob = append(finalBlob, mode)
|
||||
finalBlob = append(finalBlob, byte(serialSize))
|
||||
finalBlob = append(finalBlob, maskedSerial...)
|
||||
finalBlob = append(finalBlob, ephPubX...)
|
||||
|
||||
if isHybrid {
|
||||
if len(kyberCT) != 1088 {
|
||||
fmt.Printf("CRITICAL: kyberCT is %d bytes, expected 1088\n", len(kyberCT))
|
||||
return
|
||||
}
|
||||
finalBlob = append(finalBlob, kyberCT...)
|
||||
}
|
||||
|
||||
finalBlob = append(finalBlob, nonce...)
|
||||
finalBlob = append(finalBlob, ciphertext...)
|
||||
|
||||
// 10. Write output
|
||||
|
||||
dst, _ := os.Create(outputValue)
|
||||
defer dst.Close()
|
||||
|
||||
if isArmoredSet {
|
||||
dst.WriteString(vars.PrivateKeyHeader + "\n")
|
||||
encoded := base64.StdEncoding.EncodeToString(finalBlob)
|
||||
|
||||
for i := 0; i < len(encoded); i += 64 {
|
||||
end := i + 64
|
||||
if end > len(encoded) {
|
||||
end = len(encoded)
|
||||
}
|
||||
dst.WriteString(encoded[i:end] + "\n")
|
||||
}
|
||||
dst.WriteString(vars.PrivateKeyFooter + "\n")
|
||||
|
||||
} else {
|
||||
dst.Write(finalBlob)
|
||||
}
|
||||
|
||||
fmt.Printf("File created: %s (mode %d, %d bytes)\n", outputValue, mode, len(finalBlob))
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
isLockSet, _ := utils.IsFlagPassed("L")
|
||||
isAPISet, _ := utils.IsFlagPassed("A")
|
||||
isPassSet, _ := utils.IsFlagPassed("P")
|
||||
isArmoredSet, _ := utils.IsFlagPassed("a")
|
||||
/////////
|
||||
isKeyPassed, _ := utils.IsFlagPassed("k")
|
||||
keyValue, _ := utils.GetFlagValue("k")
|
||||
_ = isKeyPassed
|
||||
//////////
|
||||
|
||||
// set values
|
||||
|
||||
apiValue, _ := utils.GetFlagValue("A")
|
||||
passValue, _ := utils.GetFlagValue("P")
|
||||
|
||||
_ = passValue
|
||||
|
||||
var apiKey string
|
||||
var pass string
|
||||
|
||||
if isAPISet {
|
||||
apiKey, _ = utils.FetchFileKey(apiValue, "key")
|
||||
}
|
||||
|
||||
if isPassSet {
|
||||
pass = ""
|
||||
}
|
||||
|
||||
//isInputSet, inputHasValue := utils.IsFlagPassed("i")
|
||||
//inputValue, _ := utils.GetFlagValue("i")
|
||||
|
||||
src, _ := os.Open(inputValue)
|
||||
|
||||
plaintext, _ := io.ReadAll(src)
|
||||
|
||||
cleanPub := strings.TrimPrefix(pub.PublicKey.Key, "syscrypt")
|
||||
recipientPubX, _ := hex.DecodeString(cleanPub)
|
||||
|
||||
ephPrivX := make([]byte, 32)
|
||||
io.ReadFull(rand.Reader, ephPrivX)
|
||||
ephPubX, _ := curve25519.X25519(ephPrivX, curve25519.Basepoint)
|
||||
sharedX, _ := curve25519.X25519(ephPrivX, recipientPubX)
|
||||
|
||||
var kyberCT, sharedML []byte
|
||||
|
||||
isHybrid := pub.PublicKey.MLKEMKey != ""
|
||||
if isHybrid {
|
||||
scheme := kyber768.Scheme()
|
||||
pkBytes, _ := hex.DecodeString(pub.PublicKey.MLKEMKey)
|
||||
pkK, _ := scheme.UnmarshalBinaryPublicKey(pkBytes)
|
||||
sharedML, kyberCT, _ = scheme.Encapsulate(pkK)
|
||||
}
|
||||
|
||||
combined := append(sharedX, sharedML...)
|
||||
if isLockSet {
|
||||
passKey := argon2.IDKey([]byte(pass), []byte(apiKey), 1, 64*1024, 4, 32)
|
||||
combined = append(combined, passKey...)
|
||||
zeroize(passKey)
|
||||
}
|
||||
|
||||
h := hkdf.New(sha256.New, combined, nil, []byte("syscrypt-v1-hybrid"))
|
||||
symmetricKey := make([]byte, 32)
|
||||
io.ReadFull(h, symmetricKey)
|
||||
zeroize(symmetricKey)
|
||||
|
||||
aead, _ := cc20.New(symmetricKey)
|
||||
nonce := make([]byte, aead.NonceSize())
|
||||
io.ReadFull(rand.Reader, nonce)
|
||||
ciphertext := aead.Seal(nil, nonce, plaintext, nil)
|
||||
|
||||
var mode byte
|
||||
|
||||
switch {
|
||||
case isHybrid && isLockSet:
|
||||
mode = 0x04 // Post-Quantum + Password Protected
|
||||
case isHybrid:
|
||||
mode = 0x03 // Post-Quantum only
|
||||
case isLockSet:
|
||||
mode = 0x02 // Classical + Password Protected
|
||||
default:
|
||||
mode = 0x01 // Classical Only
|
||||
}
|
||||
|
||||
serialKey, err := utils.FetchFileKey(keyValue, "serial")
|
||||
if err != nil {
|
||||
msg := "unable to fetch key serial. Unable to proceed."
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
serialBytes := []byte(serialKey)
|
||||
serialSize := len(serialBytes)
|
||||
|
||||
maskedSerial := make([]byte, serialSize)
|
||||
for i := 0; i < serialSize; i++ {
|
||||
maskedSerial[i] = serialBytes[i] ^ ephPubX[i%32]
|
||||
}
|
||||
|
||||
var finalBlob []byte
|
||||
|
||||
finalBlob = append(finalBlob, mode)
|
||||
finalBlob = append(finalBlob, byte(serialSize))
|
||||
finalBlob = append(finalBlob, maskedSerial...)
|
||||
finalBlob = append(finalBlob, ephPubX...)
|
||||
|
||||
if isHybrid {
|
||||
finalBlob = append(finalBlob, kyberCT...)
|
||||
}
|
||||
|
||||
finalBlob = append(finalBlob, nonce...)
|
||||
finalBlob = append(finalBlob, ciphertext...)
|
||||
|
||||
dst, err := os.Create(outputValue)
|
||||
if err != nil {
|
||||
fmt.Printf("error: unable to create %s\n", outputValue)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
if isArmoredSet {
|
||||
|
||||
dst.WriteString(vars.PrivateKeyHeader + "\n")
|
||||
encoded := base64.StdEncoding.EncodeToString(finalBlob)
|
||||
|
||||
for i := 0; i < len(encoded); i += 64 {
|
||||
end := i + 64
|
||||
if end > len(encoded) {
|
||||
end = len(encoded)
|
||||
}
|
||||
dst.WriteString(encoded[i:end] + "\n")
|
||||
}
|
||||
|
||||
dst.WriteString(vars.PrivateKeyFooter + "\n")
|
||||
|
||||
} else {
|
||||
dst.Write(finalBlob)
|
||||
}
|
||||
|
||||
fmt.Printf("final blob: %v\n", finalBlob)
|
||||
fmt.Printf("is hybrid: %v\n", isHybrid)
|
||||
|
||||
_ = ciphertext
|
||||
_ = isArmoredSet
|
||||
_ = ephPubX
|
||||
_ = kyberCT
|
||||
_ = mode
|
||||
_ = serialBytes
|
||||
|
||||
//////////////////////////////////////////
|
||||
|
||||
//serialKey, err := utils.FetchFileKey(keyValue, "serial")
|
||||
//if err != nil {
|
||||
// msg := "Unable to fetch key serial. Unable to proceed."
|
||||
// utils.HandleFailure(msg)
|
||||
// os.Exit(1)
|
||||
//}
|
||||
|
||||
//serialBytes := []byte(serialKey)
|
||||
//serialSize := len(serialBytes)
|
||||
|
||||
//maskedSerial := make([]byte, serialSize)
|
||||
//for i := 0; i < serialSize; i++ {
|
||||
// maskedSerial[i] = serialBytes[i] ^ ephPubX[i%32]
|
||||
//}
|
||||
|
||||
//fmt.Printf("serial: %s\n", serialKey)
|
||||
//fmt.Printf("masked: %s\n", maskedSerial)
|
||||
|
||||
//os.Exit(1)
|
||||
|
||||
///////////////////////////////////////////
|
||||
|
||||
//var finalBlob []byte
|
||||
//finalBlob = append(finalBlob, mode)
|
||||
//finalBlob = append(finalBlob, ephPubX...)
|
||||
|
||||
//if isHybrid {
|
||||
// finalBlob = append(finalBlob, kyberCT...)
|
||||
//}
|
||||
|
||||
//finalBlob = append(finalBlob, nonce...)
|
||||
//finalBlob = append(finalBlob, ciphertext...)
|
||||
|
||||
//dst, err := os.Create(outputValue)
|
||||
//if err != nil {
|
||||
// fmt.Printf("Error: unable to create %s\n", outputValue)
|
||||
// os.Exit(1)
|
||||
//}
|
||||
//defer dst.Close()
|
||||
|
||||
//if isArmoredSet {
|
||||
// dst.WriteString(vars.PrivateKeyHeader + "\n")
|
||||
// encoded := base64.StdEncoding.EncodeToString(finalBlob)
|
||||
|
||||
// for i := 0; i < len(encoded); i += 64 {
|
||||
// end := i + 64
|
||||
// if end > len(encoded) {
|
||||
// end = len(encoded)
|
||||
// }
|
||||
// dst.WriteString(encoded[i:end] + "\n")
|
||||
// }
|
||||
|
||||
// dst.WriteString(vars.PrivateKeyFooter + "\n")
|
||||
//} else {
|
||||
|
||||
// dst.Write(finalBlob)
|
||||
//}
|
||||
|
||||
//fmt.Printf("Encryption Complete: %s\n", outputValue)
|
||||
|
||||
//dst, err := os.Create(outputValue)
|
||||
//if err != nil {
|
||||
// fmt.Printf("Error: unable to create %s\n", outputValue)
|
||||
// os.Exit(1)
|
||||
//}
|
||||
//defer dst.Close()
|
||||
|
||||
//dst.Write([]byte{mode})
|
||||
//dst.Write(ephPubX)
|
||||
|
||||
//switch mode {
|
||||
//case 0x03, 0x04:
|
||||
// dst.Write(kyberCT)
|
||||
//}
|
||||
|
||||
//dst.Write(nonce)
|
||||
//dst.Write(ciphertext)
|
||||
|
||||
// validate headers
|
||||
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
504
internal/actions/keygen/keygen.go
Executable file
504
internal/actions/keygen/keygen.go
Executable file
@@ -0,0 +1,504 @@
|
||||
package keygen
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"sources.truenas.cloud/code/syscrypt/internal/utils"
|
||||
"sources.truenas.cloud/code/syscrypt/internal/vars"
|
||||
)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
func FirstRun() {
|
||||
|
||||
defaultFolder := configuration.ConfigKeyFolder
|
||||
|
||||
//fmt.Printf("default folder: %s\n", defaultFolder)
|
||||
|
||||
//fmt.Printf("[DEBUG KEYGEN] Value: %s | Addr: %p\n", config.KeyFolder, &config.KeyFolder)
|
||||
|
||||
//defaultFolder := config.KeyFolder
|
||||
|
||||
//defaultKey := config.KeyFolder + "/" + config.MasterKey
|
||||
//defaultKeyExists := utils.FileExists(defaultKey)
|
||||
//defaultFolderExists := utils.FolderExists(defaultFolder)
|
||||
|
||||
//fmt.Printf("CONFIG KEY FOLDER: %s\n", config.KeyFolder)
|
||||
|
||||
_ = defaultFolder
|
||||
|
||||
os.Exit(1)
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
func Validate() {
|
||||
|
||||
keygenAllowedFlags := map[string]struct{}{
|
||||
"-C": {},
|
||||
"-i": {},
|
||||
"-c": {},
|
||||
"-PQ": {},
|
||||
"-k": {},
|
||||
"-f": {},
|
||||
}
|
||||
|
||||
utils.ValidateAllowedFlags(keygenAllowedFlags)
|
||||
|
||||
keygenRequiredFlags := []vars.FlagRequirement{
|
||||
{Flag: "-f", IsRequired: true},
|
||||
}
|
||||
|
||||
// friendly name -f
|
||||
// keypath -K
|
||||
// output -o
|
||||
|
||||
utils.ValidateRequiredFlags(keygenRequiredFlags, "keygen")
|
||||
|
||||
// friendlyname
|
||||
|
||||
isFriendlySet, friendlyHasValue := utils.IsFlagPassed("f")
|
||||
friendlyValue, _ := utils.GetFlagValue("f")
|
||||
isFriendlyValid := utils.IsAlphaNumeric(friendlyValue)
|
||||
|
||||
if isFriendlySet && !friendlyHasValue {
|
||||
msg := fmt.Sprintf("%s: -f FRIENDLYNAME: requires a value.\n"+
|
||||
"Do not enter spaces or special characters. e.g. 'masterkey'", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if isFriendlySet && friendlyHasValue && !isFriendlyValid {
|
||||
msg := fmt.Sprintf("%s: -f FRIENDLYNAME: invalid friendly name.\n"+
|
||||
"The friendly name requires an alphanumeric value. e.g. 'masterkey'\n"+
|
||||
"Do not enter paths, spaces, special characters or file extensions.", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// check default keys
|
||||
|
||||
// keypath
|
||||
|
||||
isKeyPathSet, keyPathHasValue := utils.IsFlagPassed("k")
|
||||
keyPathValue, _ := utils.GetFlagValue("k")
|
||||
keyPathIsValid := utils.IsValidPath(keyPathValue)
|
||||
keyPathExists := utils.FolderExists(keyPathValue)
|
||||
|
||||
if isKeyPathSet && !keyPathHasValue {
|
||||
msg := fmt.Sprintf("%s: -k KEYPATH: requires a value.", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if isKeyPathSet && !keyPathIsValid {
|
||||
msg := fmt.Sprintf("%s: -k KEYPATH: requires a valid folder path.", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if isKeyPathSet && keyPathIsValid && !keyPathExists {
|
||||
msg := fmt.Sprintf("%s: -k KEYPATH: folder path '%s' does not exist.", vars.CommandFlag, keyPathValue)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var keyFolder string
|
||||
var defaultSet bool
|
||||
|
||||
if isKeyPathSet {
|
||||
defaultSet = false
|
||||
keyFolder = keyPathValue
|
||||
} else {
|
||||
defaultSet = true
|
||||
keyFolder = config.KeyFolder
|
||||
}
|
||||
|
||||
if defaultSet {
|
||||
keyPathIsValid = utils.IsValidPath(keyFolder)
|
||||
}
|
||||
|
||||
if defaultSet && !keyPathIsValid {
|
||||
msg := fmt.Sprintf("%s: DEFAULT KEYPATH '%s' was not found.", vars.CommandFlag, config.KeyFolder)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// comment
|
||||
|
||||
isCommentSet, commentHasValue := utils.IsFlagPassed("C")
|
||||
if isCommentSet && !commentHasValue {
|
||||
msg := fmt.Sprintf("%s: -C COMMENT: flag is set but no value was provided.", vars.CommandFlag)
|
||||
utils.HandleFailure(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Printf("key folder: %s\n", keyFolder)
|
||||
|
||||
_ = isKeyPathSet
|
||||
_ = keyPathHasValue
|
||||
_ = keyPathIsValid
|
||||
_ = keyPathExists
|
||||
_ = keyFolder
|
||||
|
||||
// comment
|
||||
|
||||
// output
|
||||
|
||||
KeyGen()
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
func generateRandomSerial() string {
|
||||
token := make([]byte, 15)
|
||||
rand.Read(token)
|
||||
return hex.EncodeToString(token)
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
func getCurrentDate() string {
|
||||
return time.Now().Format("2006-01-02 15:04:05")
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
func saveKeyFile(filename string, permission string, data interface{}) {
|
||||
|
||||
fmt.Printf("%v\n", data)
|
||||
os.Exit(1)
|
||||
|
||||
if permission == "" {
|
||||
fmt.Printf("error: permission code required.\n")
|
||||
return
|
||||
}
|
||||
|
||||
fileData, err := json.MarshalIndent(data, "", " ")
|
||||
if err != nil {
|
||||
fmt.Printf("error encoding json: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
err = os.WriteFile(filename, fileData, 0600)
|
||||
if err != nil {
|
||||
fmt.Printf("Error writing %s: %v\n", filename, err)
|
||||
return
|
||||
}
|
||||
|
||||
permUint, _ := strconv.ParseUint(permission, 8, 32)
|
||||
err = os.Chmod(filename, os.FileMode(permUint))
|
||||
if err != nil {
|
||||
fmt.Printf("Error adjusting permissions on %s: %v\n", filename, err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("Success: '%s' saved successfully.\n", filename)
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
func KeyGen() {
|
||||
|
||||
outputFolder, _ := utils.GetFlagValue("o")
|
||||
isPQSet, _ := utils.IsFlagPassed("PQ")
|
||||
commentValue, _ := utils.GetFlagValue("C")
|
||||
|
||||
if outputFolder == "" {
|
||||
outputFolder = config.KeyFolder
|
||||
}
|
||||
|
||||
_ = isPQSet
|
||||
_ = commentValue
|
||||
|
||||
//fmt.Printf("%s", config.KeyFolder)
|
||||
|
||||
//outputValue, _ := utils.GetFlagValue("o")
|
||||
//isPQSet, _ := utils.IsFlagPassed("PQ")
|
||||
//commentValue, _ := utils.GetFlagValue("C")
|
||||
|
||||
//pubWrap := syscrypt.PublicKeyWrapper{}
|
||||
//privWrap := syscrypt.PrivateKeyWrapper{}
|
||||
//apiWrap := syscrypt.ApiKeyWrapper{}
|
||||
///
|
||||
//var privX, pubX [32]byte
|
||||
//io.ReadFull(rand.Reader, privX[:])
|
||||
//curve25519.ScalarBaseMult(&pubX, &privX)
|
||||
|
||||
//serial := generateRandomSerial()
|
||||
//date := getCurrentDate()
|
||||
|
||||
//password := (generatepassword)
|
||||
|
||||
//pubWrap.PublicKey.Key = vars.DefaultPrefixLabel + hex.EncodeToString(pubX[:])
|
||||
//pubWrap.PublicKey.Serial = serial
|
||||
//pubWrap.PublicKey.Date = date
|
||||
//pubWrap.PublicKey.Comment = commentValue
|
||||
|
||||
//privWrap.PrivateKey.Key = vars.PrivateKeyPrefixLabel + hex.EncodeToString(privX[:])
|
||||
//privWrap.PrivateKey.Serial = serial
|
||||
//privWrap.PrivateKey.Date = date
|
||||
//privWrap.PrivateKey.Comment = commentValue
|
||||
|
||||
//apiWrap.ApiKey.Key = ""
|
||||
//apiWrap.ApiKey.Serial = serial
|
||||
//apiWrap.ApiKey.Date = date
|
||||
//apiWrap.ApiKey.Comment = commentValue
|
||||
|
||||
/*
|
||||
type ApiKeyWrapper struct {
|
||||
ApiKey struct {
|
||||
Key string `json:"key"`
|
||||
Serial string `json:"serial"`
|
||||
Date string `json:"date"`
|
||||
Comment string `json:"comment"`
|
||||
} `json:"APIKey"`
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
//if isPQSet {
|
||||
// scheme := kyber768.Scheme()
|
||||
// pkK, skK, err := scheme.GenerateKeyPair()
|
||||
// if err != nil {
|
||||
// fmt.Printf("error: keygen failed: %v\n", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
// pkBytes, _ := pkK.MarshalBinary()
|
||||
// skBytes, _ := skK.MarshalBinary()
|
||||
|
||||
// pubWrap.PublicKey.MLKEMKey = vars.PQPublicKeyPrefixLabel + hex.EncodeToString(pkBytes)
|
||||
// privWrap.PrivateKey.MLKEMKey = vars.PQPrivateKeyPrefixLabel + hex.EncodeToString(skBytes)
|
||||
//}
|
||||
|
||||
//pubJSON, err := json.MarshalIndent(pubWrap, "", " ")
|
||||
//if err != nil {
|
||||
// fmt.Printf("Marshal Error: %v\n", err)
|
||||
// return
|
||||
//}
|
||||
|
||||
//privJSON, err := json.MarshalIndent(privWrap, "", " ")
|
||||
//if err != nil {
|
||||
// fmt.Printf("Marshal Error: %v\n", err)
|
||||
// return
|
||||
//}
|
||||
|
||||
//MasterFolder := config.KeyFolder
|
||||
|
||||
// Public Key File
|
||||
|
||||
//pubFullPath := outputValue
|
||||
//pubDir := filepath.Dir(pubFullPath)
|
||||
//pubBase := filepath.Base(pubFullPath)
|
||||
//pubExt := filepath.Ext(pubBase)
|
||||
//pubFileName := strings.TrimSuffix(pubBase, pubExt)
|
||||
//pubFilePath := MasterFolder + "/" + pubFileName + ".pub" + pubExt
|
||||
|
||||
// API Key File
|
||||
|
||||
//apiFullPath := outputValue
|
||||
//apiDir := filepath.Dir(apiFullPath)
|
||||
//apiBase := filepath.Base(apiFullPath)
|
||||
//apiExt := filepath.Ext(apiBase)
|
||||
//apiFileName := strings.TrimSuffix(apiBase, apiExt)
|
||||
//apiFilePath := MasterFolder + "/" + apiFileName + ".api" + apiExt
|
||||
|
||||
// Master Password
|
||||
/*
|
||||
passFullPath := outputValue
|
||||
passDir := filepath.Dir(passFullPath)
|
||||
passBase := filepath.Base(passFullPath)
|
||||
passExt := filepath.Ext(passBase)
|
||||
passFileName := strings.TrimSuffix(passBase, passExt)
|
||||
passFilePath := MasterFolder + "/" + passFileName + ".secret" + passExt
|
||||
|
||||
fmt.Printf("fullpath: %s\n", passFullPath)
|
||||
fmt.Printf("dir: %s\n", passDir)
|
||||
fmt.Printf("base: %s\n", passBase)
|
||||
fmt.Printf("ext: %s\n", passExt)
|
||||
fmt.Printf("filename: %s\n", passFileName)
|
||||
fmt.Printf("path: %s\n", passFilePath)
|
||||
|
||||
*/
|
||||
|
||||
// Save to disk
|
||||
|
||||
//err = os.WriteFile(pubFilePath, pubJSON, 0644)
|
||||
//if err != nil {
|
||||
// fmt.Printf("File Error: %v\n", err)
|
||||
// os.Exit(1)
|
||||
//}
|
||||
|
||||
//err = os.WriteFile(outputValue, privJSON, 0600)
|
||||
//if err != nil {
|
||||
// fmt.Printf("File Error: %v\n", err)
|
||||
// os.Exit(1)
|
||||
//}
|
||||
|
||||
//saveKeyFile(outputValue, "600", privJSON)
|
||||
|
||||
//saveKeyFile(filename string, permission string, data interface{})
|
||||
|
||||
////pubFullPath := outputValue
|
||||
////pubDir := filepath.Dir(pubFullPath)
|
||||
////pubBase := filepath.Base(pubFullPath)
|
||||
////pubExt := filepath.Ext(pubBase)
|
||||
////pubClean := strings.TrimSuffix(pubBase, pubExt)
|
||||
////pubFileOut := pubClean + ".pub" + pubExt
|
||||
////pubFileOut = pubDir + "/" + pubFileOut
|
||||
|
||||
//_ = outputValue
|
||||
//_ = commentValue
|
||||
//_ = pubJSON
|
||||
//_ = privJSON
|
||||
//_ = pubDir
|
||||
//_ = pubFilePath
|
||||
//_ = apiDir
|
||||
//_ = apiFilePath
|
||||
//_ = apiWrap
|
||||
//_ = passDir
|
||||
//_ = passFilePath
|
||||
|
||||
//fmt.Printf("%v\n", pkK)
|
||||
//fmt.Printf("%v\n", skK)
|
||||
|
||||
////outputValue, _ := utils.GetFlagValue("o")
|
||||
|
||||
////isPQSet, _ := utils.IsFlagPassed("PQ")
|
||||
////commentValue, _ := utils.GetFlagValue("C")
|
||||
|
||||
////privX := make([]byte, 32)
|
||||
////rand.Read(privX)
|
||||
////pubX, _ := curve25519.X25519(privX, curve25519.Basepoint)
|
||||
|
||||
////pubWrap := syscrypt.PublicKeyWrapper{}
|
||||
////privWrap := syscrypt.PrivateKeyWrapper{}
|
||||
////apiWrap := syscrypt.ApiKeyWrapper{}
|
||||
|
||||
////_ = apiWrap
|
||||
///
|
||||
////serial := generateRandomSerial()
|
||||
////date := getCurrentDate()
|
||||
|
||||
////if isPQSet {
|
||||
//// pubK, privK, _ := kyber768.GenerateKeyPair(rand.Reader)
|
||||
//// pBytes, _ := pubK.MarshalBinary()
|
||||
//// sBytes, _ := privK.MarshalBinary()
|
||||
//// pubWrap.PublicKey.MLKEMKey = vars.PQPublicKeyPrefixLabel + hex.EncodeToString(pBytes)
|
||||
//// privWrap.PrivateKey.MLKEMKey = vars.PQPrivateKeyPrefixLabel + hex.EncodeToString(sBytes)
|
||||
////}
|
||||
|
||||
////pubWrap.PublicKey.Key = vars.DefaultPrefixLabel + hex.EncodeToString(pubX)
|
||||
////pubWrap.PublicKey.Serial = serial
|
||||
////pubWrap.PublicKey.Date = date
|
||||
////pubWrap.PublicKey.Comment = commentValue
|
||||
|
||||
////privWrap.PrivateKey.Key = vars.PrivateKeyPrefixLabel + hex.EncodeToString(privX)
|
||||
////privWrap.PrivateKey.Serial = serial
|
||||
////privWrap.PrivateKey.Date = date
|
||||
////privWrap.PrivateKey.Comment = commentValue
|
||||
|
||||
//apiWrap.ApiKey.Key = GenerateAPIKey(xxx, )
|
||||
//apiWrap.ApiKey.Serial = serial
|
||||
//apiWrap.ApiKey.Date = date
|
||||
//apiWrap.ApiKey.Comment = commentValue
|
||||
|
||||
//type ApiKeyWrapper struct {
|
||||
// ApiKey struct {
|
||||
// Key string `json:"key"`
|
||||
// Serial string `json:"serial"`
|
||||
// Date string `json:"date"`
|
||||
// Comment string `json:"comment"`
|
||||
// } `json:"APIKey"`
|
||||
//}
|
||||
|
||||
////fmt.Printf("public key: %s\n", pubWrap.PublicKey.Key)
|
||||
////fmt.Printf("private key: %s\n", privWrap.PrivateKey.Key)
|
||||
////fmt.Printf("pq: %s\n", pubWrap.PublicKey.MLKEMKey)
|
||||
|
||||
//preview, _ := json.MarshalIndent(privWrap, "", " ")
|
||||
//fmt.Println(string(preview))
|
||||
|
||||
////pubFullPath := outputValue
|
||||
////pubDir := filepath.Dir(pubFullPath)
|
||||
////pubBase := filepath.Base(pubFullPath)
|
||||
////pubExt := filepath.Ext(pubBase)
|
||||
////pubClean := strings.TrimSuffix(pubBase, pubExt)
|
||||
////pubFileOut := pubClean + ".pub" + pubExt
|
||||
////pubFileOut = pubDir + "/" + pubFileOut
|
||||
|
||||
////apiFullPath := outputValue
|
||||
////apiDir := filepath.Dir(apiFullPath)
|
||||
////apiBase := filepath.Base(apiFullPath)
|
||||
////apiExt := filepath.Ext(apiBase)
|
||||
////apiClean := strings.TrimSuffix(apiBase, apiExt)
|
||||
////apiFileOut := apiClean + ".api" + apiExt
|
||||
////apiFileOut = apiDir + "/" + apiFileOut
|
||||
|
||||
// Generate Master Password if one doesnt already exist
|
||||
|
||||
//mpExists := utils.ReadJson("config.masterpass", config.ConfigPath)
|
||||
|
||||
////_ = pubDir
|
||||
////_ = apiDir
|
||||
////_ = apiFileOut
|
||||
|
||||
////fmt.Printf("public out: %s\n", pubDir+"/"+pubFileOut)
|
||||
////fmt.Printf("api out: %s\n", apiDir+"/"+apiFileOut)
|
||||
|
||||
////saveKeyFile(pubFileOut, "0600", pubWrap)
|
||||
////saveKeyFile(outputValue, "0644", privWrap)
|
||||
//saveKeyFile(xxxx, 0600, xxxxxx)
|
||||
|
||||
//func saveKeyFile(filename string, permission string, data interface{}) {
|
||||
|
||||
//type PublicKeyWrapper struct {
|
||||
// PublicKey struct {
|
||||
// Key string `json:"key"`
|
||||
// MLKEMKey string `json:"mlkem_key,omitempty"`
|
||||
// Serial string `json:"serial"`
|
||||
// Date string `json:"date"`
|
||||
// Comment string `json:"comment"`
|
||||
// } `json:"PublicKey"`
|
||||
//}
|
||||
|
||||
//privRaw := make([]byte, 32)
|
||||
//serial := utils.GenerateSerial(27)
|
||||
//io.ReadFull(rand.Reader, privRaw)
|
||||
//pubRaw, _ := curve25519.X25519(privRaw, curve25519.Basepoint)
|
||||
//dateStr := time.Now().Format("2006-01-02 15:04:05")
|
||||
|
||||
//privStruct := syscrypt.PrivateKeyWrapper{}
|
||||
//privStruct.PrivateKey.Key = vars.PrivateKeyPrefixLabel + hex.EncodeToString(privRaw)
|
||||
//privStruct.PrivateKey.Serial = serial
|
||||
//privStruct.PrivateKey.Date = dateStr
|
||||
//privStruct.PrivateKey.Comment = vars.Comment
|
||||
|
||||
//pubStruct := syscrypt.PublicKeyWrapper{}
|
||||
//pubStruct.PublicKey.Key = vars.DefaultPrefixLabel + hex.EncodeToString(pubRaw)
|
||||
//pubStruct.PublicKey.Serial = serial
|
||||
//pubStruct.PublicKey.Date = dateStr
|
||||
//pubStruct.PublicKey.Comment = vars.Comment
|
||||
|
||||
//pBytes, _ := json.MarshalIndent(privStruct, "", " ")
|
||||
//pubBytes, _ := json.MarshalIndent(pubStruct, "", " ")
|
||||
|
||||
//fmt.Printf("%s\n", pBytes)
|
||||
//fmt.Printf("%s\n", pubBytes)
|
||||
//fmt.Printf("%s\n", pubStruct.PublicKey.Serial)
|
||||
|
||||
//utils.GenerateKeys(pubStruct.PublicKey.Key, privStruct.PrivateKey.Key, serial)
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Reference in New Issue
Block a user