Merge branch 'main' into test-sigil-coverage
This commit is contained in:
commit
b03ba0cd99
16 changed files with 368 additions and 16 deletions
17
.github/workflows/mkdocs.yml
vendored
Normal file
17
.github/workflows/mkdocs.yml
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
name: Publish Docs
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- run: |
|
||||
pip install mkdocs-material
|
||||
- run: |
|
||||
cd docs && mkdocs gh-deploy --force --clean --verbose
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,7 +1,6 @@
|
|||
node_modules
|
||||
package-lock.json
|
||||
.idea
|
||||
go.sum
|
||||
covdata/
|
||||
merged_covdata/
|
||||
coverage.txt
|
||||
|
|
|
|||
33
docs/docs/checksums.md
Normal file
33
docs/docs/checksums.md
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# Checksums
|
||||
|
||||
This example demonstrates how to use the `crypt` service to calculate checksums using various algorithms.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/Snider/Enchantrix/pkg/crypt"
|
||||
)
|
||||
|
||||
func demoChecksums() {
|
||||
fmt.Println("--- Checksum Demo ---")
|
||||
cryptService := crypt.NewService()
|
||||
|
||||
// Luhn
|
||||
luhnPayloadGood := "49927398716"
|
||||
luhnPayloadBad := "49927398717"
|
||||
fmt.Printf("Luhn Checksum:\n")
|
||||
fmt.Printf(" - Payload '%s' is valid: %v\n", luhnPayloadGood, cryptService.Luhn(luhnPayloadGood))
|
||||
fmt.Printf(" - Payload '%s' is valid: %v\n", luhnPayloadBad, cryptService.Luhn(luhnPayloadBad))
|
||||
|
||||
// Fletcher
|
||||
fletcherPayload := "abcde"
|
||||
fmt.Printf("\nFletcher Checksums (Payload: \"%s\"):\n", fletcherPayload)
|
||||
fmt.Printf(" - Fletcher16: %d\n", cryptService.Fletcher16(fletcherPayload))
|
||||
fmt.Printf(" - Fletcher32: %d\n", cryptService.Fletcher32(fletcherPayload))
|
||||
fmt.Printf(" - Fletcher64: %d\n", cryptService.Fletcher64(fletcherPayload))
|
||||
fmt.Println()
|
||||
}
|
||||
```
|
||||
34
docs/docs/hashing.md
Normal file
34
docs/docs/hashing.md
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# Hashing
|
||||
|
||||
This example demonstrates how to use the `crypt` service to hash a payload using various algorithms.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/Snider/Enchantrix/pkg/crypt"
|
||||
)
|
||||
|
||||
func demoHashing() {
|
||||
fmt.Println("--- Hashing Demo ---")
|
||||
cryptService := crypt.NewService()
|
||||
payload := "Enchantrix"
|
||||
|
||||
hashTypes := []crypt.HashType{
|
||||
crypt.LTHN,
|
||||
crypt.MD5,
|
||||
crypt.SHA1,
|
||||
crypt.SHA256,
|
||||
crypt.SHA512,
|
||||
}
|
||||
|
||||
fmt.Printf("Payload to hash: \"%s\"\n", payload)
|
||||
for _, hashType := range hashTypes {
|
||||
hash := cryptService.Hash(hashType, payload)
|
||||
fmt.Printf(" - %-6s: %s\n", hashType, hash)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
```
|
||||
17
docs/docs/index.md
Normal file
17
docs/docs/index.md
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# Welcome to Enchantrix
|
||||
|
||||
Enchantrix is a Go-based crypto library and miner application. This documentation provides information on how to use the various features of the Enchantrix library.
|
||||
|
||||
## Trix File Format
|
||||
|
||||
The `.trix` file format is a generic and flexible binary container for storing an arbitrary data payload alongside structured metadata. For more information, see the [Trix File Format](./trix_format.md) page.
|
||||
|
||||
## Examples
|
||||
|
||||
The following pages provide examples of how to use the Enchantrix library:
|
||||
|
||||
* [Trix & Sigil Chaining](./trix_and_sigils.md)
|
||||
* [Hashing](./hashing.md)
|
||||
* [Checksums](./checksums.md)
|
||||
* [RSA](./rsa.md)
|
||||
* [Standalone Sigils](./standalone_sigils.md)
|
||||
52
docs/docs/rsa.md
Normal file
52
docs/docs/rsa.md
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# RSA
|
||||
|
||||
This example demonstrates how to use the `crypt` service to generate an RSA key pair, encrypt a message, and then decrypt it.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/Snider/Enchantrix/pkg/crypt"
|
||||
)
|
||||
|
||||
func demoRSA() {
|
||||
fmt.Println("--- RSA Demo ---")
|
||||
cryptService := crypt.NewService()
|
||||
|
||||
// 1. Generate RSA key pair
|
||||
fmt.Println("Generating 2048-bit RSA key pair...")
|
||||
publicKey, privateKey, err := cryptService.GenerateRSAKeyPair(2048)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to generate RSA key pair: %v", err)
|
||||
}
|
||||
fmt.Println("Key pair generated successfully.")
|
||||
|
||||
// 2. Encrypt a message
|
||||
message := []byte("This is a secret message for RSA.")
|
||||
fmt.Printf("\nOriginal message: %s\n", message)
|
||||
ciphertext, err := cryptService.EncryptRSA(publicKey, message, nil)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to encrypt with RSA: %v", err)
|
||||
}
|
||||
fmt.Printf("Encrypted ciphertext (base64): %s\n", base64.StdEncoding.EncodeToString(ciphertext))
|
||||
|
||||
// 3. Decrypt the message
|
||||
decrypted, err := cryptService.DecryptRSA(privateKey, ciphertext, nil)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to decrypt with RSA: %v", err)
|
||||
}
|
||||
fmt.Printf("Decrypted message: %s\n", decrypted)
|
||||
|
||||
// 4. Verify
|
||||
if string(message) == string(decrypted) {
|
||||
fmt.Println("\nSuccess! RSA decrypted message matches the original.")
|
||||
} else {
|
||||
fmt.Println("\nFailure! RSA decrypted message does not match the original.")
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
```
|
||||
59
docs/docs/standalone_sigils.md
Normal file
59
docs/docs/standalone_sigils.md
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
# Standalone Sigils
|
||||
|
||||
This example demonstrates how to use sigils independently to transform data.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/Snider/Enchantrix/pkg/enchantrix"
|
||||
)
|
||||
|
||||
func demoSigils() {
|
||||
fmt.Println("--- Standalone Sigil Demo ---")
|
||||
data := []byte(`{"message": "hello world"}`)
|
||||
fmt.Printf("Original data: %s\n", data)
|
||||
|
||||
// A chain of sigils to apply
|
||||
sigils := []string{"gzip", "base64"}
|
||||
fmt.Printf("Applying sigil chain: %v\n", sigils)
|
||||
|
||||
var transformedData = data
|
||||
for _, name := range sigils {
|
||||
s, err := enchantrix.NewSigil(name)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create sigil %s: %v", name, err)
|
||||
}
|
||||
transformedData, err = s.In(transformedData)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to apply sigil %s 'In': %v", name, err)
|
||||
}
|
||||
fmt.Printf(" -> After '%s': %s\n", name, transformedData)
|
||||
}
|
||||
|
||||
fmt.Println("\nReversing sigil chain...")
|
||||
// Reverse the transformations
|
||||
for i := len(sigils) - 1; i >= 0; i-- {
|
||||
name := sigils[i]
|
||||
s, err := enchantrix.NewSigil(name)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create sigil %s: %v", name, err)
|
||||
}
|
||||
transformedData, err = s.Out(transformedData)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to apply sigil %s 'Out': %v", name, err)
|
||||
}
|
||||
fmt.Printf(" -> After '%s' Out: %s\n", name, transformedData)
|
||||
}
|
||||
|
||||
if string(data) == string(transformedData) {
|
||||
fmt.Println("Success! Data returned to original state.")
|
||||
} else {
|
||||
fmt.Println("Failure! Data did not return to original state.")
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
```
|
||||
124
docs/docs/trix_and_sigils.md
Normal file
124
docs/docs/trix_and_sigils.md
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
# Trix & Sigil Chaining
|
||||
|
||||
This example demonstrates how to use the Trix container with a chain of sigils to obfuscate and then encrypt a payload.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/Snider/Enchantrix/pkg/crypt"
|
||||
"github.com/Snider/Enchantrix/pkg/crypt/std/chachapoly"
|
||||
"github.com/Snider/Enchantrix/pkg/trix"
|
||||
)
|
||||
|
||||
func demoTrix() {
|
||||
fmt.Println("--- Trix & Sigil Chaining Demo ---")
|
||||
|
||||
// 1. Original plaintext (JSON data) and encryption key
|
||||
type Message struct {
|
||||
Author string `json:"author"`
|
||||
Time int64 `json:"time"`
|
||||
Body string `json:"body"`
|
||||
}
|
||||
originalMessage := Message{Author: "Jules", Time: time.Now().Unix(), Body: "This is a super secret message!"}
|
||||
plaintext, err := json.Marshal(originalMessage)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to marshal JSON: %v", err)
|
||||
}
|
||||
key := make([]byte, 32) // In a real application, use a secure key
|
||||
for i := range key {
|
||||
key[i] = 1
|
||||
}
|
||||
|
||||
fmt.Printf("Original Payload (JSON):\n%s\n\n", plaintext)
|
||||
|
||||
// 2. Create a Trix container with the plaintext and attach a chain of sigils
|
||||
sigilChain := []string{"json-indent", "gzip", "base64", "reverse"}
|
||||
trixContainer := &trix.Trix{
|
||||
Header: map[string]interface{}{},
|
||||
Payload: plaintext,
|
||||
InSigils: sigilChain,
|
||||
}
|
||||
|
||||
// 3. Pack the Trix container to apply the sigil transformations
|
||||
fmt.Println("Packing payload with sigils:", sigilChain)
|
||||
if err := trixContainer.Pack(); err != nil {
|
||||
log.Fatalf("Failed to pack trix container: %v", err)
|
||||
}
|
||||
fmt.Printf("Packed (obfuscated) payload is now non-human-readable bytes.\n\n")
|
||||
|
||||
// 4. Encrypt the packed payload
|
||||
ciphertext, err := chachapoly.Encrypt(trixContainer.Payload, key)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to encrypt: %v", err)
|
||||
}
|
||||
trixContainer.Payload = ciphertext // Update the payload with the ciphertext
|
||||
|
||||
// 5. Add encryption metadata and checksum to the header
|
||||
nonce := ciphertext[:24]
|
||||
trixContainer.Header = map[string]interface{}{
|
||||
"content_type": "application/json",
|
||||
"encryption_algorithm": "chacha20poly1305",
|
||||
"nonce": base64.StdEncoding.EncodeToString(nonce),
|
||||
"created_at": time.Now().UTC().Format(time.RFC3339),
|
||||
}
|
||||
trixContainer.ChecksumAlgo = crypt.SHA512
|
||||
fmt.Printf("Checksum will be calculated with %s and added to the header.\n", trixContainer.ChecksumAlgo)
|
||||
|
||||
// 6. Encode the .trix container into its binary format
|
||||
magicNumber := "MyT1"
|
||||
encodedTrix, err := trix.Encode(trixContainer, magicNumber, nil)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to encode .trix container: %v", err)
|
||||
}
|
||||
fmt.Println("Successfully created .trix container.")
|
||||
|
||||
// --- DECODING ---
|
||||
fmt.Println("--- DECODING ---")
|
||||
|
||||
// 7. Decode the .trix container
|
||||
decodedTrix, err := trix.Decode(encodedTrix, magicNumber, nil)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to decode .trix container: %v", err)
|
||||
}
|
||||
fmt.Println("Successfully decoded .trix container. Checksum verified.")
|
||||
fmt.Printf("Decoded Header: %+v\n", decodedTrix.Header)
|
||||
|
||||
// 8. Decrypt the payload
|
||||
decryptedPayload, err := chachapoly.Decrypt(decodedTrix.Payload, key)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to decrypt: %v", err)
|
||||
}
|
||||
decodedTrix.Payload = decryptedPayload
|
||||
fmt.Println("Payload decrypted.")
|
||||
|
||||
// 9. Unpack the Trix container to reverse the sigil transformations
|
||||
decodedTrix.InSigils = trixContainer.InSigils // Re-attach sigils for unpacking
|
||||
fmt.Println("Unpacking payload by reversing sigils:", decodedTrix.InSigils)
|
||||
if err := decodedTrix.Unpack(); err != nil {
|
||||
log.Fatalf("Failed to unpack trix container: %v", err)
|
||||
}
|
||||
fmt.Printf("Unpacked (original) payload:\n%s\n", decodedTrix.Payload)
|
||||
|
||||
// 10. Verify the result
|
||||
// To properly verify, we need to compact the indented JSON before comparing
|
||||
var compactedPayload bytes.Buffer
|
||||
if err := json.Compact(&compactedPayload, decodedTrix.Payload); err != nil {
|
||||
log.Fatalf("Failed to compact final payload for verification: %v", err)
|
||||
}
|
||||
|
||||
if bytes.Equal(plaintext, compactedPayload.Bytes()) {
|
||||
fmt.Println("\nSuccess! The message was decrypted and unpacked correctly.")
|
||||
} else {
|
||||
fmt.Println("\nFailure! The final payload does not match the original.")
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
```
|
||||
12
docs/mkdocs.yml
Normal file
12
docs/mkdocs.yml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
site_name: Enchantrix
|
||||
theme:
|
||||
name: material
|
||||
nav:
|
||||
- Home: index.md
|
||||
- Trix File Format: trix_format.md
|
||||
- Examples:
|
||||
- Trix & Sigil Chaining: trix_and_sigils.md
|
||||
- Hashing: hashing.md
|
||||
- Checksums: checksums.md
|
||||
- RSA: rsa.md
|
||||
- Standalone Sigils: standalone_sigils.md
|
||||
10
go.work.sum
10
go.work.sum
|
|
@ -1,2 +1,8 @@
|
|||
github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk=
|
||||
github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM=
|
||||
golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
|
||||
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
|
||||
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
|
||||
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||
|
|
|
|||
|
|
@ -160,4 +160,4 @@ func (s *Service) EncryptRSA(publicKey, data, label []byte) ([]byte, error) {
|
|||
func (s *Service) DecryptRSA(privateKey, ciphertext, label []byte) ([]byte, error) {
|
||||
s.ensureRSA()
|
||||
return s.rsa.Decrypt(privateKey, ciphertext, label)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,11 +31,11 @@ func TestHash_Bad(t *testing.T) {
|
|||
func TestHash_Ugly(t *testing.T) {
|
||||
// Test with potentially problematic inputs
|
||||
testCases := []string{
|
||||
"", // Empty string
|
||||
" ", // Whitespace
|
||||
"\x00\x01\x02\x03\x04", // Null bytes
|
||||
"", // Empty string
|
||||
" ", // Whitespace
|
||||
"\x00\x01\x02\x03\x04", // Null bytes
|
||||
strings.Repeat("a", 1024*1024), // Large payload (1MB)
|
||||
"こんにちは", // Unicode characters
|
||||
"こんにちは", // Unicode characters
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
|
@ -108,7 +108,6 @@ func TestFletcher64_Ugly(t *testing.T) {
|
|||
assert.NotEqual(t, uint64(0), service.Fletcher64(" "), "Checksum of space should not be 0")
|
||||
}
|
||||
|
||||
|
||||
// --- RSA Tests ---
|
||||
|
||||
func TestRSA_Good(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -88,4 +88,4 @@ func (s *Service) Decrypt(privateKey, ciphertext, label []byte) ([]byte, error)
|
|||
}
|
||||
|
||||
return plaintext, nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ var (
|
|||
type Trix struct {
|
||||
Header map[string]interface{}
|
||||
Payload []byte
|
||||
InSigils []string `json:"-"` // Ignore Sigils during JSON marshaling
|
||||
OutSigils []string `json:"-"` // Ignore Sigils during JSON marshaling
|
||||
InSigils []string `json:"-"` // Ignore Sigils during JSON marshaling
|
||||
OutSigils []string `json:"-"` // Ignore Sigils during JSON marshaling
|
||||
ChecksumAlgo crypt.HashType `json:"-"`
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -117,10 +117,10 @@ func TestTrixEncodeDecode_Ugly(t *testing.T) {
|
|||
t.Run("CorruptedHeaderLength", func(t *testing.T) {
|
||||
// Manually construct a byte slice where the header length is larger than the actual data.
|
||||
var buf []byte
|
||||
buf = append(buf, []byte(magicNumber)...) // Magic Number
|
||||
buf = append(buf, byte(trix.Version)) // Version
|
||||
buf = append(buf, []byte{0, 0, 3, 232}...) // BigEndian representation of 1000
|
||||
buf = append(buf, []byte("{}")...) // A minimal valid JSON header
|
||||
buf = append(buf, []byte(magicNumber)...) // Magic Number
|
||||
buf = append(buf, byte(trix.Version)) // Version
|
||||
buf = append(buf, []byte{0, 0, 3, 232}...) // BigEndian representation of 1000
|
||||
buf = append(buf, []byte("{}")...) // A minimal valid JSON header
|
||||
buf = append(buf, []byte("payload")...)
|
||||
|
||||
_, err := trix.Decode(buf, magicNumber, nil)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue