dockerized, integration with cloudflare tunnel, encryption and decryption.

This commit is contained in:
Josh Ashton
2024-07-19 15:14:57 -06:00
parent bfc343cd11
commit 9d5fdb97c8
14 changed files with 70 additions and 440 deletions
View File
View File
View File
@@ -1,8 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/web-services-gin.iml" filepath="$PROJECT_DIR$/.idea/web-services-gin.iml" />
</modules>
</component>
</project>
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../../../.." vcs="Git" />
</component>
</project>
@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
@@ -1,6 +0,0 @@
curl http://localhost:8080/prompts -d '{
"prompt": "68 D7 B8 23 C2 78 73 70 85 15 A0 9E B 88 C9 A0 E9 3 C 1D 85 D3 CF 62 23 C7 59 1F CB E6 27 D2 E1 63 60 65 3 5 C6 52 F3 B3 B0 D9 8 4 3F 16 86 B8 44 66 FF B7 B0 AC 6 B0 F9 1C 7F 78 EB 87 49 EB F9 76 C2 4 89 1B 9E BE 86 44 15 69 1A 86 A E0 E9 73 1C 0 99 D1",
"sum": "DGyij1YH2G5UJrRnleD6gn8WJ9Y="
}'
#curl http://localhost:8080/prompts
@@ -1,34 +0,0 @@
module example.com/web-service-gin
go 1.22.5
require github.com/gin-gonic/gin v1.10.0
require (
github.com/bytedance/sonic v1.11.6 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.20.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
golang.org/x/arch v0.8.0 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
google.golang.org/protobuf v1.34.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
@@ -1,79 +0,0 @@
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
@@ -1,191 +0,0 @@
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/sha1"
"encoding/base64"
"errors"
"fmt"
"github.com/gin-gonic/gin"
"io"
"net/http"
"strconv"
"strings"
)
// TEST VALUES:
// KEY: passphrasewhichneedstobe32bytes! // TODO: Test with 256 bits
// INPUT: The ultimate question: of life, the universe, of everything!
// SHA-1 HASH: 0c6ca28f5607d86e5426b46795e0fa827f1627d6
// BASE64 HASH: string DGyij1YH2G5UJrRnleD6gn8WJ9Y=
// AES OUTPUT: []uint8{104, 215, 184, 35, 194, 120, 115, 112, 133, 21, 160, 158, 11, 136, 201, 160, 233, 3, 12, 29, 133, 211, 207, 98, 35, 199, 89, 31, 203, 230, 39, 210, 225, 99, 96, 101, 3, 5, 198, 82, 243, 179, 176, 217, 8, 4, 63, 22, 134, 184, 68, 102, 255, 183, 176, 172, 6, 176, 249, 28, 127, 120, 235, 135, 73, 235, 249, 118, 194, 4, 137, 27, 158, 190, 134, 68, 21, 105, 26, 134, 10, 224, 233, 115, 28, 0, 153, 209}
// HEX AES: "68 D7 B8 23 C2 78 73 70 85 15 A0 9E B 88 C9 A0 E9 3 C 1D 85 D3 CF 62 23 C7 59 1F CB E6 27 D2 E1 63 60 65 3 5 C6 52 F3 B3 B0 D9 8 4 3F 16 86 B8 44 66 FF B7 B0 AC 6 B0 F9 1C 7F 78 EB 87 49 EB F9 76 C2 4 89 1B 9E BE 86 44 15 69 1A 86 A E0 E9 73 1C 0 99 D1"
var rawHash = "DGyij1YH2G5UJrRnleD6gn8WJ9Y="
type request struct {
//UserID string `json:"id"`
Prompt string `json:"prompt"`
Sum string `json:"sum"`
}
var requests []request
// TODO: Test if 256 bit key works.
// TODO: Dynamically get key? Need to research best way to store private keys between two devices.
var key = []byte("passphrasewhichneedstobe32bytes!")
func encrypt() {
text := []byte("The ultimate question: of life, the universe, of everything!")
// generate a new aes cipher using our 32 byte long key
c, err := aes.NewCipher(key)
// if there are any errors, handle them
if err != nil {
fmt.Println(err)
}
// gcm or Galois/Counter Mode, is a mode of operation
// for symmetric key cryptographic block ciphers
// - https://en.wikipedia.org/wiki/Galois/Counter_Mode
gcm, err := cipher.NewGCM(c)
// if any error generating new GCM
// handle them
if err != nil {
fmt.Println(err)
}
// creates a new byte array the size of the nonce
// which must be passed to Seal
nonce := make([]byte, gcm.NonceSize())
// populates our nonce with a cryptographically secure
// random sequence
if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
fmt.Println(err)
}
// here we encrypt our text using the Seal function
// Seal encrypts and authenticates plaintext, authenticates the
// additional data and appends the result to dst, returning the updated
// slice. The nonce must be NonceSize() bytes long and unique for all
// time, for a given key.
fmt.Println(gcm.Seal(nonce, nonce, text, nil))
//// the WriteFile method returns an error if unsuccessful
//err = ioutil.WriteFile("myfile", gcm.Seal(nonce, nonce, text, nil), 0777)
//// handle this error
//if err != nil {
// // print it out
// fmt.Println(err)
//}
}
func convertHexToBytes(hexString *string) ([]uint8, error) {
// Handle nil pointer case
if hexString == nil {
return nil, errors.New("nil pointer provided for hex string")
}
// Split the hex string by spaces
hexBytes := strings.Fields(*hexString)
// Initialize an empty slice for uint8
data := make([]uint8, len(hexBytes))
// Iterate and convert each hex byte
for i, hexByte := range hexBytes {
// Convert each hex string to a uint8 value (handling errors)
value, err := strconv.ParseUint(hexByte, 16, 8)
if err != nil {
return nil, fmt.Errorf("error parsing hex byte '%s': %w", hexByte, err)
}
// Assign the converted value to the slice
data[i] = uint8(value)
}
// Return the slice of uint8 and any errors encountered
return data, nil
}
func decrypt(input *request) bool {
//ciphertext, err := ioutil.ReadFile("myfile")
ciphertext, err := convertHexToBytes(&input.Prompt)
// if our program was unable to read the file
// print out the reason why it can't
if err != nil {
fmt.Println(err)
}
c, err := aes.NewCipher(key)
if err != nil {
fmt.Println(err)
}
gcm, err := cipher.NewGCM(c)
if err != nil {
fmt.Println(err)
}
nonceSize := gcm.NonceSize()
if len(ciphertext) < nonceSize {
fmt.Println(err)
}
nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]
plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
if err != nil {
fmt.Println(err)
}
s := string(plaintext)
if validateHash(s) {
input.Prompt = s
return true
}
input.Prompt = "DATA CORRUPTED OR TAMPERED"
return false
}
// Validate there's no tampering with SHA-1 sum. The decrypted hash and the transmitted hash should be identical.
func validateHash(decrypted string) bool {
// Calculate the SHA256 sum of the decrypted request
hasher := sha1.New()
hasher.Write([]byte(decrypted))
decryptedHashString := base64.URLEncoding.EncodeToString(hasher.Sum(nil))
// TODO: Add error handling if hash doesn't match.
return decryptedHashString == rawHash
}
// User HTTP GET request has the prompt decrypted and verified with a SHA-1 checksum.
// If there's been no data corruption, re-construct user prompt for ollama
// TODO: Eventually, add additional logic that will allow for re-direction and contextual awareness (pre-processing)
func postRequest(c *gin.Context) {
var newInput request
//Call BindJSON to bind the received JSON to
if err := c.BindJSON(&newInput); err != nil {
return
}
if decrypt(&newInput) {
requests = append(requests, newInput)
c.IndentedJSON(http.StatusCreated, newInput) // TODO: Formulate prompt and transfer to AI layer to formulate new JSON response back
} else {
c.IndentedJSON(http.StatusBadRequest, gin.H{"message": "Failed checksum. Presumably data corrupted."})
}
}
func main() {
router := gin.Default()
router.POST("/prompts", postRequest)
err := router.Run("localhost:8080")
if err != nil {
return
}
}
+61 -85
View File
@@ -2,11 +2,10 @@ package main
import (
"encoding/base64"
//"encoding/json"
"encoding/hex"
"fmt"
"io"
"net/http"
"time"
"crypto/aes"
"crypto/cipher"
@@ -18,106 +17,82 @@ import (
"strings"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v5"
)
// TODO: Test with 256 bits
// TEST VALUES:
// KEY: passphrasewhichneedstobe32bytes!
// INPUT: The ultimate question: of life, the universe, of everything!
// SHA-1 HASH: 0c6ca28f5607d86e5426b46795e0fa827f1627d6
// BASE64 HASH: string DGyij1YH2G5UJrRnleD6gn8WJ9Y=
// AES OUTPUT: []uint8{104, 215, 184, 35, 194, 120, 115, 112, 133, 21, 160, 158, 11, 136, 201, 160, 233, 3, 12, 29, 133, 211, 207, 98, 35, 199, 89, 31, 203, 230, 39, 210, 225, 99, 96, 101, 3, 5, 198, 82, 243, 179, 176, 217, 8, 4, 63, 22, 134, 184, 68, 102, 255, 183, 176, 172, 6, 176, 249, 28, 127, 120, 235, 135, 73, 235, 249, 118, 194, 4, 137, 27, 158, 190, 134, 68, 21, 105, 26, 134, 10, 224, 233, 115, 28, 0, 153, 209}
// HEX AES: "68 D7 B8 23 C2 78 73 70 85 15 A0 9E B 88 C9 A0 E9 3 C 1D 85 D3 CF 62 23 C7 59 1F CB E6 27 D2 E1 63 60 65 3 5 C6 52 F3 B3 B0 D9 8 4 3F 16 86 B8 44 66 FF B7 B0 AC 6 B0 F9 1C 7F 78 EB 87 49 EB F9 76 C2 4 89 1B 9E BE 86 44 15 69 1A 86 A E0 E9 73 1C 0 99 D1"
var rawHash = "DGyij1YH2G5UJrRnleD6gn8WJ9Y="
type Request struct {
//UserID string `json:"id"`
Prompt string `json:"prompt"`
Sum string `json:"sum"`
type Communication struct {
Communication string `json:"communication"`
Hash string `json:"hash"`
}
var requests []Request
var requests []Communication
// TODO: Test if 256 bit key works.
// TODO: Dynamically get key? Need to research best way to store private keys between two devices.
var key = []byte("passphrasewhichneedstobe32bytes!")
func verifyToken(tokenString string) error {
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return key, nil
})
if err != nil {
return err
func hash(text string) string {
hasher := sha1.New()
hasher.Write([]byte(text))
return base64.URLEncoding.EncodeToString(hasher.Sum(nil))
}
if !token.Valid {
return fmt.Errorf("invalid token")
func encrypt(gc *gin.Context) {
var newCommunication Communication
if err := gc.BindJSON(&newCommunication); err != nil {
gc.IndentedJSON(http.StatusBadRequest, gin.H{"message": err})
return
}
return nil
}
text := []byte(newCommunication.Communication)
func createToken(username string) (string, error) {
token := jwt.NewWithClaims(jwt.SigningMethodHS256,
jwt.MapClaims{
"username": username,
"exp": time.Now().Add(time.Hour * 24).Unix(),
})
tokenString, err := token.SignedString(key)
if err != nil {
return "", err
}
return tokenString, nil
}
func encrypt() {
text := []byte("The ultimate question: of life, the universe, of everything!")
// generate a new aes cipher using our 32 byte long key
c, err := aes.NewCipher(key)
// if there are any errors, handle them
if err != nil {
fmt.Println(err)
gc.IndentedJSON(http.StatusBadRequest, gin.H{"message": err})
}
// gcm or Galois/Counter Mode, is a mode of operation
// for symmetric key cryptographic block ciphers
// - https://en.wikipedia.org/wiki/Galois/Counter_Mode
gcm, err := cipher.NewGCM(c)
// if any error generating new GCM
// handle them
if err != nil {
fmt.Println(err)
gc.IndentedJSON(http.StatusBadRequest, gin.H{"message": err})
}
// creates a new byte array the size of the nonce
// which must be passed to Seal
nonce := make([]byte, gcm.NonceSize())
// populates our nonce with a cryptographically secure
// random sequence
if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
fmt.Println(err)
gc.IndentedJSON(http.StatusBadRequest, gin.H{"message": err})
}
// here we encrypt our text using the Seal function
// Seal encrypts and authenticates plaintext, authenticates the
// additional data and appends the result to dst, returning the updated
// slice. The nonce must be NonceSize() bytes long and unique for all
// time, for a given key.
fmt.Println(gcm.Seal(nonce, nonce, text, nil))
var b []byte = gcm.Seal(nonce, nonce, text, nil)
hex, err := convertBytesToHex(b)
if(err != nil) {
fmt.Println(err)
}
var test string = "{data: " + hex + ", hash: " + hash(string(text)) + "}"
//// the WriteFile method returns an error if unsuccessful
//err = ioutil.WriteFile("myfile", gcm.Seal(nonce, nonce, text, nil), 0777)
//// handle this error
//if err != nil {
// // print it out
// fmt.Println(err)
//}
gc.IndentedJSON(http.StatusCreated, gin.H{"message": test})
}
func convertBytesToHex(b []byte) (string, error) {
// Handle nil pointer case
if b == nil {
return "", errors.New("nil pointer provided for hex string")
}
// Split the hex string by spaces
var h string = hex.EncodeToString(b)
var builder strings.Builder
for i := 0; i < len(h); i += 2 {
end := i + 2
if end > len(h) {
end = len(h)
}
chunk := h[i:end]
builder.WriteString(chunk)
if end < len(h) {
builder.WriteString(" ")
}
}
// Return the slice of uint8 and any errors encountered
return builder.String(), nil
}
func convertHexToBytes(hexString *string) ([]uint8, error) {
@@ -148,9 +123,9 @@ func convertHexToBytes(hexString *string) ([]uint8, error) {
return data, nil
}
func decrypt(input *Request) bool {
func decrypt(input *Communication) bool {
//ciphertext, err := ioutil.ReadFile("myfile")
ciphertext, err := convertHexToBytes(&input.Prompt)
ciphertext, err := convertHexToBytes(&input.Communication)
// if our program was unable to read the file
// print out the reason why it can't
@@ -179,30 +154,30 @@ func decrypt(input *Request) bool {
fmt.Println(err)
}
s := string(plaintext)
if validateHash(s) {
input.Prompt = s
if validateHash(s, input.Hash) {
input.Communication = s
return true
}
input.Prompt = "DATA CORRUPTED OR TAMPERED"
input.Communication = "DATA CORRUPTED OR TAMPERED"
return false
}
// Validate there's no tampering with SHA-1 sum. The decrypted hash and the transmitted hash should be identical.
func validateHash(decrypted string) bool {
func validateHash(decrypted string, hash string) bool {
// Calculate the SHA256 sum of the decrypted request
hasher := sha1.New()
hasher.Write([]byte(decrypted))
decryptedHashString := base64.URLEncoding.EncodeToString(hasher.Sum(nil))
// TODO: Add error handling if hash doesn't match.
return decryptedHashString == rawHash
return decryptedHashString == hash
}
// User HTTP GET request has the prompt decrypted and verified with a SHA-1 checksum.
// If there's been no data corruption, re-construct user prompt for ollama
// TODO: Eventually, add additional logic that will allow for re-direction and contextual awareness (pre-processing)
func promptRequest(c *gin.Context) {
var newInput Request
func request(c *gin.Context) {
var newInput Communication
//Call BindJSON to bind the received JSON to
if err := c.BindJSON(&newInput); err != nil {
@@ -220,7 +195,8 @@ func promptRequest(c *gin.Context) {
func main() {
router := gin.Default()
router.POST("/prompt", promptRequest)
router.POST("/request", request)
router.POST("/encrypt", encrypt)
err := router.Run("0.0.0.0:8000")
if err != nil {
+9
View File
@@ -0,0 +1,9 @@
#!/bin/zsh
# Force delete the old container and re-initialize the container.
docker rm -f security-layer
# Build the Docker image.
docker build --tag security-layer:latest .
# Create a Docker container from the image and connect host port 8000 to container port 8000.
docker run --name security-layer -d -p 8000:8000 security-layer:latest
-14
View File
@@ -1,14 +0,0 @@
# Build the Docker image.
docker build --tag security-layer:latest .
# Create a Docker container from the image and connect host port 8000 to container port 8000.
docker run --name security-layer -d -p 8000:8000 security-layer:latest
# Send a JSON request to the security layer within the Docker container.
curl http://localhost:8000/prompt -d '{
"prompt": "68 D7 B8 23 C2 78 73 70 85 15 A0 9E B 88 C9 A0 E9 3 C 1D 85 D3 CF 62 23 C7 59 1F CB E6 27 D2 E1 63 60 65 3 5 C6 52 F3 B3 B0 D9 8 4 3F 16 86 B8 44 66 FF B7 B0 AC 6 B0 F9 1C 7F 78 EB 87 49 EB F9 76 C2 4 89 1B 9E BE 86 44 15 69 1A 86 A E0 E9 73 1C 0 99 D1",
"sum": "DGyij1YH2G5UJrRnleD6gn8WJ9Y="
}'
# Delete the container so the next build and container utilize code changes.
docker rm -f security-layer