Can anyone suggest a way of modifying the below code so that I can use the constant pubkey I've included? I'm having trouble changing it and getting it to work with a constant.
package main
import (
"golang.org/x/crypto/nacl/sign"
"crypto/rand"
"log"
"encoding/base64"
"encoding/json"
"io/ioutil"
"net/http"
"github.com/gin-gonic/gin"
// "os"
// "strings"
)
type authtoken struct {
Cookie string `json:"cookie"`
}
type user struct {
Username string `json:"username"`
Password string `json:"password"`
}
var users []user
var pubkey *[64]byte
var privkey *[32]byte
const pubkeyStr = "123eRhvE0bqx81t3G9o79LOkkR4CK9Cyhvt8-QJ-s1H2A6uSwukUI0CYUlc3WbmIAa3VTo4Jm9RF5F0Af4DzmQ"
func login(c *gin.Context) {
var tryUser user
if err := c.BindJSON(&tryUser); err != nil {
return
}
for _, user := range users {
if user == tryUser {
// Convert the constant public key string to bytes
pubkey := []byte(pubkeyStr)
//token = authtoken{Username: user.Username}
//out := make([]byte, 300)
out := make([]byte,0)
log.Println("username", []byte(user.Username), "pubkey",pubkey)
signedtokenout := sign.Sign(out, []byte(user.Username), pubkey)
log.Println("signed token:",signedtokenout)
signedtokenstr := base64.RawURLEncoding.EncodeToString(signedtokenout[:])
c.IndentedJSON(http.StatusOK, gin.H{"cookie":signedtokenstr})
c.IndentedJSON(http.StatusOK, gin.H{"my pubkey is":base64.RawURLEncoding.EncodeToString(pubkey[:])})
return
}
}
c.IndentedJSON(http.StatusForbidden, "wrong")
}
func home(c *gin.Context) {
c.IndentedJSON(http.StatusOK, gin.H{"my pubkey is":base64.RawURLEncoding.EncodeToString(pubkey[:])})
}
func main() {
bytes, err := ioutil.ReadFile("users.json")
if err != nil {
log.Println("Unable to load users file!")
return
}
err = json.Unmarshal(bytes, &users)
if err != nil {
log.Println("Unable to unmarshal users file!")
return
}
privkey,pubkey, _ = sign.GenerateKey(rand.Reader)
// if err != nil {
// log.Fatal("could not GenerateKey", err)
// }
log.Printf("\n\nThe public key is:%v\n\nThe private key is:%v\n", pubkey,privkey)
pubstr := base64.RawURLEncoding.EncodeToString(pubkey[:])
log.Println("\nThe encoded public key:", pubstr)
router := gin.Default()
router.POST("/login", login)
router.GET("/", home)
router.Run("0.0.0.0:80")
}
I want to be able to replace "var pubkey *[64]byte" with the constant pubkey in the entire code. At the moment, when running it, it generates a random key in the main function which is currently expected, but not what I need. I have an idea that the 'type' is incorrect but I can't work out how to modify it.
Any assistance would be greatly appreciated.
UPDATE - I've made progress thanks to @larsks by implementing your code.
I get the use of a constant key however what I have now realised is that the cookie created during the login process is a signed token using the base64 encoded string, therefore the string I am setting as the constant, is not the actual string I want to use.
My goal is to able able to reverse eng the cookie using the username, knowing that it's been signed with the key.
Essentially, if I have a cookie in the form P5Q-c_EQWhkUbagDC3klwsv0SQ6JdK9zDZLws3PzWjjdjcqiHlJMWLsxKDraTgU6za_fOXuaEOa5i2NhEmY0DnJvY2t5 , where the username is rocky, I want to modify the cookie and use the username 'admin' knowing the encoded pubkey is 123eRhvE0bqx81t3G9o79LOkkR4CK9Cyhvt8-QJ-s1H2A6uSwukUI0CYUlc3WbmIAa3VTo4Jm9RF5F0Af4DzmQ
That said, there might be an easier way to do this so I am open to suggestions.
I have tried this as a complete left of arc trial but I'm noticing the modified cookie has a different length to the original.
package main
import (
"encoding/base64"
"fmt"
"log"
)
type User struct {
Username string
}
func main() {
// Your original public key value
pubkeyStr := "937eRhvE0bqx81t3G9o79LOkkR4CK9Cyhvt8-QJ-s1H2A6uSwukUI0CYUlc3WbmIAa3VTo4Jm9RF5F0Af4DzmQ"
pubkey, err := base64.RawURLEncoding.DecodeString(pubkeyStr)
if err != nil {
log.Fatal("Error decoding public key:", err)
}
// Existing cookie value
existingCookie := "P5Q-c_EQWhkUbagDC3klwsv0SQ6JdK9zDZLws3PzWjjdjcqiHlJMWLsxKDraTgU6za_fOXuaEOa5i2NhEmY0DnJvY2t5"
Username := "admin"
// Modify the existing cookie to change the username
modifiedCookie, err := modifyCookie(existingCookie, Username, pubkey)
if err != nil {
log.Fatal("Error modifying cookie:", err)
}
fmt.Println("Encoded public key used is:", pubkeyStr)
fmt.Println("\nDecoded public key is :", pubkey)
fmt.Println("\nCookie to be modified is:", existingCookie)
fmt.Println("\nModified Cookie is :", modifiedCookie)
// fmt.Println("Or is this the modified cookie:", modifiedCookieStr)
fmt.Println("\nEncoded public key should be 937eRhvE0bqx81t3G9o79LOkkR4CK9Cyhvt8-QJ-s1H2A6uSwukUI0CYUlc3WbmIAa3VTo4Jm9RF5F0Af4DzmQ")
fmt.Println("\nRencoded public key, to ensure integirty, is:", base64.RawURLEncoding.EncodeToString(pubkey))
}
// Dummy function to modify the existing cookie
func modifyCookie(existingCookie string, Username string, pubkey []byte) (string, error) {
// Decode the existing cookie from base64
decodedCookie, err := base64.RawURLEncoding.DecodeString(existingCookie)
if err != nil {
return "", err
}
// Verify the signature of the existing cookie
if err := verifySignature(decodedCookie, pubkey); err != nil {
return "", err
}
// Modify the username
userPart := decodedCookie[:len(decodedCookie)-len(pubkey)]
modifiedCookie := append(userPart, []byte(Username)...)
modifiedCookie = append(modifiedCookie, pubkey...)
// Encode the modified cookie back to base64
modifiedCookieStr := base64.RawURLEncoding.EncodeToString(modifiedCookie)
return modifiedCookieStr, nil
}
// Dummy function to verify the signature of the existing cookie
func verifySignature(cookie []byte, pubkey []byte) error {
// Replace this with your actual logic to verify the cookie signature
// For security, you should use a proper cryptographic library
// This is just a dummy example
return nil
}
I don't think you can do that exactly, but you could initialize a global variable in
init:With that, you can reference
pubkeyanywhere else in your package and it will have the expected value.