| package subprocess | |
| import ( | |
| "encoding/hex" | |
| "encoding/json" | |
| "fmt" | |
| "strings" | |
| ) | |
| // Common top-level structure to parse mode | |
| type slhdsaTestVectorSet struct { | |
| Algorithm string `json:"algorithm"` | |
| Mode string `json:"mode"` | |
| Revision string `json:"revision"` | |
| } | |
| type slhdsaKeyGenTestVectorSet struct { | |
| Algorithm string `json:"algorithm"` | |
| Mode string `json:"mode"` | |
| Revision string `json:"revision"` | |
| Groups []slhdsaKeyGenTestGroup `json:"testGroups"` | |
| } | |
| type slhdsaKeyGenTestGroup struct { | |
| ID uint64 `json:"tgId"` | |
| TestType string `json:"testType"` | |
| ParameterSet string `json:"parameterSet"` | |
| Tests []slhdsaKeyGenTest `json:"tests"` | |
| } | |
| type slhdsaKeyGenTest struct { | |
| ID uint64 `json:"tcId"` | |
| SKSeed string `json:"skSeed"` | |
| SKPrf string `json:"skPrf"` | |
| PKSeed string `json:"pkSeed"` | |
| } | |
| type slhdsaKeyGenTestGroupResponse struct { | |
| ID uint64 `json:"tgId"` | |
| Tests []slhdsaKeyGenTestResponse `json:"tests"` | |
| } | |
| type slhdsaKeyGenTestResponse struct { | |
| ID uint64 `json:"tcId"` | |
| PublicKey string `json:"pk"` | |
| PrivateKey string `json:"sk"` | |
| } | |
| type slhdsaSigGenTestVectorSet struct { | |
| Algorithm string `json:"algorithm"` | |
| Mode string `json:"mode"` | |
| Revision string `json:"revision"` | |
| Groups []slhdsaSigGenTestGroup `json:"testGroups"` | |
| } | |
| type slhdsaSigGenTestGroup struct { | |
| ID uint64 `json:"tgId"` | |
| TestType string `json:"testType"` | |
| ParameterSet string `json:"parameterSet"` | |
| Deterministic bool `json:"deterministic"` | |
| Tests []slhdsaSigGenTest `json:"tests"` | |
| } | |
| type slhdsaSigGenTest struct { | |
| ID uint64 `json:"tcId"` | |
| Message string `json:"message"` | |
| PrivateKey string `json:"sk"` | |
| AdditionalRandomness string `json:"additionalRandomness,omitempty"` | |
| } | |
| type slhdsaSigGenTestGroupResponse struct { | |
| ID uint64 `json:"tgId"` | |
| Tests []slhdsaSigGenTestResponse `json:"tests"` | |
| } | |
| type slhdsaSigGenTestResponse struct { | |
| ID uint64 `json:"tcId"` | |
| Signature string `json:"signature"` | |
| } | |
| type slhdsaSigVerTestVectorSet struct { | |
| Algorithm string `json:"algorithm"` | |
| Mode string `json:"mode"` | |
| Revision string `json:"revision"` | |
| Groups []slhdsaSigVerTestGroup `json:"testGroups"` | |
| } | |
| type slhdsaSigVerTestGroup struct { | |
| ID uint64 `json:"tgId"` | |
| TestType string `json:"testType"` | |
| ParameterSet string `json:"parameterSet"` | |
| Tests []slhdsaSigVerTest `json:"tests"` | |
| } | |
| type slhdsaSigVerTest struct { | |
| ID uint64 `json:"tcId"` | |
| Message string `json:"message"` | |
| Signature string `json:"signature"` | |
| PublicKey string `json:"pk"` | |
| } | |
| type slhdsaSigVerTestGroupResponse struct { | |
| ID uint64 `json:"tgId"` | |
| Tests []slhdsaSigVerTestResponse `json:"tests"` | |
| } | |
| type slhdsaSigVerTestResponse struct { | |
| ID uint64 `json:"tcId"` | |
| TestPassed bool `json:"testPassed"` | |
| } | |
| type slhdsa struct{} | |
| func (s *slhdsa) Process(vectorSet []byte, t Transactable) (any, error) { | |
| var common slhdsaTestVectorSet | |
| if err := json.Unmarshal(vectorSet, &common); err != nil { | |
| return nil, fmt.Errorf("failed to unmarshal vector set: %v", err) | |
| } | |
| switch common.Mode { | |
| case "keyGen": | |
| return s.processKeyGen(vectorSet, t) | |
| case "sigGen": | |
| return s.processSigGen(vectorSet, t) | |
| case "sigVer": | |
| return s.processSigVer(vectorSet, t) | |
| default: | |
| return nil, fmt.Errorf("unsupported SLH-DSA mode: %s", common.Mode) | |
| } | |
| } | |
| func (s *slhdsa) processKeyGen(vectorSet []byte, t Transactable) (any, error) { | |
| var parsed slhdsaKeyGenTestVectorSet | |
| if err := json.Unmarshal(vectorSet, &parsed); err != nil { | |
| return nil, fmt.Errorf("failed to unmarshal keyGen vector set: %v", err) | |
| } | |
| var ret []slhdsaKeyGenTestGroupResponse | |
| for _, group := range parsed.Groups { | |
| response := slhdsaKeyGenTestGroupResponse{ | |
| ID: group.ID, | |
| } | |
| if !strings.HasPrefix(group.ParameterSet, "SLH-DSA-") { | |
| return nil, fmt.Errorf("invalid parameter set: %s", group.ParameterSet) | |
| } | |
| cmdName := group.ParameterSet + "/keyGen" | |
| for _, test := range group.Tests { | |
| skSeed, err := hex.DecodeString(test.SKSeed) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to decode skSeed in test case %d/%d: %s", | |
| group.ID, test.ID, err) | |
| } | |
| skPrf, err := hex.DecodeString(test.SKPrf) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to decode skPrf in test case %d/%d: %s", | |
| group.ID, test.ID, err) | |
| } | |
| pkSeed, err := hex.DecodeString(test.PKSeed) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to decode pkSeed in test case %d/%d: %s", | |
| group.ID, test.ID, err) | |
| } | |
| var seed []byte | |
| seed = append(seed, skSeed...) | |
| seed = append(seed, skPrf...) | |
| seed = append(seed, pkSeed...) | |
| result, err := t.Transact(cmdName, 2, seed) | |
| if err != nil { | |
| return nil, fmt.Errorf("key generation failed for test case %d/%d: %s", | |
| group.ID, test.ID, err) | |
| } | |
| response.Tests = append(response.Tests, slhdsaKeyGenTestResponse{ | |
| ID: test.ID, | |
| PrivateKey: hex.EncodeToString(result[0]), | |
| PublicKey: hex.EncodeToString(result[1]), | |
| }) | |
| } | |
| ret = append(ret, response) | |
| } | |
| return ret, nil | |
| } | |
| func (s *slhdsa) processSigGen(vectorSet []byte, t Transactable) (any, error) { | |
| var parsed slhdsaSigGenTestVectorSet | |
| if err := json.Unmarshal(vectorSet, &parsed); err != nil { | |
| return nil, fmt.Errorf("failed to unmarshal sigGen vector set: %v", err) | |
| } | |
| var ret []slhdsaSigGenTestGroupResponse | |
| for _, group := range parsed.Groups { | |
| response := slhdsaSigGenTestGroupResponse{ | |
| ID: group.ID, | |
| } | |
| if !strings.HasPrefix(group.ParameterSet, "SLH-DSA-") { | |
| return nil, fmt.Errorf("invalid parameter set: %s", group.ParameterSet) | |
| } | |
| cmdName := group.ParameterSet + "/sigGen" | |
| for _, test := range group.Tests { | |
| sk, err := hex.DecodeString(test.PrivateKey) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to decode private key in test case %d/%d: %s", | |
| group.ID, test.ID, err) | |
| } | |
| msg, err := hex.DecodeString(test.Message) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to decode message in test case %d/%d: %s", | |
| group.ID, test.ID, err) | |
| } | |
| var randomness []byte | |
| if !group.Deterministic { | |
| randomness, err = hex.DecodeString(test.AdditionalRandomness) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to decode randomness in test case %d/%d: %s", | |
| group.ID, test.ID, err) | |
| } | |
| } | |
| result, err := t.Transact(cmdName, 1, sk, msg, randomness) | |
| if err != nil { | |
| return nil, fmt.Errorf("signature generation failed for test case %d/%d: %s", | |
| group.ID, test.ID, err) | |
| } | |
| response.Tests = append(response.Tests, slhdsaSigGenTestResponse{ | |
| ID: test.ID, | |
| Signature: hex.EncodeToString(result[0]), | |
| }) | |
| } | |
| ret = append(ret, response) | |
| } | |
| return ret, nil | |
| } | |
| func (s *slhdsa) processSigVer(vectorSet []byte, t Transactable) (any, error) { | |
| var parsed slhdsaSigVerTestVectorSet | |
| if err := json.Unmarshal(vectorSet, &parsed); err != nil { | |
| return nil, fmt.Errorf("failed to unmarshal sigVer vector set: %v", err) | |
| } | |
| var ret []slhdsaSigVerTestGroupResponse | |
| for _, group := range parsed.Groups { | |
| response := slhdsaSigVerTestGroupResponse{ | |
| ID: group.ID, | |
| } | |
| if !strings.HasPrefix(group.ParameterSet, "SLH-DSA-") { | |
| return nil, fmt.Errorf("invalid parameter set: %s", group.ParameterSet) | |
| } | |
| cmdName := group.ParameterSet + "/sigVer" | |
| for _, test := range group.Tests { | |
| pk, err := hex.DecodeString(test.PublicKey) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to decode public key in test case %d/%d: %s", | |
| group.ID, test.ID, err) | |
| } | |
| msg, err := hex.DecodeString(test.Message) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to decode message in test case %d/%d: %s", | |
| group.ID, test.ID, err) | |
| } | |
| sig, err := hex.DecodeString(test.Signature) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to decode signature in test case %d/%d: %s", | |
| group.ID, test.ID, err) | |
| } | |
| result, err := t.Transact(cmdName, 1, pk, msg, sig) | |
| if err != nil { | |
| return nil, fmt.Errorf("signature verification failed for test case %d/%d: %s", | |
| group.ID, test.ID, err) | |
| } | |
| testPassed := result[0][0] != 0 | |
| response.Tests = append(response.Tests, slhdsaSigVerTestResponse{ | |
| ID: test.ID, | |
| TestPassed: testPassed, | |
| }) | |
| } | |
| ret = append(ret, response) | |
| } | |
| return ret, nil | |
| } |