| 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 |
| } |