Implemented stronger string obfuscation

pull/54/head
Pagran 5 years ago
parent 796f2b833e
commit 10f3dba709

@ -4,6 +4,7 @@ import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/binary"
"fmt"
mathrand "math/rand"
"strings"
@ -38,6 +39,15 @@ func genRandBytes(size int) []byte {
return buffer
}
func genRandUInt32() uint32 {
bytes := genRandBytes(4)
return binary.LittleEndian.Uint32(bytes)
}
func genRandUInt32Max(max uint32) uint32 {
return genRandUInt32() % max
}
// encAES encrypt data with key in AES GCM mode.
func encAES(data, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)

@ -282,12 +282,142 @@ var funcStmt = &ast.FuncDecl{
}},
}
const tempKeyType = "uint32"
const tempKeyPrefix = "___garble_tmp"
const arrVarName = tempKeyPrefix + "_arr"
const maxTempKeyCount = 5
func makeTempKeyName(i int) string {
return tempKeyPrefix + strconv.Itoa(i)
}
func makeEmbedFuncTemplateFunc(argCount uint32) *ast.FuncLit {
keyNames := make([]*ast.Ident, argCount)
for i := range keyNames {
keyNames[i] = &ast.Ident{Name: makeTempKeyName(i)}
}
return &ast.FuncLit{
Type: &ast.FuncType{
Params: &ast.FieldList{
List: []*ast.Field{{
Names: keyNames,
Type: &ast.Ident{Name: tempKeyType},
}}},
Results: &ast.FieldList{List: []*ast.Field{{
Type: &ast.Ident{Name: "string"},
}}},
},
}
}
func generateTempKeys(keyCount uint32) ([]uint32, []ast.Expr) {
keys := make([]uint32, keyCount)
args := make([]ast.Expr, keyCount)
for i := range keys {
key := genRandUInt32()
keys[i] = key
args[i] = &ast.BasicLit{Kind: token.INT, Value: fmt.Sprint(key)}
}
return keys, args
}
func generateRandomCipherBlock(ciphertext []byte, keys []uint32) *ast.BlockStmt {
keyCount := uint32(len(keys))
stmtCount := int(keyCount + genRandUInt32Max(3*keyCount))
stmt := &ast.BlockStmt{List: make([]ast.Stmt, stmtCount)}
l := len(ciphertext)
for i := 0; i < stmtCount; i++ {
keyIdx := i % len(keys)
key := keys[keyIdx]
valShift := genRandUInt32Max(16)
posShift := 16 + genRandUInt32Max(16)
val := byte(key >> valShift)
pos := int(key>>posShift) % l
ciphertext[pos] ^= val
stmt.List[stmtCount-i-1] = &ast.AssignStmt{
Lhs: []ast.Expr{
&ast.IndexExpr{
X: &ast.Ident{Name: arrVarName},
Index: &ast.CallExpr{
Fun: &ast.Ident{Name: "int"},
Args: []ast.Expr{
&ast.BinaryExpr{
X: &ast.BinaryExpr{
X: &ast.Ident{Name: makeTempKeyName(keyIdx)},
Op: token.SHR,
Y: &ast.BasicLit{
Kind: token.INT,
Value: fmt.Sprint(posShift),
},
},
Op: token.REM,
Y: &ast.BasicLit{
Kind: token.INT,
Value: fmt.Sprint(l),
},
},
}},
},
},
Tok: token.XOR_ASSIGN,
Rhs: []ast.Expr{
&ast.CallExpr{
Fun: &ast.Ident{Name: "byte"},
Args: []ast.Expr{
&ast.BinaryExpr{
X: &ast.Ident{Name: makeTempKeyName(keyIdx)},
Op: token.SHR,
Y: &ast.BasicLit{
Kind: token.INT,
Value: fmt.Sprint(valShift),
},
},
},
},
},
}
}
return stmt
}
func ciphertextStmt(ciphertext []byte) *ast.CallExpr {
ciphertextLit := dataToByteSlice(ciphertext)
keyCount := 1 + genRandUInt32Max(maxTempKeyCount)
embedFunc := makeEmbedFuncTemplateFunc(keyCount)
keys, args := generateTempKeys(keyCount)
decryptBlock := generateRandomCipherBlock(ciphertext, keys)
embedFunc.Body = &ast.BlockStmt{List: []ast.Stmt{
&ast.AssignStmt{
Lhs: []ast.Expr{
&ast.Ident{Name: arrVarName},
},
Tok: token.DEFINE,
Rhs: []ast.Expr{dataToByteSlice(ciphertext)},
},
decryptBlock,
&ast.ReturnStmt{Results: []ast.Expr{
&ast.CallExpr{
Fun: &ast.Ident{Name: "garbleDecrypt"},
Args: []ast.Expr{&ast.Ident{Name: arrVarName}},
},
}},
}}
return &ast.CallExpr{
Fun: &ast.Ident{Name: "garbleDecrypt"},
Args: []ast.Expr{ciphertextLit},
Fun: embedFunc,
Args: args,
}
}

Loading…
Cancel
Save