Documentation
¶
Overview ¶
Package core is the cchef engine: the pieces an operation is written against and a recipe is run with.
A Dish carries data between operations along with the type it is currently being treated as, so an operation that wants bytes and one that wants text can sit next to each other in the same recipe. An Operation declares what it is called and what arguments it takes (OpMeta and ArgDef) and transforms one Dish into the next. A Recipe is an ordered list of operations with their arguments; running it feeds each result into the next step.
Operations are looked up by name in a Registry. The package-level Default registry is the one Register adds to and the one the cchef command uses; importing the ops package for its side effects fills it with every operation cchef implements.
import (
"github.com/roberson-io/cchef/core"
_ "github.com/roberson-io/cchef/ops" // register the operations
)
r, err := core.ParseRecipeConfig(`[{"op":"To Base64"}]`)
if err != nil {
return err
}
out, err := r.Execute(core.NewDish([]byte("hello"), core.TypeByteArray))
if err != nil {
return err
}
fmt.Println(out.String()) // aGVsbG8=
Arguments may be given in full or left out. DefaultArgs fills in what an operation declares, and CoerceArgs converts and checks what a caller supplies against those declarations — the same validation the command-line interface applies, so a recipe behaves the same whichever way it is run.
Registering an operation of your own is the same work cchef's own operations do: implement Operation and hand it to Register. It is then available by name to any recipe, alongside the built-in ones.
Index ¶
- Constants
- Variables
- func BuildURL(base string, r Recipe, input []byte) string
- func CoerceArg(def ArgDef, value any) (any, error)
- func CoerceArgs(defs []ArgDef, args []any) ([]any, error)
- func DecodeURIFragment(s string) (string, error)
- func DefaultArgs(defs []ArgDef) []any
- func EncodeURIFragment(s string) string
- func GeneratePrettyRecipe(r Recipe, newline bool) string
- func Kebab(name string) string
- func MarshalRecipeJSON(r Recipe) (string, error)
- func Register(op Operation)
- type ArgDef
- type ArgType
- type Dish
- type DishType
- type FlowOperation
- type FlowState
- type NamedFile
- type OpMeta
- type Operation
- type Recipe
- type RecipeOp
- type Registry
- type ToggleString
Constants ¶
const DefaultBaseURL = "https://gchq.github.io/CyberChef/"
DefaultBaseURL is the public CyberChef instance share links point at unless the caller names another.
Variables ¶
var Default = NewRegistry()
Default is the process-wide registry. Operation packages register into it from their init() functions.
Functions ¶
func BuildURL ¶
BuildURL constructs a CyberChef share URL for the given recipe and input, pointing at the instance named by base. The recipe is rendered in Chef format; the input is standard base64 (no padding), both then fragment-encoded.
func CoerceArg ¶
CoerceArg validates and normalises a single argument value against its definition, returning the canonical Go type for that ArgType.
func CoerceArgs ¶
CoerceArgs coerces a full argument list against an operation's definitions, filling in defaults for any trailing arguments the caller omitted.
func DecodeURIFragment ¶ added in v1.0.1
DecodeURIFragment resolves the percent-escapes EncodeURIFragment writes, returning the bytes as they were. It is that function's inverse.
A "+" is left alone rather than read as a space. CyberChef substitutes it, but EncodeURIFragment writes a space as %20 and a plus as %2B, so a literal "+" in a fragment can only have come from the data — most often from base64, where reading it as a space would lose a byte.
func DefaultArgs ¶
DefaultArgs returns the default value for each argument definition. For ArgOption the default is the choice at DefaultIndex (0 unless set).
func EncodeURIFragment ¶
EncodeURIFragment percent-encodes a string for use in a URL fragment, keeping the human-readable safe set literal. Ported from Utils.encodeURIFragment.
func GeneratePrettyRecipe ¶
GeneratePrettyRecipe serialises a recipe to CyberChef's compact "Chef" text format, e.g. To_Base64('A-Za-z0-9+/='). Ported from Utils.generatePrettyRecipe.
func Kebab ¶
Kebab converts an operation name to a CLI subcommand name: lower-cased, with accented Latin letters folded to ASCII, spaces and separators collapsed to single hyphens, and other punctuation dropped (e.g. "To Base64" -> "to-base64", "Find / Replace" -> "find-replace", "Vigenère Encode" -> "vigenere-encode", "XPRESS LZ77+Huffman Decompress" -> "xpress-lz77-huffman-decompress").
func MarshalRecipeJSON ¶ added in v1.0.1
MarshalRecipeJSON renders a recipe as CyberChef's indented JSON form. It is the inverse of ParseRecipeConfig for a recipe written as a JSON array, and carries no trailing newline. <, > and & are left as themselves, matching JavaScript's JSON.stringify, so a saved recipe stays readable to edit.
Types ¶
type ArgDef ¶
type ArgDef struct {
Name string
Flag string // CLI flag name; when empty it is derived from Name
Type ArgType
Value any // default value; for ArgOption this is the []string of choices
DefaultIndex int // for ArgOption: index of the default choice
Min *float64 // optional numeric lower bound
Max *float64 // optional numeric upper bound
Integer bool // for ArgNumber: the value must be a whole number
NonEmpty bool // for string arguments: the value may not be empty
MaxLength *int // optional cap on the length of a string argument
ToggleValues []string // modes for ArgToggleString
}
ArgDef describes a single operation argument.
type ArgType ¶
type ArgType string
ArgType mirrors CyberChef's ingredient types (src/core/Ingredient.mjs). The curated operation set only needs this subset.
const ( // ArgString is a free-form string argument. ArgString ArgType = "string" // ArgNumber is a numeric argument (stored as float64). ArgNumber ArgType = "number" // ArgBoolean is a true/false argument. ArgBoolean ArgType = "boolean" // ArgOption is a single choice from a fixed list (Value is []string). ArgOption ArgType = "option" // ArgEditableOption is a string with suggested values (Value is the default string). ArgEditableOption ArgType = "editableOption" // ArgToggleString is a string paired with a mode selected from ToggleValues. ArgToggleString ArgType = "toggleString" )
type Dish ¶
type Dish struct {
// contains filtered or unexported fields
}
Dish is the data container passed between operations. It holds canonical []byte storage plus a type tag describing the current interpretation.
func NewFileListDish ¶
NewFileListDish builds a Dish holding several named files.
func (*Dish) Get ¶
Get returns the dish value converted to the requested type. String, byteArray and ArrayBuffer are byte-backed and convert trivially; number is parsed from the ASCII representation.
func (*Dish) Set ¶
Set replaces the dish value. Byte-backed values are stored as-is; numbers are rendered to their ASCII representation.
type DishType ¶
type DishType string
DishType identifies how the bytes in a Dish should be interpreted. It mirrors CyberChef's Dish types (src/core/Dish.mjs). All byte-backed types share the same canonical storage ([]byte); conversions only matter at the edges.
const ( // TypeString treats the bytes as a UTF-8 string. TypeString DishType = "string" // TypeByteArray treats the bytes as a raw byte array. TypeByteArray DishType = "byteArray" // TypeArrayBuffer is CyberChef's binary hub type; identical storage to byteArray. TypeArrayBuffer DishType = "ArrayBuffer" // TypeNumber treats the bytes as the ASCII representation of a number. TypeNumber DishType = "number" // TypeJSON treats the bytes as JSON text. TypeJSON DishType = "JSON" // TypeBigNumber treats the bytes as the decimal text of an arbitrary-precision number. TypeBigNumber DishType = "BigNumber" // TypeFileList holds several named files rather than one byte string. It is // CyberChef's List<File>; such a dish is terminal — it cannot be converted // back to bytes and so cannot feed a following operation. TypeFileList DishType = "List<File>" )
type FlowOperation ¶
FlowOperation is implemented by operations that steer the recipe. An operation implementing it still satisfies Operation — its Run is what a standalone invocation outside a recipe does.
type FlowState ¶
type FlowState struct {
// Steps is the recipe being executed. A flow operation may rewrite the
// arguments of later steps; the slice is a copy made for this execution, so
// doing so cannot affect the caller's recipe or a later run of it.
Steps []RecipeOp
// Progress is the index of the flow operation itself. Setting it moves
// execution: the next step run is the one after the index left here, so
// setting it to a step's own index resumes just after that step, and
// setting it past the end stops the recipe.
Progress int
// Dish is the data as it stands. A flow operation that changes the data
// (Fork, Subsection) replaces it.
Dish *Dish
// Args holds the coerced arguments of the step being run, so a flow
// operation reads its own arguments the way an ordinary one does.
Args []any
// NumJumps counts jumps taken so far, shared by every jump in the recipe so
// that a backwards jump terminates. It lasts for one execution only.
NumJumps int
// NumRegisters is how many registers earlier Register steps have claimed,
// so that a second Register continues the numbering.
NumRegisters int
// Registry resolves step names, so a flow operation can run a sub-recipe.
Registry *Registry
}
FlowState is the state of a recipe execution, as seen by a flow operation.
type OpMeta ¶
type OpMeta struct {
Name string
Module string
Description string
InfoURL string
InputType DishType
OutputType DishType
}
OpMeta is the static metadata describing an operation.
type Recipe ¶
type Recipe []RecipeOp
Recipe is an ordered list of operations executed in sequence.
func ParseRecipeConfig ¶
ParseRecipeConfig parses a recipe given as either a JSON array or the Chef text format, auto-detecting by a leading "[". Ported from Utils.parseRecipeConfig.
func ParseURL ¶ added in v1.0.1
ParseURL reads a CyberChef share URL, returning the recipe it names and any input it carries. It accepts a whole URL, a bare "#..." fragment, or a bare parameter string. Settings only a browser can act on (theme, ienc, oenc, ieol, oeol) are ignored.
func (Recipe) ExecuteWith ¶
ExecuteWith runs the recipe against the input dish using the given registry. Each step converts the dish to the operation's input type before running and stores the result as the operation's output type. Disabled steps are skipped; a breakpoint halts execution before that step runs, returning the dish so far.
A flow control step is handed the execution state instead and may move to another step, so the steps are copied for this run: one that rewrites a later step's arguments cannot affect the caller's recipe.
type RecipeOp ¶
type RecipeOp struct {
Op string `json:"op"`
Args []any `json:"args,omitempty"`
Disabled bool `json:"disabled,omitempty"`
Breakpoint bool `json:"breakpoint,omitempty"`
}
RecipeOp is a single step in a recipe: an operation name plus its argument values. It matches CyberChef's JSON recipe entry {op, args, disabled?, breakpoint?}.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry maps operation names to their implementations.
type ToggleString ¶
ToggleString is the value form of an ArgToggleString argument: a string plus the selected mode (e.g. {Value:"ff", Option:"Hex"}).
Option is declared first so the two fields are written in the order CyberChef writes them, which is also the order they come back in once a recipe has been through a text form and its toggle strings have become maps. A recipe therefore reads the same however it was built.