Skip to content

Commit

Permalink
feat(crypto): add nonce scrambling into crypto functions
Browse files Browse the repository at this point in the history
  • Loading branch information
Gusted committed Jul 12, 2021
1 parent 972e88a commit 63e2b29
Show file tree
Hide file tree
Showing 12 changed files with 92 additions and 42 deletions.
2 changes: 1 addition & 1 deletion handlers/api/callback.go
Expand Up @@ -39,7 +39,7 @@ func CallbackGet(c *fiber.Ctx) error {
if redirectCode != "codeberg" && redirectCode != "gitlab" {
service = "github"
// Decode the string so we get our actual information back.
code, err := utils.DecodePreparedText(redirectCode, utils.AEAD_OAUTH)
code, err := utils.DecodePreparedText(redirectCode, utils.AEAD_OAUTH, config.ScrambleConfig)
if err != nil {
log.Println("Error: Couldn't decode our prepared text.")
return c.Next()
Expand Down
3 changes: 2 additions & 1 deletion handlers/oauthProvider/access_token.go
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/gofiber/fiber/v2"

"userstyles.world/models"
"userstyles.world/modules/config"
"userstyles.world/utils"
)

Expand All @@ -34,7 +35,7 @@ func TokenPost(c *fiber.Ctx) error {
return errorMessage(c, 400, "Incorrect client_secret specified")
}

unsealedText, err := utils.DecodePreparedText(tCode, utils.AEAD_OAUTHP)
unsealedText, err := utils.DecodePreparedText(tCode, utils.AEAD_OAUTHP, config.ScrambleConfig)
if err != nil {
log.Println("Error: Couldn't unseal JWT Token:", err.Error())
return errorMessage(c, 500, "JWT Token error, please notify the admins.")
Expand Down
7 changes: 4 additions & 3 deletions handlers/oauthProvider/authorize.go
Expand Up @@ -11,6 +11,7 @@ import (

jwtware "userstyles.world/handlers/jwt"
"userstyles.world/models"
"userstyles.world/modules/config"
"userstyles.world/utils"
)

Expand All @@ -34,7 +35,7 @@ func redirectFunction(c *fiber.Ctx, state, redirectURI string) error {
return errorMessage(c, 500, "JWT Token error, please notify the admins.")
}

returnCode := "?code=" + utils.PrepareText(jwt, utils.AEAD_OAUTHP)
returnCode := "?code=" + utils.PrepareText(jwt, utils.AEAD_OAUTHP, config.ScrambleConfig)
if state != "" {
returnCode += "&state=" + state
}
Expand Down Expand Up @@ -97,7 +98,7 @@ func AuthorizeGet(c *fiber.Ctx) error {
arguments := fiber.Map{
"User": u,
"OAuth": OAuth,
"SecureToken": utils.PrepareText(jwt, utils.AEAD_OAUTHP),
"SecureToken": utils.PrepareText(jwt, utils.AEAD_OAUTHP, config.ScrambleConfig),
}
for _, v := range OAuth.Scopes {
arguments["Scope_"+v] = true
Expand All @@ -115,7 +116,7 @@ func AuthPost(c *fiber.Ctx) error {
return errorMessage(c, 400, "Incorrect oauthID specified")
}

unsealedText, err := utils.DecodePreparedText(secureToken, utils.AEAD_OAUTHP)
unsealedText, err := utils.DecodePreparedText(secureToken, utils.AEAD_OAUTHP, config.ScrambleConfig)
if err != nil {
log.Println("Error: Couldn't unseal JWT Token:", err.Error())
return errorMessage(c, 500, "JWT Token error, please notify the admins.")
Expand Down
9 changes: 5 additions & 4 deletions handlers/oauthProvider/authorize_style.go
Expand Up @@ -11,6 +11,7 @@ import (

jwtware "userstyles.world/handlers/jwt"
"userstyles.world/models"
"userstyles.world/modules/config"
"userstyles.world/utils"
)

Expand Down Expand Up @@ -45,7 +46,7 @@ func OAuthStyleGet(c *fiber.Ctx) error {
log.Println("Error: Couldn't make a JWT Token due to:", err.Error())
return errorMessage(c, 500, "Couldn't make JWT Token, please notify the admins.")
}
secureToken := utils.PrepareText(jwt, utils.AEAD_OAUTHP)
secureToken := utils.PrepareText(jwt, utils.AEAD_OAUTHP, config.ScrambleConfig)

styles, err := models.GetStylesByUser(u.Username)
if err != nil {
Expand Down Expand Up @@ -81,7 +82,7 @@ func OAuthStylePost(c *fiber.Ctx) error {
return errorMessage(c, 400, "Incorrect oauthID specified")
}

unsealedText, err := utils.DecodePreparedText(secureToken, utils.AEAD_OAUTHP)
unsealedText, err := utils.DecodePreparedText(secureToken, utils.AEAD_OAUTHP, config.ScrambleConfig)
if err != nil {
log.Println("Error: Couldn't unseal JWT Token:", err.Error())
return errorMessage(c, 500, "JWT Token error, please notify the admins.")
Expand Down Expand Up @@ -128,7 +129,7 @@ func OAuthStylePost(c *fiber.Ctx) error {
return errorMessage(c, 500, "JWT Token error, please notify the admins.")
}

returnCode := "?code=" + utils.PrepareText(jwt, utils.AEAD_OAUTHP)
returnCode := "?code=" + utils.PrepareText(jwt, utils.AEAD_OAUTHP, config.ScrambleConfig)
returnCode += "&style_id=" + styleID
if state != "" {
returnCode += "&state=" + state
Expand All @@ -146,7 +147,7 @@ func OAuthStyleNewPost(c *fiber.Ctx) error {
return errorMessage(c, 400, "Incorrect oauthID specified")
}

unsealedText, err := utils.DecodePreparedText(secureToken, utils.AEAD_OAUTHP)
unsealedText, err := utils.DecodePreparedText(secureToken, utils.AEAD_OAUTHP, config.ScrambleConfig)
if err != nil {
log.Println("Error: Couldn't unseal JWT Token:", err.Error())
return errorMessage(c, 500, "JWT Token error, please notify the admins.")
Expand Down
5 changes: 3 additions & 2 deletions handlers/style/add.go
Expand Up @@ -16,6 +16,7 @@ import (

jwtware "userstyles.world/handlers/jwt"
"userstyles.world/models"
"userstyles.world/modules/config"
"userstyles.world/modules/database"
"userstyles.world/modules/images"
"userstyles.world/search"
Expand Down Expand Up @@ -146,7 +147,7 @@ func handleAPIStyle(c *fiber.Ctx, secureToken, oauthID, styleID string, style *m
})
}

unsealedText, err := utils.DecodePreparedText(secureToken, utils.AEAD_OAUTHP)
unsealedText, err := utils.DecodePreparedText(secureToken, utils.AEAD_OAUTHP, config.ScrambleConfig)
if err != nil {
log.Println("Error: Couldn't unseal JWT Token:", err.Error())
return c.Status(500).
Expand Down Expand Up @@ -205,7 +206,7 @@ func handleAPIStyle(c *fiber.Ctx, secureToken, oauthID, styleID string, style *m
})
}

returnCode := "?code=" + utils.PrepareText(jwt, utils.AEAD_OAUTHP)
returnCode := "?code=" + utils.PrepareText(jwt, utils.AEAD_OAUTHP, config.ScrambleConfig)
returnCode += "&style_id=" + styleID
if state != "" {
returnCode += "&state=" + state
Expand Down
3 changes: 2 additions & 1 deletion handlers/user/register.go
Expand Up @@ -10,6 +10,7 @@ import (

"userstyles.world/handlers/jwt"
"userstyles.world/models"
"userstyles.world/modules/config"
"userstyles.world/utils"
)

Expand Down Expand Up @@ -57,7 +58,7 @@ func RegisterPost(c *fiber.Ctx) error {
})
}

link := c.BaseURL() + "/verify/" + utils.PrepareText(token, utils.AEAD_CRYPTO)
link := c.BaseURL() + "/verify/" + utils.PrepareText(token, utils.AEAD_CRYPTO, config.ScrambleConfig)

partPlain := utils.NewPart().
SetBody("Verify your UserStyles.world account by clicking the link below.\n" +
Expand Down
7 changes: 4 additions & 3 deletions handlers/user/reset.go
Expand Up @@ -10,6 +10,7 @@ import (

jwtware "userstyles.world/handlers/jwt"
"userstyles.world/models"
"userstyles.world/modules/config"
"userstyles.world/modules/database"
"userstyles.world/utils"
)
Expand Down Expand Up @@ -39,7 +40,7 @@ func ResetGet(c *fiber.Ctx) error {
return renderError
}

_, err := utils.DecodePreparedText(key, utils.AEAD_CRYPTO)
_, err := utils.DecodePreparedText(key, utils.AEAD_CRYPTO, config.ScrambleConfig)
if err != nil {
log.Printf("Couldn't decode key due to: %s\n", err.Error())
return renderError
Expand Down Expand Up @@ -71,7 +72,7 @@ func ResetPost(c *fiber.Ctx) error {
return renderError
}

unSealedText, err := utils.DecodePreparedText(key, utils.AEAD_CRYPTO)
unSealedText, err := utils.DecodePreparedText(key, utils.AEAD_CRYPTO, config.ScrambleConfig)
if err != nil {
log.Printf("Couldn't decode key due to: %s\n", err.Error())
return renderError
Expand Down Expand Up @@ -154,7 +155,7 @@ func RecoverPost(c *fiber.Ctx) error {
})
}

link := c.BaseURL() + "/reset/" + utils.PrepareText(jwt, utils.AEAD_CRYPTO)
link := c.BaseURL() + "/reset/" + utils.PrepareText(jwt, utils.AEAD_CRYPTO, config.ScrambleConfig)

partPlain := utils.NewPart().
SetBody("We have received a request to reset the password for your UserStyles.world account.\n\n" +
Expand Down
3 changes: 2 additions & 1 deletion handlers/user/verify.go
Expand Up @@ -8,6 +8,7 @@ import (

jwtware "userstyles.world/handlers/jwt"
"userstyles.world/models"
"userstyles.world/modules/config"
"userstyles.world/modules/database"
"userstyles.world/utils"
)
Expand All @@ -28,7 +29,7 @@ func VerifyGet(c *fiber.Ctx) error {
})
}

unSealedText, err := utils.DecodePreparedText(base64Key, utils.AEAD_CRYPTO)
unSealedText, err := utils.DecodePreparedText(base64Key, utils.AEAD_CRYPTO, config.ScrambleConfig)
if err != nil {
log.Printf("Couldn't decode key due to: %s\n", err.Error())
return c.Render("err", fiber.Map{
Expand Down
23 changes: 23 additions & 0 deletions modules/config/config.go
Expand Up @@ -3,8 +3,14 @@ package config
import (
"fmt"
"os"
"strconv"
)

type NonceScramblingConfig struct {
StepSize int
BytesPerInsert int
}

var (
PORT = getEnv("PORT", ":3000")
DB = getEnv("DB", "dev.db")
Expand Down Expand Up @@ -32,8 +38,25 @@ var (

// Production is used for various "feature flags".
Production = DB != "dev.db"

ScrambleConfig = &NonceScramblingConfig{
StepSize: getEnvInt("NONCE_SCRAMBLE_STEP", 2),
BytesPerInsert: getEnvInt("NONCE_SCRAMBLE_BYTES_PER_INSERT", 3),
}
)

func getEnvInt(name string, defaultValue int) int {
envValue := getEnv(name, "__NOT_FOUND!")
if envValue == "__NOT_FOUND!" {
return defaultValue
}
if envInt, err := strconv.Atoi(envValue); err != nil {
return defaultValue
} else {
return envInt
}
}

func getEnv(name, fallback string) string {
if val, set := os.LookupEnv(name); set {
return val
Expand Down
20 changes: 11 additions & 9 deletions utils/chacha20poly1305.go
Expand Up @@ -42,10 +42,11 @@ func InitalizeCrypto() {
AEAD_OAUTHP = aead
}

func SealText(text string, aead cipher.AEAD) []byte {
func SealText(text string, aead cipher.AEAD, nonceScrambling *config.NonceScramblingConfig) []byte {
nonce := RandStringBytesMaskImprSrcUnsafe(aead.NonceSize())

return aead.Seal(nonce, nonce, UnsafeBytes(text), nil)
dest := aead.Seal(nil, nonce, UnsafeBytes(text), nil)
return ScrambleNonce(nonce, dest, nonceScrambling.StepSize, nonceScrambling.BytesPerInsert)
}

// ScrambleNonce into string takes a nonce and a text
Expand Down Expand Up @@ -171,15 +172,16 @@ mainLoop:
return nonce, text
}

func OpenText(encryptedMsg string, aead cipher.AEAD) ([]byte, error) {
func OpenText(encryptedMsg string, aead cipher.AEAD, nonceScrambling *config.NonceScramblingConfig) ([]byte, error) {
if len(encryptedMsg) < aead.NonceSize() {
return nil, errors.ErrMessageSmall
}

// Split nonce and ciphertext.
nonce, ciphertext := encryptedMsg[:aead.NonceSize()], encryptedMsg[aead.NonceSize():]
nonce, ciphertext := DescrambleNonce([]byte(encryptedMsg), aead.NonceSize(), nonceScrambling.StepSize, nonceScrambling.BytesPerInsert)

// Decrypt the message and check it wasn't tampered with.
return aead.Open(nil, UnsafeBytes(nonce), UnsafeBytes(ciphertext), nil)
return aead.Open(nil, nonce, ciphertext, nil)
}

func VerifyJwtKeyFunction(t *jwt.Token) (interface{}, error) {
Expand All @@ -196,23 +198,23 @@ func OAuthPJwtKeyFunction(t *jwt.Token) (interface{}, error) {
return OAuthPSigningKey, nil
}

func PrepareText(text string, aead cipher.AEAD) string {
func PrepareText(text string, aead cipher.AEAD, nonceScrambling *config.NonceScramblingConfig) string {
// We have to prepare the encrypted text for transport
// Seal Text -> Base64(URL Version)
sealedText := SealText(text, aead)
sealedText := SealText(text, aead, nonceScrambling)

return EncodeToString(sealedText)
}

func DecodePreparedText(preparedText string, aead cipher.AEAD) (string, error) {
func DecodePreparedText(preparedText string, aead cipher.AEAD, nonceScrambling *config.NonceScramblingConfig) (string, error) {
// Now we have to reverse the process.
// Decode Base64(URL version) -> Unseal Text
enryptedText, err := DecodeString(preparedText)
if err != nil {
return "", err
}

decryptedText, err := OpenText(UnsafeString(enryptedText), aead)
decryptedText, err := OpenText(UnsafeString(enryptedText), aead, nonceScrambling)
if err != nil {
return "", err
}
Expand Down

0 comments on commit 63e2b29

Please sign in to comment.