diff --git a/sign/mayo/doc.go b/sign/mayo/doc.go deleted file mode 100644 index a064a579..00000000 --- a/sign/mayo/doc.go +++ /dev/null @@ -1,15 +0,0 @@ -//go:generate go run gen.go - -// Package mayo implements the MAYO signature scheme -// as submitted to round1 of the NIST PQC competition of Additional Signature Scehemes and described in -// -// https://csrc.nist.gov/csrc/media/Projects/pqc-dig-sig/documents/round-1/spec-files/mayo-spec-web.pdf -// -// This implemented the nibble-sliced version as proposed in -// -// https://eprint.iacr.org/2023/1683 -// -// and the code is written with heavy reference to -// -// https://github.com/PQCMayo/MAYO-C/tree/nibbling-mayo -package mayo diff --git a/sign/mayo/example_test.go b/sign/mayo/example_test.go new file mode 100644 index 00000000..d03bcf61 --- /dev/null +++ b/sign/mayo/example_test.go @@ -0,0 +1,56 @@ +package mayo_test + +import ( + "fmt" + "sort" + + "github.com/cloudflare/circl/sign/mayo" +) + +func Example() { + // Check supported modes + modes := mayo.ModeNames() + sort.Strings(modes) + fmt.Printf("Supported modes: %v\n", modes) + + // Pick MAYO mode 3. + mode := mayo.ModeByName("MAYO_3") + if mode == nil { + panic("Mode3 not supported") + } + + // Alternatively one could simply write + // + // mode := MAYO.Mode3 + + // Generates a keypair. + pk, sk, err := mode.GenerateKey(nil) + if err != nil { + panic(err) + } + // (Alternatively one can derive a keypair from a seed, + // see mode.NewKeyFromSeed().) + + // Packs public and private key + packedSk := sk.Bytes() + packedPk := pk.Bytes() + + // Load it again + sk2 := mode.PrivateKeyFromBytes(packedSk) + pk2 := mode.PublicKeyFromBytes(packedPk) + + // Creates a signature on our message with the generated private key. + msg := []byte("Some message") + signature, _ := mode.Sign(sk2, msg, nil) + + // Checks whether a signature is correct + if !mode.Verify(pk2, msg, signature) { + panic("incorrect signature") + } + + fmt.Printf("O.K.") + + // Output: + // Supported modes: [MAYO_1 MAYO_2 MAYO_3 MAYO_5] + // O.K. +} diff --git a/sign/mayo/gen.go b/sign/mayo/gen.go index 078bd784..6b7e8715 100644 --- a/sign/mayo/gen.go +++ b/sign/mayo/gen.go @@ -86,6 +86,7 @@ var ( func main() { generateModePackageFiles() + generateModeToplevelFiles() generateParamsFiles() generateSourceFiles() generateSignApiFiles() @@ -151,6 +152,32 @@ func generateModePackageFiles() { } } +// Generates modeX.go from templates/mode.templ.go +func generateModeToplevelFiles() { + tl, err := template.ParseFiles("templates/mode.templ.go") + if err != nil { + panic(err) + } + + for _, mode := range Modes { + buf := new(bytes.Buffer) + err := tl.Execute(buf, mode) + if err != nil { + panic(err) + } + + res := buf.String() + offset := strings.Index(res, TemplateWarning) + if offset == -1 { + panic("Missing template warning in mode.templ.go") + } + err = os.WriteFile(mode.Pkg()+".go", []byte(res[offset:]), 0o644) + if err != nil { + panic(err) + } + } +} + // Generates modeX/signapi.go from templates/signapi.templ.go func generateSignApiFiles() { tl, err := template.ParseFiles("templates/signapi.templ.go") diff --git a/sign/mayo/mayo.go b/sign/mayo/mayo.go new file mode 100644 index 00000000..b2149b8c --- /dev/null +++ b/sign/mayo/mayo.go @@ -0,0 +1,100 @@ +//go:generate go run gen.go + +// Package mayo implements the MAYO signature scheme +// as submitted to round1 of the NIST PQC competition of Additional Signature Scehemes and described in +// +// https://csrc.nist.gov/csrc/media/Projects/pqc-dig-sig/documents/round-1/spec-files/mayo-spec-web.pdf +// +// This implemented the nibble-sliced version as proposed in +// +// https://eprint.iacr.org/2023/1683 +// +// and the code is written with heavy reference to +// +// https://github.com/PQCMayo/MAYO-C/tree/nibbling-mayo +package mayo + +import ( + "crypto" + "io" +) + +// PublicKey is a MAYO public key. +// +// The structure contains values precomputed during unpacking/key generation +// and is therefore significantly larger than a packed public key. +type PublicKey interface { + // Packs public key + Bytes() []byte +} + +// PrivateKey is a MAYO public key. +// +// The structure contains values precomputed during unpacking/key generation +// and is therefore significantly larger than a packed private key. +type PrivateKey interface { + // Packs private key + Bytes() []byte + + crypto.Signer +} + +// Mode is a certain configuration of the MAYO signature scheme. +type Mode interface { + // GenerateKey generates a public/private key pair using entropy from rand. + // If rand is nil, crypto/rand.Reader will be used. + GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) + + // NewKeyFromSeed derives a public/private key pair using the given seed. + // Panics if len(seed) != SeedSize() + NewKeyFromSeed(seed []byte) (PublicKey, PrivateKey) + + // Sign signs the given message using entropy from rand and returns the signature. + // If rand is nil, crypto/rand.Reader will be used. + // It will panic if sk has not been generated for this mode. + Sign(sk PrivateKey, msg []byte, rand io.Reader) ([]byte, error) + + // Verify checks whether the given signature by pk on msg is valid. + // It will panic if pk is of the wrong mode. + Verify(pk PublicKey, msg []byte, signature []byte) bool + + // Unpacks a public key. Panics if the buffer is not of PublicKeySize() + // length. Precomputes values to speed up subsequent calls to Verify. + PublicKeyFromBytes([]byte) PublicKey + + // Unpacks a private key. Panics if the buffer is not + // of PrivateKeySize() length. Precomputes values to speed up subsequent + // calls to Sign(To). + PrivateKeyFromBytes([]byte) PrivateKey + + // SeedSize returns the size of the seed for NewKeyFromSeed + SeedSize() int + + // PublicKeySize returns the size of a packed PublicKey + PublicKeySize() int + + // PrivateKeySize returns the size of a packed PrivateKey + PrivateKeySize() int + + // SignatureSize returns the size of a signature + SignatureSize() int + + // Name returns the name of this mode + Name() string +} + +var modes = make(map[string]Mode) + +// ModeNames returns the list of supported modes. +func ModeNames() []string { + names := []string{} + for name := range modes { + names = append(names, name) + } + return names +} + +// ModeByName returns the mode with the given name or nil when not supported. +func ModeByName(name string) Mode { + return modes[name] +} diff --git a/sign/mayo/mayo_test.go b/sign/mayo/mayo_test.go new file mode 100644 index 00000000..e7e4ee00 --- /dev/null +++ b/sign/mayo/mayo_test.go @@ -0,0 +1,136 @@ +package mayo + +import ( + "crypto/sha256" + "encoding/hex" + "fmt" + "testing" + + "github.com/cloudflare/circl/internal/nist" +) + +func TestNewKey(t *testing.T) { + for _, tc := range []struct { + name string + seed string + expectedPk string + }{ + {"MAYO_1", "7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb14803", "5b61421edc1c90efaf6075560f0206173555c55eb845ef3a70ee5ef18618361883a0ade490e9e5bc51cd2b25fb4ec9147a2fa6735d8749ed7e149330a30b3ab62b7991c2494cb21d0bc011ceb357597b8afef939a1fe398421c88f43fb4fe380c10caa3a95e507ebae5a571fd958e0505d994566263be8db31ac833aa20ae7ec97d1a865bb292e89d583975009046053bf91ce7d73e9c23c4244071e17a1095f3918330559f323ce557d66b8771f0003cccaeea82314088d56455d72f258e4c35fc6ce2d195cdae99f359a8307ec15f27da4d0634531cd9a1a719121f7c9b99a0d0c24252316f1ea7c16d73f5ecf7125ad0c8d2e02574131504875af5ab6dea1c328e71122f0cdd09e826cc515b4ec160f31d63253dd8798b2d841e80a28479bcca320853a459d4d659df695eea4b5aeb8f45f6c5fce283c64dd6fe928d452be3723f8b448650ebb72acf231e3c27683afcdec22037f1af29c479db1a97448ce570fef082052c9ef45179ba62abd7dd156f17f4da51557383d40a9d544cdf5cac4f4cc1ce69326a3ccc611fb7a6d04126dc54c55c2286a796be18958846d53e1e3f55f3ac0f4e09d8f302878f4993e25c2164970b337d0364aa61eff5d85e41fe784fd57420a5481b9a15f02a47e3e49c0709a37352a50fd0feb7e7f9938173b3e3c570a79c2424f5dc5bf95363b6d5d764e1a38a1aa05a31bbb9858b51fe3cbb19eaade5d4f482260838f5273b042f6340236395f6c347d4bfb922752ad0b17f1bae8645a9a6b1d72e1e91b4828faa313dd85ec5795252dcd95aa33519a56d740cbab7b9ee13e1b8add763bd07a25455e44e60f664846e32eec329c46e0741b6649c34358905d9d01124c3c8ae14e3fb47cc6477ba8e63bd4a3937588251952f5232bb9999aef509414e11a36d110ea24bedc235c55ab6f80116b036845e291148135a32b0d44fe5a4e9ea9f3ae150e11c62ea91318129f79318d3506ba50db3dbe235427d405a5baa9e6192a17014dd19863087445eb4cc9b6164aab3d5af4e73bc3edd97c76dabba0bc26c43d70f7880a0f7c042465da77ae3f8a31fa65903d90797fc0b5deddf578d52940040276c9b415d880e3782e03a2965a6d3b265628c690bd1b096a355362eb751d528fbc6fa365d1cf3d39cf49d8296c28fe8eb52a31a07e877d1e57e91971cbbd14216db76a08da45258a1a801d0cb232a87280df4522329ecd9312e5489d90a39547735cbd11493d0d86389af40c1b9ec5a993d0cbc508da424392695e1cdf205a294122412fac5a2b4d6e0ed5eed7b4de18f0d4b81f746753fa8744ab845c18800befc926d3290531053bf2cecf23d1b6d7fa9fb8d4827e87abf574afe39a636dbb9fce48854c641981f236da01bd8a5901871891aac7fa1f02300101540e7b05665e5f19912ee898666b64bb3cef688577c7b5482e123c0e8fcc466302eca8fc02f35260569cc1d4b00662be924f188226dbc6086d4aaed1ff9c7604748a556d00f87823f9fafaccf752d645b76a5851723274737e4dd7d5d76fdb256e3f1ef733914eb36932eb1c4c666df436351fb817e7055fbfca2b3103fcec84233feaf3fefd600721d3ca1514ee26db6a608dd4333377a9e36dd2dbadb1651eb99d8e3b4fe6"}, + {"MAYO_3", "7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb148032dcd739936737f2d", "1c0ee1111b08003f28e65e8b3bdeb0378c8800a9a87f38ca101b55cbe065f76cd8be17feef5b448fbdc40c759729dd609f2f3e0a70f719bd04bdec59158c1d885127c91066d31b4e53848db9566d8d25393dd3e665c8f4b5fd5d5b836fc2e012a059a5550646dfaf9db63eb4c928198a4dc3e8631fa743e11004a2fe3454a9d537697af4bf5d6bee82c2fe40d5c74c29be0cd7e56c8dff8dacebe18320a455a72265559a287385643668d2a20058d927c87a41b8d94ac1c68b6a07c7b055604c7491f11ac30974ab0d76ff2034b6c73d3b4cfb13e8f341f9f3f445bb6a4e47aa381282f83af4c46fd38207da843135dceac04af08096915318e464a8a1fda2a99efd41c61197a498abc875ce302f94eeb8ec32e56f24e2c6c419250e08e2f69148fe083747340af17e634a98afbdd6902211c767b750365f6200fd92e8431160f1e293058cf2cd57be92816a712d796e6fc0c672026c162d93eb79a19c7d4853df371234fec9c9ce76b6edfe082007ff69c64c9980f2c7b7b6009e3db0990cffad1f4119844967572e1122e5c7ce460ccf732c82d3f18457111ae8e1a5381c5b30e9d76028ca26839455d44aac728a24731a1d69c8c856b3d611dfe5336fd5a42f62ee607219c654aa117a874ca33fbb89ecdb6310cb4e0c4a5e2554be2d4bfe6abb062eef513d726c258dafa690324302d8fb108376f991e50e9037e31ed3ce8d8cd785fe9eb419d33c7ac381f91c463a8a06629db910f5fed1d18f2cf30afcfc968ca5617c6cc6fd9080f53cbd05b727c04bf75dd93f08a0ac1a7bc46e8b5a08e6d3c3b1e1232126d4e65b1a3877689dca9b1e53a73d45ad9eeb38faf942a62a804b088226f4ecf15526e24936f9c28c951f5c101c5c44bf91b72fecbb3a9d28cf77e63343ad760089e0739017cf829297204041acf5b4c10fbca19219db233fabb3a564c8cddb281f290b9a8536c9a1d39a35d8eb124182d9cdc51044067647ee861b8c0c6fbbe1aec13076b8f3d8982b52d1243a9448729361619ba34edce7bbc1b3a1545f791a5f2f6d04b5204e073bf66e7b009c7d4a1660355d066fd0d358623fcee946e69d20bf6fb291906e700004aa001494381382c5e1bcc4fb2b7cfc4bba6866548ecc797fec670abc2e8a8dea2c4219ed32102a0a1f4fa67775512768e57851571fd383a5a684ed1e10b62f3bbbb65d58e08151695008ef6a7cf4b7cdd265d9cf1c158f64c607aaf37e51140518724c39f3ad8a759a7ec0af43778c00832088270934cd08a582196953b283fa047f6365585b6078027be9d9c915569b78c65702561ef5de7953fb6f5e3df3ae8b85d3fb2161cc3af62ed83d027b733507fee131da9d228c79277630c3efcdc9ee1e559bcaee4c818d6d29ea6c8cf9eb46ad58a4ab6a4fb2f6d6f4380efa4d60843ca4eac32f8772073f1cb70021547050c30095fc7c884e31a2f91994985eab00e7565da2ece39e47a6c8cfae012687dea9d65b8745d4d760e656a55243fa9ba8fbbd31b7f2bb2629a0ec9265aa883c8775ba173e5ff08a9a3ae4e76f9925418f4e2dce1d00e4f9377245b8939dc58b7d15c172baf984781afd318b264709bde5f0859a95923ecc42108f2fa7c600e9ff69f3f65751d8a457dde89a1ad900314f90e9b712580eff5e4a73efa3633c5d5e34fa8f2528075fa92dce66506f5e947f1fdef820296cc294ecdc059390b644a1407b13d24541d275a49d9bd1a6f68dab296f52965c7f72d50cdc0ec19456001516c10030086d2efa109f45fb6d1f7550de534d0d4ce856e72763463e6d0d11cd237037fea14abb32465f632ff785f1917322e4574bbfa8f74682da17f2bf7bffa0ff030297d5c999d6a7c387ef2a5e168225a60ebb01c6dfc72ba1fdec8f74651f3e64750f2dc98d72099fc85f43fb28ee0c4efe8b7d76bb432453a848310f6e96d833a27ccc98046a210f568c075dc71545ff0d37ae5138406d569e964bf8e6903de7651b33c05e22747074b730cb6f3e94b891e8105ad6921cf5efd40da88ec3d0765756b7bece012f59f1f68ab80082fda5fa37b026d0b6cb5fab9a0ecab6980a179815bc9e56cbdc0d0682c29c5f9fc8cbfbf5a6a9679de92adb5b4778ecdc70f819549087bef738037de613cbec897e016672ce9eaf00382ce4b60c563cf3d23cfa178403f270215cef465ae9b60f007c75c1fcb85ab4ae9ead303057dbeedcaf55f13ea586f55a2eee9da8dd92bc210d1e2d4fb7d219c54517fe5a4ddf5c8c6a776703ec8407d6b393fb331d7aa62423cbbf7a062bc210e9c6565cacfef1e4a5d448f2cbf5c8861857dc870bc37c2070ce1f1147dfdc285d9df8296d6620e1430884e29571ea95ce1deb9c2ae7198f10732b2b2d5ddabfabda6e77acfa2b10c75842e07de69cb2b34abe41018c9a765e45ac85b63a85ca612b1e9682d7c8f512297bdfb780e21506956fcb528bb1916fc1a8356667033e99e16c223139efef6790b8745eafe30df12d900301643f8bd6717d0b5d1de5e75f25bdc950ce507ce7b3489e72d5abdf5a28105a8063d0a9662672489de16a1628548382277fcfb24bc878f071b13d6e120af00c1cdcacf5f1ef4823a2b5da0e7c8487550d80ac9f6891e50be3dca0096042c97cdea3553db702bbcfcf64f1b64719bc89ba51a09057fd9285c4aa7d95532cdc04ee185beb1318132c836278e368ff8e2653e4aafa829a2d40d91bda7b4af3f16442931b7da2b500f7e3abf80219b8a245fc4748d20d549cd12c5af7ca3a8543bd14d0ddfb4fff8a43c661d0a8163fe80bc0f77b762d010b64b831e7c29f9982e5b7338a6411a37c4f1f46419b610415104f154a009cf3bf1805ff279145477a0d5ff0f3c9584874e8e8376101dec2c8c69592a8c46add07a6c0100cfab2bba03771749b3028d287805a6859a1e3a82f30231b01a7e3453059638e0d7a2430348ff4af26d00481cb3de085d269015fb6043a0346281a05448a81d04ad196d916503c35d31e513bb133d49f9646c191f872cf4d6798c18c87e52695d1adf59c97ba8bff5e826ea17ab2fcb8b559e871e6d62d8a93522554bb5d48de674596761595bf28d0114142a542c2f9cab2be451eb37546ce3eb60bb0cc6050e5d38ac96752a8d2575f67ce28452b00b486e2efc8aa80e94a0a442fd35f5fdeb48e52a82c43ef2c0a02d3bf71da67f0131af8aa90e159056ebf4e5dbbe176c9cd8c07d234135c50b524a4efd7b72ca4f413b29809e7a1a53442a1919bcce952203d17e3c5600dcc3160dcbf7f18b9352289ce78fd337c36416b8342635c3d542bd1a357b8e39b04098fe7b60248fd6ea4a2778ec576e4c34323c81e56386d40c79260e3d914db7cabbf269441dcfa216ef7aa85fae99a89f2c1f56838c30fc180135efb98bcd01e2a88d144ecf7063613d3ba62af5fa8cf7d63465273ac0abb3f94e87130310f4b841db13ad7fab1444a02af5649ef9a29392a4fc15b747799cd8a8d735094cb03a606735ac94ee244a8c5a3504f31ae62d3acf7f1586390efc6e8da967f3b174d9e805554603c4fd5cd875e70352d2c6576e3baf0420d6f3aa161f605219bffb93abd51628014072e7c2e533aa86117f02ccd67b623af4ca911eebe981595fd393e75d5b0d0da9440e3aaf9249110f5e8c22a68f9cfe0b30e8665270763390fb8618668a1a56b71065a85b91ff8dbb8e4ab9c3e6c079a2b0276ba475d388262f36a76c3e230bed8c47faae910"}, + {"MAYO_5", "7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb148032dcd739936737f2db505d7cfad1b4974", "708141534c09f5f604225ef8c3472f3749ffbce6c071fa7bb1f4b50b78ecd32e7f35efb6bfcead3313156f9995fca2d2db6d0f0ec50a66bd3d5b469698ab131f21cbae3785a0c838e2e3316fa73e9670adb76fa9e1ec8a0bb7ddae82c0ca7c1aa5e61c31b84180c3aae027223430e988e28c48ce0d5b2ad2750203707f2e284cf1807f008ae2570092a662b73a9a728f81a79338f3452d6af920ee59037f2c8a20b495420c5bb3fa7518a34ae1e64ffa742db0c3c009504ca98882e4abadaf8396cc242d9a7c1d4d71b17d6c65ed26c4e459d8bef86326ecc156209299424cc015c52f97862998f871ebacba29877e040b7adfecc69081f55162d190f374b704662c138c39782e7a8b74b7867e92c5bd8a7833b4242f04712ef4384ef452fbc3078550f15e563c9238d72088275d02d94cf8c163a2bd73810938a1208883874e1b7d8a9ced0ce6a7177da260ec1a35d2e0f45bbdf18f27cd3f0619d134aa47e4df364fbea1dfb852c225b06be4707824d9d2f8b25d6e15f81079511778cca8b82554591823616a7b7ea029c3c3670dba35bf2f11b6493ba5044c159c368f7e4d3ddb215247ac0fa17f227298b9b1d6af4632fec18ab98c9218f583c75e9b8434cb0b68105e44be85da80a65fd67839b4981e2e89feed17f41b60e75122b5328fc0a5772b8a0ec5e4646e1fc1f98a44a31d516be5cf6c187850d7343078304f8a2a02929dc2aaf268ee590507b325a0d744e413d58dd61e62decd0d4e846f08f9fae80cdb7e33d693c57e46cdbc7e1ebd06fc44133748064db8b77f1f87df1f21891af721e840d768be637ebd41cf8be5de36739045b9bae72cd9192a1ff0addbddaf6a0b6cb0d0923ce5b3d5c261c20b1bac348eed6d1cebcdda642103f3a4246e9ee3a1f1950be11796a2db39c54299a6973bdbc4a9446ff27a85fbce46e4c94c25d6fcf1d8bfc773df36591862c0447a400312969c056399b2ddc92703a4d14f1b5862752257103a300381f41f47d7baaaaef9bccbc1a3ce8c94edd1d7c43ba63c961918c1c9cffdd03659158d0827384f796466449a0bc72e94badcbf567e9f6812e320b772b7d330ca8d58996fb9cb9a4ee7772ef4e77f67e2875070249026c1287ca6b43af591a647c33efc965921c9225cb195898f0c0185d3142cd1d924119b003b0b51ccb42caced8baa8060a1750b53f7c039f857dbb248a2520bac9117da7a12ba07483bb751afb7fa1f3d9e9eecea70a9fd233adbad40fd3ff7ca1267a4a8d2375ecfe35d7984ce860725f68f19a19c0e00af83f13d452491720370effe877ec6ad51e702c9ae828b0ad3a845519d3267f3908c808498ea73bc96b70cf4d9cbaf1b1bcc9b12a093936cdf56cbb703799307d80b3755ad72dcc0b667cc14f6dd47d99d936ae3afd5be34264ddc8eaa7026e6391780444ac43c01cddba3c50548d7a2c03a59b1db7d798043351b51d4fc32f6d5f8ceeb8654977e7ba147936a6d172cfb023308730adaa3973fb4d883b95cdc5aea24a83e70561aaec784023e28dc385aae7076d271ca0551b83a60d7388b9a2c804ed66ff4fa6284fd57045d03b6c31d0d32165222efc6876b14a01c18024b0d6fec28361de82a337fb087ba25daed484b3e17fae66ce2bf2bc88614ed5a2e1db9f485ccbf7e029009c164ae3bb9b7f3b7de396970cda0943036e18d2cf96b9979e8d874980a844d7628b5fae66f00ecc4366a96c814785516d056e44b906ef6dc09e1a976384ccaf1b3f40d79a5f6ad426bb70035e84961c188ad24a8122088fb2a4b5abcb5fdd0a26cd7d44dd341c5e5ad65478269cbb5e30f4c23d63043de9c65fdd57fbae9f7a68c7bcf4e4e6b0eefdeaa3bf376c912b15f00e1a6c1b4c80269cdf9bdf25373fd55a7f51ae9aa0c0de6faf001a2016eef56d82eb696472546ec8bd29f1e76f0666b4c8d4c4cf6e633b30f323110d7b0fef38a2ec90f9359278a23f276da7984e87880105d12051937b037d86688b0aab4a11ceccd776263b8a82aa6d5a5490d33e734c651aafea394fb24d85ef3a0620686e1d96d198509e5f04f406986ff201e0b2d3d7584216e8568c68c2d8ebe1947209dff588969c3c088877b8c1dc0b0fadb7295fc44e3bef5d81789329675ac5c3142fec702f749c6e3aed13071c02680f7cb82e91432f6d6fd7c10ca132e61f2d47d6e2008ac2d5157445c1a3cfa52e03c5ad575fe836cdf4d8c9624e097d969eec08dcb4540be5b4a9f3ca03201457a2dae4a966d0b35abc65559484fe0afecb774e9437eba24d22e4da5927d00ca3a9cd49a1f3843b1f3f7b2872f0b1790788bb216d53b9b61f3f394d140a200ed30c3229761af6d3ecff8fc463ef63ae13f92d3d555261f04a287dac6653b7d493cc9026f5be29c8c550bfc513cfdeaf83ec0280fe2786ca9c07b222f6ccd9c31a8848a4e79be4b590fe4e239ad9239df96539b48cdad99fd0249d50204649e26838a076adcd6800221fff817681a6a1ccf807c1ae1794aa7cbe383cef23610436d51cdeb631df8bc1f7f7207b9972c60dfba18cd5378eab1501c6f8d4e0971862cff6b1cf3a327e1afa6371de15fefbb1c80c658d2b372f0bed979929e9fe3c3769ad0766edb634949c29f9bffd879c961f626d10617c161319957c28519ef29142236ccdbe214f7e3e9ab77edd5fa814f5b599513a46f79cac9fd9ab62d7859ed57a5e6a0af7f5e74ea4f9fbef3c9943f2c69cb66ef4497c92b25059980bd55568e8a5c50c0853fe02f9eafe068ebe710cf284976fe4b3c12d5990951775b891cebaf38ba4c9dbf70423210f723a6c0961f00766f0acf1ae75d3f1298b378cdd7fed999a8b45c923c3c8a9a48f007b88f6fc9e0d37458e441247074e9c89e7429bc76a7bef55e702420c1bc65d66bb28d46ad7e0c5be42de7b89a44dbe7ee416c795c0b7e91ca9cf2f2762816ef4bbed139137a8ad3fa7a5a96c917e8af660e736ebe9d70e4b90fa18b560ad173617f8dff65804a2bae40a4d27e86e97e02e485cb529fad4a5c7f72a2b758a693826bb964eeb28842f5aee51db712d68354d7f1ec129b7785091b1cbc3fb389263e064eb03df94183e0c1bd1824b8f5c232d7970c11e53caaae90ebba5ea862f5aa26aba25b5f627823182444efa64f21125de36afdd615518bb5dfdd117b5485910319b458236dad01de33b8605352517ce3aeee706de917ca76ecdc4ef53a733e5f898c2dd6c4d641d141ebcdca2c5c7cc176eac1b493df81702083bfc124ad9ed3511452a71f831c9a2f8d2d771cd3c1b1c440bdc46e87fb5ddc0d45c3e28c10aa1af313c08bb554590dcd296e0916a9b9df3d527a5db9ec1694083bb99c480231c87444998dc7f922f7159b019460d39be64882528f4df1e3e332f7386cfa34310b666d369ed7fff15ce6db939e448beeb74e221862a901c37275cec3e3718b146d0376c0b44e64d393c231050bf166658c333509aadca601619ba6e473705b5be1c9c290a390ee24062265298ad5bb30cc53571b4e8046856a10da99823e0a33c85fbfe785ba709a3cb9b97dd6d56db92febf8a833941655294134be7d37de581caf4e8fe278d9ad5e31d046c7c4c6e3f162c8b5bdb27f1bb5c772b8e7838f67f97cc3c090510fcb5e2f96191a77eeb7febfdcbff81a58860bd4fa87cb41b1fd51ac670828fd6efdcace5ceb85339db706286e860bacb1667da894ab79d32a67563f9a1935953679b687b558324e801c62b9eff69888a51cb8c79d6eb4aa9651108b53d1b66afb1fcbed7dce98403c64885bef7e45a0689ce783cf7741c2c787c1643e08a109b7f5813c11a16bc9269faf0c74e6e0d08428d3de2cd00e18615e157488b2a4095ade2e101dc3fd48da57bbd1c79e9c5cf0992014f80317fa35ee71560c27500761e8a60449546ffe1a232806a8ec6a5694941485f3e0af3f4cb557a42219435bf38fa10e11f3a243c9c584cde736a02bcc37b8f624931710c159f167cdb41deec3db28535731dcefb4926c8580d290ae818eb3a09738ca5d88ed1909ca95f1c71d9305f89b773cb840e3f481aa2f51dd65082da3afca358bf88d2781b46d82d7685f4ccd0983c75f9f1d6382493692604da6c8e8effb27129b1776509b98efc15c75ea1f11c04d7374742ec8cf28341a1be36deba666dabf6bcade7bc3670c03bf3bd42441edfe79716a7ccd32dc3008693a42800944bea936484bed7b6174718d31ada938690ad1efb0442fcdc7a8967f96fc4fa96821ff9862c3b1495ca55afe8ed5aa8097e20fe54f3ed2f2be1cd241a494bccfd3c75d7acd180ab6eb192402947c273abf6fac2e957c8fcc7757d79361071b2067349823cc9db3d531aaf0561acbb918df2924276ea64eb2bb095680d0be8da8d38d53f97d6cc68d88bc4f22c6865cffbd59a6fa015d2f0a12a985fd97a34e4d7f9504cc5a86acd4c791f105b9cb944ae4d0b0f747a1dd089a7903dda5528752132d2387e4854234a8a3ce95fd8afd4bfe8e55f4c026e80348ece14da917b3a696ad797e70d06356cfd2463f5ccb96549e1a037f938624754c57401cddcc948cbd088a0f276329a87db91308ece6360c743e4f8f360fed28b77f7a60745aea0b89721f4cb342b75ee1e51625292db27a97c2eb18186278fd826fb49cfe87fc9b45bd26a02266da90a7ca7d6c5d9eaaa036a0c7a12171832923facc0aae7554eb365e312e6b7b3e8be167b8e580fd5cdd609b5308864600b98f9b69d71eef1d4765f4ec07a584d9bae8a407777d7334bbb285ddb15a07dd5e3a4e8c8072710a4ac204162987f2b669524d88afb77e5f4a540f9985d560dae55945abcdeb3f90a498f76cf44d0a9e3977cdadc11a8613d50e4fb19577a6f6a16dd1b4003e56268a1134d774b9cc4e94ced0943a0199ea9ec944e891f02deb85c1b870e535f97599f843e8467c771784796c3c8712f3681b475a4eab150d18928aef90f293bdc505784441b6ffec7e525b15b5d1e2203f8ec95db5eddc8c6eb21e82118c75d6dcf2c58eb4487eed220b1eb6f3a3a7e92b0ce13ad5e87c4e4edd2c8bcab83d7622d20f3f5cd74a930515808e500563848ab0893cef9323ebdeeac9716270f3550c1d92ffb4d650c8442300cb7a4c61de2b5876f6563271ab7abdacc962be387556a6452dfdedf99148b4a2fe635dc730cfe9cf07a1ad5e148e2eb639e25838a8b5f6271a1ac8330847da496f042237e9f38ace9c37f096da0d76157825c2c8f578919faa984f4be65f7055e517b8f78589e1ff361d769e5d387795b79bf476959815d9b6ff22361f76e60cab6986e0d164a0984a013101e3cadd3eee5199030b45e8c6b9ea63f80c7e6e2909b39d96d6f62776820281eac9fb55fb5c124b7dd9e9b114d476d2fbc676df79f9e9b214ea69013681e7cd8d379bba254382ae4678986f67eba92cd978ac6353e6207101a3e1d18008c3d5924eef4991e0b576fd9f582980faf24b898796c18388f40ae96403d45b31785958d37ca09b76a5a7320776ca4d328e95ea7b6703f4ab0947070f5c20dfd154a9476099d193dccd487f589759754c43fb81c1941439b4d63eeb6b24c294c70ac0a71ff437a6abb795aed2fa4e2483f2a09ac6d1a85b91155cb368219d17883106568c27c924070ad23ed0193dacc353dbb95a4c1de118c1a710f96db6eb9c146c2d0e07873d495d1ad9e3717e09c067422fe5a2da8d9406e1395aa39cf0c82f9c290d1e31a4a4d9b4c381c95079327c296e5db5f8e3c92ef62c03f1c2ac7c4b0174528b5dc0ff37c8c7d0533e4248fb86ca1cb5df91e05e1cc582482e7f12136e8628a48085ff27d15815506c5013f6f65e3c89286616ffd5d08f3fc2194ae51fc4a706e2cd83b6629ea8cce9ee3f968db84c85e3dc0c4b3e4cd6f105a196260f5873c8590401719ce3afd8de96d465b5258ce6b6e53db24fdc8fea3a9062fd2f10ddfb0adcd355724e366afb6b401118d73873c8e682dacbb4be47452eeb98ce51607903126f83ab6b27723818f816f9ede8ef344b3e7bdafdbe8292c6af60835f572ee68629386575541f1b5d5bae84bd85cb65e1ec46a70abf6365f75f975c3b87944e45d0da01f267b569d9ce55cdc90fb3ba1b5f7337f87a914eb5f6f7dd66a56b052430b148e3e295eb82fed70c6a38f738ac63b820db7183d18156abaf638ae366ce6491f0f0e326e1c9c3c8e7df4d62632f7599805f4a8ef06ddee3191e35f20cb7d03e7afbae7cc71a914aa9c1744b420ab5f406771e944ee7e3aec062bec33696df2c5ac2e09648902ea629aac071346ef87f5e54aaf650785f5ade96e0919ec00b99926594cdbdd1e0482e56fc0b78cb6142d2a4be8aed181918b11a841fbb8b442a3e2af1ef1c29528d6447c72b8c2e514aabd0595ebdc698b90ef61a6ee4b400f01fa5c71a2dead6822f33c3341d8c019bd100aa9028b57e517ac6880112335390a8349b90235486eddee01685a7cf1ea158cf9cc1f348a6b113a9d82f2dae95c7ae56f9183d97cbc35a25baea3552b8c2a7de779f6b74db1cfc75d07d79aae1857b601e73cc3686c175f135233989e6d56bdbe611f96a2b51804467e47b474479ccfabddbb4629a0fdc7f73e172da3c168c6c40461371e05a9a332ee3aeb0c9a5985425e102e421f497ec978de92bf73c98fd7d1bbd068e9d8ae82cbc7ef3923bcfe97bd68fe9563195d26a1afdc3bd91b32044fbe68b4bccf29a8d52d13c625d89f73611e371dfe6b73b50d6388cfd87ba92074533cfb34a4d543126f096002d9ce5ecf89cc11b0449f696e1661a36884ac1bf58f397d993c82bcc03c1db156ffa5148da7a73b3be2b6a3b2436c26c24ac0154bee5837d079dfa65d04a208de8b79691518f9056ccdb382e61c8d7606be73322641c71719a23ad6a571f907aa0bd1d8f3170296f3cc88bacd9b3fe944548808e80d00c07bfddf271ace893f56e01f95329aa944d32d9623180142b32e60ce0b908cf2748a29c42a3a59b378e47ebbc4ada9b43133f51bb4d28b821bec1788cc94ac1c8e9e4499aae9e17fcabff0a824637f125e9b358e0"}, + } { + t.Run(tc.name, func(t *testing.T) { + mode := ModeByName(tc.name) + if mode == nil { + t.Fatal() + } + + seed := make([]byte, mode.SeedSize()) + _, _ = hex.Decode(seed[:], []byte(tc.seed)) + + pk, sk := mode.NewKeyFromSeed(seed) + + if hex.EncodeToString(pk.Bytes()) != tc.expectedPk { + t.Fatal() + } + + if hex.EncodeToString(sk.Bytes()) != tc.seed { + t.Fatal() + } + }) + } +} + +func TestVerify(t *testing.T) { + for _, tc := range []struct { + name string + seed string + message string + signature string + }{ + {"MAYO_1", "7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb14803", "d81c4d8d734fcbfbeade3d3f8a039faa2a2c9957e835ad55b22e75bf57bb556ac8", "165e6139a87a4a4966326ba83e6d1ef68d1d7bec62c9d1d267ba09df6815783980f0a6ca0923aee6e5b9495b7ed6fe6c49cc41f794a80d297b19d3f13b0bfe3e8865378f5d24a210dae0982a1036ec9cbe87c29ce9a05a8290d0d1e8603abd163a27b119878663c06745cee03f417300402bf198ee4ac2be99dfe19700f169efe6a365ae0fe9c1bc22028c864ec55072da4f98f878759de68399a2c8d2a2656996927265ce2908e05913f8057707d39dfd3ef58a79cad49f0bd010ca9e8ebde500057bffd0ff28015a60b3061cee55dfa1d59e1a72a8ce639777e6190542733639fbba575aae945583bf804ea129e1a80e12fb628accdcc3f43da37c7194bb641bb8b6404aee481b4ffb13be31941d30c1f9d818182545738ce2644dc9c9b0a1289c6294d3225cc23ee03cc8258176e1a958e90dfed58ad3a859d1b06dee53af6a"}, + {"MAYO_3", "7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb148032dcd739936737f2d", "d81c4d8d734fcbfbeade3d3f8a039faa2a2c9957e835ad55b22e75bf57bb556ac8", "01de18cb2cfce7ba2d15677a57e7d86b20a96c7b93daf27232ddc7a0249796ef9321ace5792a4af1ca49908780398a25f9e4b1293ad8209301c769f123cfa430e5bbff1812dd4a8efd5621c109444cb4a1bcf4f1d85abc6fbe493ae0370aba2b2251de011129be10c25f452c987ddb1c499faf1dc8da2e60e7913ab7ade65844a92ed3a5c04c2245c67d342e5067be4a8c024753a8fd5962481b9c52051723f50165ec2b0ec8f73b4b337361c12014607f9fe41c3591eae8653d18b95616b18a84a1a5951ab5082ceebd5d2cfd202fe3ae29b60a790d04295edfbce886eb98d63cce694c9517f5f6832b7cef38efc9c8f4c14e01429f5487cb752f675f4e4212058db63fc29b9c00701810144ac48e7b007f4dfaa80a2ec9899e60f704ac0d0b58c8a716433c91a27d966d2b7b2685da350c9f6c59233988cbb3f8f2383f5eb10e496e64017a0789ca8f702254e1b839382d42b8399488bd74517e280f1719392621596730862678dec519c50cd6bdc07f118217ff68004401fbccf8606c1af2ae6ce0dde06c1bd06a460bace8dc9408f1d5cf76dd063f63db9a0969098ec45fcde2e878d464f4de4bfe1fe710f2132d8e486f64e7d309d9faed999ce368e821a05d79f781fb895a767a09256541cd54242b5df5e262220fe232c637934380b137df86ab4fa07b11f07f914835c87d1547fe526001a61b8ce00721d90d8a4b54b60000ef75d9bdb94fc7f861ee46908ade105ea098cef938f49dae729817633003c87a0a6c0cbfd10185f7657804a2330a7def349da1df84a1a61dc857d2458425"}, + {"MAYO_5", "7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb148032dcd739936737f2db505d7cfad1b4974", "d81c4d8d734fcbfbeade3d3f8a039faa2a2c9957e835ad55b22e75bf57bb556ac8", "7bc32600e7fe4e0d8caf187997624ba57867ec136d7112aceb161cf813ad98aa9709f0e42bc6e86c4c1a32e5b929df9976a4c0d77886d9e5005fad28c3b0e20dd7bb8d49aaaa77d969c72c9d37d78c3ff556ae777f4bac4d505194b6026fb3e17ad631980dfc373c7510c024817c1900d3428984e4e952b49b4c46c928717ea34f417b5f5d6067caf5edc15c1fcbf74d9f7a158958daf27acf3bcb611195278550d06bd83441083e2a64f0e70a8b668453b7f638a64c6d2424cf2ae31fb6efedf951215d14648d2e3282526c0504e4a0b56ac0336a28b98297d16ca2087c3c46ab10275ea0f5611bbde1b44beb420977aa8ec3693ac097901a8e3aef2d377e19ab6d14a42a5c5d7a13ec1df5be83657b7ee84e7671828aff72265bc7fa90829f92df63a159e51e222da67a5201db70597814ac4d793caeda47d7fdd2c59402a2e8a67beb6f9f43b31feaec24854f429e2aec6fe9e7412584f08719c0c5c90e6bc5371d65eebefcc956ada0659b9b0b5f4d4733873fb4daa0e837fda9062d9a79766ef66686f9b355a219d74728ccad98b04391427a30d8b95391b9e54b9f902853d0086fb1bfd136df4dc1ef6eed4c75f449612c76a506ec6c2d7e9676c776f615300230aae0353afc02d80ff377d79a923d2348eec166e0d1b40aa2428a2bf2f87dd89dffd6f1969b39cd84b3d2813078cd4a7753379a79ab6b33f9e8b54a73dde0c46f4fa9afb8a9d0445ae59d202a3df70143baf1de61de9d55681467e343a025b1e0f67af5b1e3e22568d449af192b3e241b6b635e668e851b39e9909ed77ec007a8fba5aec76551e6bb08f454ccf4d48867456c50fdeeaa80f4557d375bda789dc0a5622ccd20d0e2f32e4c7876464f8c8b5393f45eba04085f356927955fe89c475aba7862590656717b5c77f1f79d2a430a2dfb6c779f1794f5f6d374e6e566706f9bfcf33e2070b10af8bc9b853d38215bcb4ad02123445d91b485952514c63a21fac93146a15962fad262c2cdc8ce18a592e4420f60d18ae4ad558b5229b372ed06f021827e932bdb7c43ed6db84ab9c2e408251619bd8b3ce28b9c55c3a21ae2f300758c80086f0ed4a316403195512c2880239f50afa996ce24374ceb25637183b96cf246d204a04018f4344c81aad9cfa98c2ee4f5f6ce3a6f352a86e9a1b07b"}, + } { + t.Run(tc.name, func(t *testing.T) { + mode := ModeByName(tc.name) + if mode == nil { + t.Fatal() + } + + seed := make([]byte, mode.SeedSize()) + _, _ = hex.Decode(seed[:], []byte(tc.seed)) + + m, _ := hex.DecodeString(tc.message) + s, _ := hex.DecodeString(tc.signature) + + pk, _ := mode.NewKeyFromSeed(seed) + + if !mode.Verify(pk, m, s) { + t.Fatal("should verify") + } + }) + } +} + +func TestPQCgenKATSign(t *testing.T) { + for _, tc := range []struct { + name string + want string + }{ + {"MAYO_1", "d0da809f52866507b6354588cd44b712bac138a8363fde768adb92285b6e9865"}, + {"MAYO_2", "e7382b9b0fd985023a53f292b5d5caf444541a5bd531cf6e1e4d35b8bd864123"}, + {"MAYO_3", "0a53ad1ea675f6be7364d37b552cfa7ca254ac315724fb2871c2fe0567f509b9"}, + {"MAYO_5", "26a4bf3204c41fcb9911f761066668da34554efdd0684346b348ccd669f16b56"}, + } { + t.Run(tc.name, func(t *testing.T) { + mode := ModeByName(tc.name) + if mode == nil { + t.Fatal() + } + + var seed [48]byte + eseed := make([]byte, mode.SeedSize()) + for i := 0; i < 48; i++ { + seed[i] = byte(i) + } + f := sha256.New() + g := nist.NewDRBG(&seed) + fmt.Fprintf(f, "# %s\n\n", tc.name) + for i := 0; i < 100; i++ { + mlen := 33 * (i + 1) + _, _ = g.Read(seed[:]) + msg := make([]byte, mlen) + _, _ = g.Read(msg[:]) + + fmt.Fprintf(f, "count = %d\n", i) + fmt.Fprintf(f, "seed = %X\n", seed) + fmt.Fprintf(f, "mlen = %d\n", mlen) + fmt.Fprintf(f, "msg = %X\n", msg) + + g2 := nist.NewDRBG(&seed) + _, _ = g2.Read(eseed[:]) + pk, sk := mode.NewKeyFromSeed(eseed) + + fmt.Fprintf(f, "pk = %X\n", pk.Bytes()) + fmt.Fprintf(f, "sk = %X\n", sk.Bytes()) + fmt.Fprintf(f, "smlen = %d\n", mlen+mode.SignatureSize()) + + sig, err := mode.Sign(sk, msg[:], &g2) + if err != nil { + t.Fatal() + } + + fmt.Fprintf(f, "sm = %X%X\n\n", sig, msg) + + if !mode.Verify(pk, msg[:], sig) { + t.Fatal() + } + } + + if fmt.Sprintf("%x", f.Sum(nil)) != tc.want { + t.Fatal() + } + }) + } +} diff --git a/sign/mayo/mode1.go b/sign/mayo/mode1.go new file mode 100644 index 00000000..3579d4bc --- /dev/null +++ b/sign/mayo/mode1.go @@ -0,0 +1,87 @@ +// Code generated from mode.templ.go. DO NOT EDIT. + +package mayo + +import ( + "fmt" + "io" + + "github.com/cloudflare/circl/sign/mayo/mode1" +) + +// implMode1 implements the mode.Mode interface for MAYO_1. +type implMode1 struct{} + +// Mode1 is MAYO in mode "MAYO_1". +var Mode1 Mode = &implMode1{} + +func (m *implMode1) GenerateKey(rand io.Reader) ( + PublicKey, PrivateKey, error) { + return mode1.GenerateKey(rand) +} + +func (m *implMode1) NewKeyFromSeed(seed []byte) (PublicKey, + PrivateKey) { + if len(seed) != mode1.SeedSize { + panic(fmt.Sprintf("seed must be of length %d", mode1.SeedSize)) + } + seedBuf := [mode1.SeedSize]byte{} + copy(seedBuf[:], seed) + return mode1.NewKeyFromSeed(&seedBuf) +} + +func (m *implMode1) Sign(sk PrivateKey, msg []byte, rand io.Reader) ([]byte, error) { + isk := sk.(*mode1.PrivateKey) + return mode1.Sign(isk, msg, rand) +} + +func (m *implMode1) Verify(pk PublicKey, msg []byte, signature []byte) bool { + ipk := pk.(*mode1.PublicKey) + return mode1.Verify(ipk, msg, signature) +} + +func (m *implMode1) PublicKeyFromBytes(data []byte) PublicKey { + var ret mode1.PublicKey + if len(data) != mode1.PublicKeySize { + panic("packed public key must be of mode1.PublicKeySize bytes") + } + var buf [mode1.PublicKeySize]byte + copy(buf[:], data) + ret.Unpack(&buf) + return &ret +} + +func (m *implMode1) PrivateKeyFromBytes(data []byte) PrivateKey { + var ret mode1.PrivateKey + if len(data) != mode1.PrivateKeySize { + panic("packed public key must be of mode1.PrivateKeySize bytes") + } + var buf [mode1.PrivateKeySize]byte + copy(buf[:], data) + ret.Unpack(&buf) + return &ret +} + +func (m *implMode1) SeedSize() int { + return mode1.SeedSize +} + +func (m *implMode1) PublicKeySize() int { + return mode1.PublicKeySize +} + +func (m *implMode1) PrivateKeySize() int { + return mode1.PrivateKeySize +} + +func (m *implMode1) SignatureSize() int { + return mode1.SignatureSize +} + +func (m *implMode1) Name() string { + return "MAYO_1" +} + +func init() { + modes["MAYO_1"] = Mode1 +} diff --git a/sign/mayo/mode1/internal/mayo.go b/sign/mayo/mode1/internal/mayo.go index 83ab278d..4ca85ffc 100644 --- a/sign/mayo/mode1/internal/mayo.go +++ b/sign/mayo/mode1/internal/mayo.go @@ -149,13 +149,13 @@ func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) { if err != nil { return nil, nil, err } - pk, sk := NewKeyFromSeed(seed) + pk, sk := NewKeyFromSeed(&seed) return pk, sk, nil } -func NewKeyFromSeed(seed [KeySeedSize]byte) (*PublicKey, *PrivateKey) { +func NewKeyFromSeed(seed *[KeySeedSize]byte) (*PublicKey, *PrivateKey) { var sk PrivateKey - sk.Unpack(&seed) + sk.Unpack(seed) return sk.Public(), &sk } diff --git a/sign/mayo/mode1/internal/mayo_test.go b/sign/mayo/mode1/internal/mayo_test.go index 2a94c97b..4529b13b 100644 --- a/sign/mayo/mode1/internal/mayo_test.go +++ b/sign/mayo/mode1/internal/mayo_test.go @@ -28,7 +28,7 @@ func TestNewKey(t *testing.T) { var seed [KeySeedSize]byte _, _ = hex.Decode(seed[:], []byte(tc.seed)) - pk, sk := NewKeyFromSeed(seed) + pk, sk := NewKeyFromSeed(&seed) var pk2 [PublicKeySize]byte var sk2 [PrivateKeySize]byte @@ -68,7 +68,7 @@ func TestVerify(t *testing.T) { m, _ := hex.DecodeString(tc.message) s, _ := hex.DecodeString(tc.signature) - pk, _ := NewKeyFromSeed(seed) + pk, _ := NewKeyFromSeed(&seed) if !Verify(pk, m, s) { t.Fatal("should verify") @@ -144,7 +144,7 @@ func TestPQCgenKATSign(t *testing.T) { g2 := nist.NewDRBG(&seed) _, _ = g2.Read(eseed[:]) - pk, sk := NewKeyFromSeed(eseed) + pk, sk := NewKeyFromSeed(&eseed) var pk2 [PublicKeySize]byte var sk2 [PrivateKeySize]byte @@ -178,7 +178,7 @@ func BenchmarkKeyGen(b *testing.B) { var seed [KeySeedSize]byte for i := 0; i < b.N; i++ { binary.LittleEndian.PutUint64(seed[:], uint64(i)) - _, _ = NewKeyFromSeed(seed) + _, _ = NewKeyFromSeed(&seed) } } @@ -198,7 +198,7 @@ func BenchmarkMatMul(b *testing.B) { func BenchmarkVerify(b *testing.B) { var seed [KeySeedSize]byte var msg [8]byte - pk, sk := NewKeyFromSeed(seed) + pk, sk := NewKeyFromSeed(&seed) sig, _ := Sign(msg[:], sk, nil) b.ResetTimer() for i := 0; i < b.N; i++ { @@ -218,7 +218,7 @@ func (zeroReader) Read(buf []byte) (int, error) { func BenchmarkSign(b *testing.B) { var seed [KeySeedSize]byte var msg [8]byte - _, sk := NewKeyFromSeed(seed) + _, sk := NewKeyFromSeed(&seed) b.ResetTimer() for i := 0; i < b.N; i++ { binary.LittleEndian.PutUint64(msg[:], uint64(i)) diff --git a/sign/mayo/mode1/mayo.go b/sign/mayo/mode1/mayo.go index 4c3b1f89..f67c85ed 100644 --- a/sign/mayo/mode1/mayo.go +++ b/sign/mayo/mode1/mayo.go @@ -50,7 +50,7 @@ func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) { } // NewKeyFromSeed derives a public/private key pair using the given seed. -func NewKeyFromSeed(seed [SeedSize]byte) (*PublicKey, *PrivateKey) { +func NewKeyFromSeed(seed *[SeedSize]byte) (*PublicKey, *PrivateKey) { pk, sk := internal.NewKeyFromSeed(seed) return (*PublicKey)(pk), (*PrivateKey)(sk) } diff --git a/sign/mayo/mode1/signapi.go b/sign/mayo/mode1/signapi.go index ad674f49..069ad959 100644 --- a/sign/mayo/mode1/signapi.go +++ b/sign/mayo/mode1/signapi.go @@ -65,7 +65,7 @@ func (*scheme) DeriveKey(seed []byte) (sign.PublicKey, sign.PrivateKey) { } var tmp [SeedSize]byte copy(tmp[:], seed) - return NewKeyFromSeed(tmp) + return NewKeyFromSeed(&tmp) } func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (sign.PublicKey, error) { diff --git a/sign/mayo/mode2.go b/sign/mayo/mode2.go new file mode 100644 index 00000000..24fb1436 --- /dev/null +++ b/sign/mayo/mode2.go @@ -0,0 +1,87 @@ +// Code generated from mode.templ.go. DO NOT EDIT. + +package mayo + +import ( + "fmt" + "io" + + "github.com/cloudflare/circl/sign/mayo/mode2" +) + +// implMode2 implements the mode.Mode interface for MAYO_2. +type implMode2 struct{} + +// Mode2 is MAYO in mode "MAYO_2". +var Mode2 Mode = &implMode2{} + +func (m *implMode2) GenerateKey(rand io.Reader) ( + PublicKey, PrivateKey, error) { + return mode2.GenerateKey(rand) +} + +func (m *implMode2) NewKeyFromSeed(seed []byte) (PublicKey, + PrivateKey) { + if len(seed) != mode2.SeedSize { + panic(fmt.Sprintf("seed must be of length %d", mode2.SeedSize)) + } + seedBuf := [mode2.SeedSize]byte{} + copy(seedBuf[:], seed) + return mode2.NewKeyFromSeed(&seedBuf) +} + +func (m *implMode2) Sign(sk PrivateKey, msg []byte, rand io.Reader) ([]byte, error) { + isk := sk.(*mode2.PrivateKey) + return mode2.Sign(isk, msg, rand) +} + +func (m *implMode2) Verify(pk PublicKey, msg []byte, signature []byte) bool { + ipk := pk.(*mode2.PublicKey) + return mode2.Verify(ipk, msg, signature) +} + +func (m *implMode2) PublicKeyFromBytes(data []byte) PublicKey { + var ret mode2.PublicKey + if len(data) != mode2.PublicKeySize { + panic("packed public key must be of mode2.PublicKeySize bytes") + } + var buf [mode2.PublicKeySize]byte + copy(buf[:], data) + ret.Unpack(&buf) + return &ret +} + +func (m *implMode2) PrivateKeyFromBytes(data []byte) PrivateKey { + var ret mode2.PrivateKey + if len(data) != mode2.PrivateKeySize { + panic("packed public key must be of mode2.PrivateKeySize bytes") + } + var buf [mode2.PrivateKeySize]byte + copy(buf[:], data) + ret.Unpack(&buf) + return &ret +} + +func (m *implMode2) SeedSize() int { + return mode2.SeedSize +} + +func (m *implMode2) PublicKeySize() int { + return mode2.PublicKeySize +} + +func (m *implMode2) PrivateKeySize() int { + return mode2.PrivateKeySize +} + +func (m *implMode2) SignatureSize() int { + return mode2.SignatureSize +} + +func (m *implMode2) Name() string { + return "MAYO_2" +} + +func init() { + modes["MAYO_2"] = Mode2 +} diff --git a/sign/mayo/mode2/internal/mayo.go b/sign/mayo/mode2/internal/mayo.go index 90359bc9..07226f73 100644 --- a/sign/mayo/mode2/internal/mayo.go +++ b/sign/mayo/mode2/internal/mayo.go @@ -151,13 +151,13 @@ func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) { if err != nil { return nil, nil, err } - pk, sk := NewKeyFromSeed(seed) + pk, sk := NewKeyFromSeed(&seed) return pk, sk, nil } -func NewKeyFromSeed(seed [KeySeedSize]byte) (*PublicKey, *PrivateKey) { +func NewKeyFromSeed(seed *[KeySeedSize]byte) (*PublicKey, *PrivateKey) { var sk PrivateKey - sk.Unpack(&seed) + sk.Unpack(seed) return sk.Public(), &sk } diff --git a/sign/mayo/mode2/internal/mayo_test.go b/sign/mayo/mode2/internal/mayo_test.go index 847949cd..2ebd29fb 100644 --- a/sign/mayo/mode2/internal/mayo_test.go +++ b/sign/mayo/mode2/internal/mayo_test.go @@ -30,7 +30,7 @@ func TestNewKey(t *testing.T) { var seed [KeySeedSize]byte _, _ = hex.Decode(seed[:], []byte(tc.seed)) - pk, sk := NewKeyFromSeed(seed) + pk, sk := NewKeyFromSeed(&seed) var pk2 [PublicKeySize]byte var sk2 [PrivateKeySize]byte @@ -70,7 +70,7 @@ func TestVerify(t *testing.T) { m, _ := hex.DecodeString(tc.message) s, _ := hex.DecodeString(tc.signature) - pk, _ := NewKeyFromSeed(seed) + pk, _ := NewKeyFromSeed(&seed) if !Verify(pk, m, s) { t.Fatal("should verify") @@ -146,7 +146,7 @@ func TestPQCgenKATSign(t *testing.T) { g2 := nist.NewDRBG(&seed) _, _ = g2.Read(eseed[:]) - pk, sk := NewKeyFromSeed(eseed) + pk, sk := NewKeyFromSeed(&eseed) var pk2 [PublicKeySize]byte var sk2 [PrivateKeySize]byte @@ -180,7 +180,7 @@ func BenchmarkKeyGen(b *testing.B) { var seed [KeySeedSize]byte for i := 0; i < b.N; i++ { binary.LittleEndian.PutUint64(seed[:], uint64(i)) - _, _ = NewKeyFromSeed(seed) + _, _ = NewKeyFromSeed(&seed) } } @@ -200,7 +200,7 @@ func BenchmarkMatMul(b *testing.B) { func BenchmarkVerify(b *testing.B) { var seed [KeySeedSize]byte var msg [8]byte - pk, sk := NewKeyFromSeed(seed) + pk, sk := NewKeyFromSeed(&seed) sig, _ := Sign(msg[:], sk, nil) b.ResetTimer() for i := 0; i < b.N; i++ { @@ -220,7 +220,7 @@ func (zeroReader) Read(buf []byte) (int, error) { func BenchmarkSign(b *testing.B) { var seed [KeySeedSize]byte var msg [8]byte - _, sk := NewKeyFromSeed(seed) + _, sk := NewKeyFromSeed(&seed) b.ResetTimer() for i := 0; i < b.N; i++ { binary.LittleEndian.PutUint64(msg[:], uint64(i)) diff --git a/sign/mayo/mode2/mayo.go b/sign/mayo/mode2/mayo.go index c0ddfe66..e25035cd 100644 --- a/sign/mayo/mode2/mayo.go +++ b/sign/mayo/mode2/mayo.go @@ -50,7 +50,7 @@ func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) { } // NewKeyFromSeed derives a public/private key pair using the given seed. -func NewKeyFromSeed(seed [SeedSize]byte) (*PublicKey, *PrivateKey) { +func NewKeyFromSeed(seed *[SeedSize]byte) (*PublicKey, *PrivateKey) { pk, sk := internal.NewKeyFromSeed(seed) return (*PublicKey)(pk), (*PrivateKey)(sk) } diff --git a/sign/mayo/mode2/signapi.go b/sign/mayo/mode2/signapi.go index c13a65cf..08961515 100644 --- a/sign/mayo/mode2/signapi.go +++ b/sign/mayo/mode2/signapi.go @@ -65,7 +65,7 @@ func (*scheme) DeriveKey(seed []byte) (sign.PublicKey, sign.PrivateKey) { } var tmp [SeedSize]byte copy(tmp[:], seed) - return NewKeyFromSeed(tmp) + return NewKeyFromSeed(&tmp) } func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (sign.PublicKey, error) { diff --git a/sign/mayo/mode3.go b/sign/mayo/mode3.go new file mode 100644 index 00000000..4c2db55c --- /dev/null +++ b/sign/mayo/mode3.go @@ -0,0 +1,87 @@ +// Code generated from mode.templ.go. DO NOT EDIT. + +package mayo + +import ( + "fmt" + "io" + + "github.com/cloudflare/circl/sign/mayo/mode3" +) + +// implMode3 implements the mode.Mode interface for MAYO_3. +type implMode3 struct{} + +// Mode3 is MAYO in mode "MAYO_3". +var Mode3 Mode = &implMode3{} + +func (m *implMode3) GenerateKey(rand io.Reader) ( + PublicKey, PrivateKey, error) { + return mode3.GenerateKey(rand) +} + +func (m *implMode3) NewKeyFromSeed(seed []byte) (PublicKey, + PrivateKey) { + if len(seed) != mode3.SeedSize { + panic(fmt.Sprintf("seed must be of length %d", mode3.SeedSize)) + } + seedBuf := [mode3.SeedSize]byte{} + copy(seedBuf[:], seed) + return mode3.NewKeyFromSeed(&seedBuf) +} + +func (m *implMode3) Sign(sk PrivateKey, msg []byte, rand io.Reader) ([]byte, error) { + isk := sk.(*mode3.PrivateKey) + return mode3.Sign(isk, msg, rand) +} + +func (m *implMode3) Verify(pk PublicKey, msg []byte, signature []byte) bool { + ipk := pk.(*mode3.PublicKey) + return mode3.Verify(ipk, msg, signature) +} + +func (m *implMode3) PublicKeyFromBytes(data []byte) PublicKey { + var ret mode3.PublicKey + if len(data) != mode3.PublicKeySize { + panic("packed public key must be of mode3.PublicKeySize bytes") + } + var buf [mode3.PublicKeySize]byte + copy(buf[:], data) + ret.Unpack(&buf) + return &ret +} + +func (m *implMode3) PrivateKeyFromBytes(data []byte) PrivateKey { + var ret mode3.PrivateKey + if len(data) != mode3.PrivateKeySize { + panic("packed public key must be of mode3.PrivateKeySize bytes") + } + var buf [mode3.PrivateKeySize]byte + copy(buf[:], data) + ret.Unpack(&buf) + return &ret +} + +func (m *implMode3) SeedSize() int { + return mode3.SeedSize +} + +func (m *implMode3) PublicKeySize() int { + return mode3.PublicKeySize +} + +func (m *implMode3) PrivateKeySize() int { + return mode3.PrivateKeySize +} + +func (m *implMode3) SignatureSize() int { + return mode3.SignatureSize +} + +func (m *implMode3) Name() string { + return "MAYO_3" +} + +func init() { + modes["MAYO_3"] = Mode3 +} diff --git a/sign/mayo/mode3/internal/mayo.go b/sign/mayo/mode3/internal/mayo.go index 90359bc9..07226f73 100644 --- a/sign/mayo/mode3/internal/mayo.go +++ b/sign/mayo/mode3/internal/mayo.go @@ -151,13 +151,13 @@ func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) { if err != nil { return nil, nil, err } - pk, sk := NewKeyFromSeed(seed) + pk, sk := NewKeyFromSeed(&seed) return pk, sk, nil } -func NewKeyFromSeed(seed [KeySeedSize]byte) (*PublicKey, *PrivateKey) { +func NewKeyFromSeed(seed *[KeySeedSize]byte) (*PublicKey, *PrivateKey) { var sk PrivateKey - sk.Unpack(&seed) + sk.Unpack(seed) return sk.Public(), &sk } diff --git a/sign/mayo/mode3/internal/mayo_test.go b/sign/mayo/mode3/internal/mayo_test.go index 847949cd..2ebd29fb 100644 --- a/sign/mayo/mode3/internal/mayo_test.go +++ b/sign/mayo/mode3/internal/mayo_test.go @@ -30,7 +30,7 @@ func TestNewKey(t *testing.T) { var seed [KeySeedSize]byte _, _ = hex.Decode(seed[:], []byte(tc.seed)) - pk, sk := NewKeyFromSeed(seed) + pk, sk := NewKeyFromSeed(&seed) var pk2 [PublicKeySize]byte var sk2 [PrivateKeySize]byte @@ -70,7 +70,7 @@ func TestVerify(t *testing.T) { m, _ := hex.DecodeString(tc.message) s, _ := hex.DecodeString(tc.signature) - pk, _ := NewKeyFromSeed(seed) + pk, _ := NewKeyFromSeed(&seed) if !Verify(pk, m, s) { t.Fatal("should verify") @@ -146,7 +146,7 @@ func TestPQCgenKATSign(t *testing.T) { g2 := nist.NewDRBG(&seed) _, _ = g2.Read(eseed[:]) - pk, sk := NewKeyFromSeed(eseed) + pk, sk := NewKeyFromSeed(&eseed) var pk2 [PublicKeySize]byte var sk2 [PrivateKeySize]byte @@ -180,7 +180,7 @@ func BenchmarkKeyGen(b *testing.B) { var seed [KeySeedSize]byte for i := 0; i < b.N; i++ { binary.LittleEndian.PutUint64(seed[:], uint64(i)) - _, _ = NewKeyFromSeed(seed) + _, _ = NewKeyFromSeed(&seed) } } @@ -200,7 +200,7 @@ func BenchmarkMatMul(b *testing.B) { func BenchmarkVerify(b *testing.B) { var seed [KeySeedSize]byte var msg [8]byte - pk, sk := NewKeyFromSeed(seed) + pk, sk := NewKeyFromSeed(&seed) sig, _ := Sign(msg[:], sk, nil) b.ResetTimer() for i := 0; i < b.N; i++ { @@ -220,7 +220,7 @@ func (zeroReader) Read(buf []byte) (int, error) { func BenchmarkSign(b *testing.B) { var seed [KeySeedSize]byte var msg [8]byte - _, sk := NewKeyFromSeed(seed) + _, sk := NewKeyFromSeed(&seed) b.ResetTimer() for i := 0; i < b.N; i++ { binary.LittleEndian.PutUint64(msg[:], uint64(i)) diff --git a/sign/mayo/mode3/mayo.go b/sign/mayo/mode3/mayo.go index 5fe33121..7069821d 100644 --- a/sign/mayo/mode3/mayo.go +++ b/sign/mayo/mode3/mayo.go @@ -50,7 +50,7 @@ func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) { } // NewKeyFromSeed derives a public/private key pair using the given seed. -func NewKeyFromSeed(seed [SeedSize]byte) (*PublicKey, *PrivateKey) { +func NewKeyFromSeed(seed *[SeedSize]byte) (*PublicKey, *PrivateKey) { pk, sk := internal.NewKeyFromSeed(seed) return (*PublicKey)(pk), (*PrivateKey)(sk) } diff --git a/sign/mayo/mode3/signapi.go b/sign/mayo/mode3/signapi.go index e8b13a47..56163b64 100644 --- a/sign/mayo/mode3/signapi.go +++ b/sign/mayo/mode3/signapi.go @@ -65,7 +65,7 @@ func (*scheme) DeriveKey(seed []byte) (sign.PublicKey, sign.PrivateKey) { } var tmp [SeedSize]byte copy(tmp[:], seed) - return NewKeyFromSeed(tmp) + return NewKeyFromSeed(&tmp) } func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (sign.PublicKey, error) { diff --git a/sign/mayo/mode5.go b/sign/mayo/mode5.go new file mode 100644 index 00000000..cd963714 --- /dev/null +++ b/sign/mayo/mode5.go @@ -0,0 +1,87 @@ +// Code generated from mode.templ.go. DO NOT EDIT. + +package mayo + +import ( + "fmt" + "io" + + "github.com/cloudflare/circl/sign/mayo/mode5" +) + +// implMode5 implements the mode.Mode interface for MAYO_5. +type implMode5 struct{} + +// Mode5 is MAYO in mode "MAYO_5". +var Mode5 Mode = &implMode5{} + +func (m *implMode5) GenerateKey(rand io.Reader) ( + PublicKey, PrivateKey, error) { + return mode5.GenerateKey(rand) +} + +func (m *implMode5) NewKeyFromSeed(seed []byte) (PublicKey, + PrivateKey) { + if len(seed) != mode5.SeedSize { + panic(fmt.Sprintf("seed must be of length %d", mode5.SeedSize)) + } + seedBuf := [mode5.SeedSize]byte{} + copy(seedBuf[:], seed) + return mode5.NewKeyFromSeed(&seedBuf) +} + +func (m *implMode5) Sign(sk PrivateKey, msg []byte, rand io.Reader) ([]byte, error) { + isk := sk.(*mode5.PrivateKey) + return mode5.Sign(isk, msg, rand) +} + +func (m *implMode5) Verify(pk PublicKey, msg []byte, signature []byte) bool { + ipk := pk.(*mode5.PublicKey) + return mode5.Verify(ipk, msg, signature) +} + +func (m *implMode5) PublicKeyFromBytes(data []byte) PublicKey { + var ret mode5.PublicKey + if len(data) != mode5.PublicKeySize { + panic("packed public key must be of mode5.PublicKeySize bytes") + } + var buf [mode5.PublicKeySize]byte + copy(buf[:], data) + ret.Unpack(&buf) + return &ret +} + +func (m *implMode5) PrivateKeyFromBytes(data []byte) PrivateKey { + var ret mode5.PrivateKey + if len(data) != mode5.PrivateKeySize { + panic("packed public key must be of mode5.PrivateKeySize bytes") + } + var buf [mode5.PrivateKeySize]byte + copy(buf[:], data) + ret.Unpack(&buf) + return &ret +} + +func (m *implMode5) SeedSize() int { + return mode5.SeedSize +} + +func (m *implMode5) PublicKeySize() int { + return mode5.PublicKeySize +} + +func (m *implMode5) PrivateKeySize() int { + return mode5.PrivateKeySize +} + +func (m *implMode5) SignatureSize() int { + return mode5.SignatureSize +} + +func (m *implMode5) Name() string { + return "MAYO_5" +} + +func init() { + modes["MAYO_5"] = Mode5 +} diff --git a/sign/mayo/mode5/internal/mayo.go b/sign/mayo/mode5/internal/mayo.go index 90359bc9..07226f73 100644 --- a/sign/mayo/mode5/internal/mayo.go +++ b/sign/mayo/mode5/internal/mayo.go @@ -151,13 +151,13 @@ func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) { if err != nil { return nil, nil, err } - pk, sk := NewKeyFromSeed(seed) + pk, sk := NewKeyFromSeed(&seed) return pk, sk, nil } -func NewKeyFromSeed(seed [KeySeedSize]byte) (*PublicKey, *PrivateKey) { +func NewKeyFromSeed(seed *[KeySeedSize]byte) (*PublicKey, *PrivateKey) { var sk PrivateKey - sk.Unpack(&seed) + sk.Unpack(seed) return sk.Public(), &sk } diff --git a/sign/mayo/mode5/internal/mayo_test.go b/sign/mayo/mode5/internal/mayo_test.go index 847949cd..2ebd29fb 100644 --- a/sign/mayo/mode5/internal/mayo_test.go +++ b/sign/mayo/mode5/internal/mayo_test.go @@ -30,7 +30,7 @@ func TestNewKey(t *testing.T) { var seed [KeySeedSize]byte _, _ = hex.Decode(seed[:], []byte(tc.seed)) - pk, sk := NewKeyFromSeed(seed) + pk, sk := NewKeyFromSeed(&seed) var pk2 [PublicKeySize]byte var sk2 [PrivateKeySize]byte @@ -70,7 +70,7 @@ func TestVerify(t *testing.T) { m, _ := hex.DecodeString(tc.message) s, _ := hex.DecodeString(tc.signature) - pk, _ := NewKeyFromSeed(seed) + pk, _ := NewKeyFromSeed(&seed) if !Verify(pk, m, s) { t.Fatal("should verify") @@ -146,7 +146,7 @@ func TestPQCgenKATSign(t *testing.T) { g2 := nist.NewDRBG(&seed) _, _ = g2.Read(eseed[:]) - pk, sk := NewKeyFromSeed(eseed) + pk, sk := NewKeyFromSeed(&eseed) var pk2 [PublicKeySize]byte var sk2 [PrivateKeySize]byte @@ -180,7 +180,7 @@ func BenchmarkKeyGen(b *testing.B) { var seed [KeySeedSize]byte for i := 0; i < b.N; i++ { binary.LittleEndian.PutUint64(seed[:], uint64(i)) - _, _ = NewKeyFromSeed(seed) + _, _ = NewKeyFromSeed(&seed) } } @@ -200,7 +200,7 @@ func BenchmarkMatMul(b *testing.B) { func BenchmarkVerify(b *testing.B) { var seed [KeySeedSize]byte var msg [8]byte - pk, sk := NewKeyFromSeed(seed) + pk, sk := NewKeyFromSeed(&seed) sig, _ := Sign(msg[:], sk, nil) b.ResetTimer() for i := 0; i < b.N; i++ { @@ -220,7 +220,7 @@ func (zeroReader) Read(buf []byte) (int, error) { func BenchmarkSign(b *testing.B) { var seed [KeySeedSize]byte var msg [8]byte - _, sk := NewKeyFromSeed(seed) + _, sk := NewKeyFromSeed(&seed) b.ResetTimer() for i := 0; i < b.N; i++ { binary.LittleEndian.PutUint64(msg[:], uint64(i)) diff --git a/sign/mayo/mode5/mayo.go b/sign/mayo/mode5/mayo.go index c6caa73b..61b9dcb3 100644 --- a/sign/mayo/mode5/mayo.go +++ b/sign/mayo/mode5/mayo.go @@ -50,7 +50,7 @@ func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) { } // NewKeyFromSeed derives a public/private key pair using the given seed. -func NewKeyFromSeed(seed [SeedSize]byte) (*PublicKey, *PrivateKey) { +func NewKeyFromSeed(seed *[SeedSize]byte) (*PublicKey, *PrivateKey) { pk, sk := internal.NewKeyFromSeed(seed) return (*PublicKey)(pk), (*PrivateKey)(sk) } diff --git a/sign/mayo/mode5/signapi.go b/sign/mayo/mode5/signapi.go index 86479496..5bae4dfe 100644 --- a/sign/mayo/mode5/signapi.go +++ b/sign/mayo/mode5/signapi.go @@ -65,7 +65,7 @@ func (*scheme) DeriveKey(seed []byte) (sign.PublicKey, sign.PrivateKey) { } var tmp [SeedSize]byte copy(tmp[:], seed) - return NewKeyFromSeed(tmp) + return NewKeyFromSeed(&tmp) } func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (sign.PublicKey, error) { diff --git a/sign/mayo/templates/mode.templ.go b/sign/mayo/templates/mode.templ.go new file mode 100644 index 00000000..3fc4319e --- /dev/null +++ b/sign/mayo/templates/mode.templ.go @@ -0,0 +1,91 @@ +// +build ignore +// The previous line (and this one up to the warning below) is removed by the +// template generator. + +// Code generated from mode.templ.go. DO NOT EDIT. + +package mayo + +import ( + "fmt" + "io" + + "github.com/cloudflare/circl/sign/mayo/{{.Pkg}}" +) + +// {{.Impl}} implements the mode.Mode interface for {{.Name}}. +type {{.Impl}} struct{} + +// {{.Mode}} is MAYO in mode "{{.Name}}". +var {{.Mode}} Mode = &{{.Impl}}{} + +func (m *{{.Impl}}) GenerateKey(rand io.Reader) ( + PublicKey, PrivateKey, error) { + return {{.Pkg}}.GenerateKey(rand) +} + +func (m *{{.Impl}}) NewKeyFromSeed(seed []byte) (PublicKey, + PrivateKey) { + if len(seed) != {{.Pkg}}.SeedSize { + panic(fmt.Sprintf("seed must be of length %d", {{.Pkg}}.SeedSize)) + } + seedBuf := [{{.Pkg}}.SeedSize]byte{} + copy(seedBuf[:], seed) + return {{.Pkg}}.NewKeyFromSeed(&seedBuf) +} + +func (m *{{.Impl}}) Sign(sk PrivateKey, msg []byte, rand io.Reader) ([]byte, error) { + isk := sk.(*{{.Pkg}}.PrivateKey) + return {{.Pkg}}.Sign(isk, msg, rand) +} + +func (m *{{.Impl}}) Verify(pk PublicKey, msg []byte, signature []byte) bool { + ipk := pk.(*{{.Pkg}}.PublicKey) + return {{.Pkg}}.Verify(ipk, msg, signature) +} + +func (m *{{.Impl}}) PublicKeyFromBytes(data []byte) PublicKey { + var ret {{.Pkg}}.PublicKey + if len(data) != {{.Pkg}}.PublicKeySize { + panic("packed public key must be of {{.Pkg}}.PublicKeySize bytes") + } + var buf [{{.Pkg}}.PublicKeySize]byte + copy(buf[:], data) + ret.Unpack(&buf) + return &ret +} + +func (m *{{.Impl}}) PrivateKeyFromBytes(data []byte) PrivateKey { + var ret {{.Pkg}}.PrivateKey + if len(data) != {{.Pkg}}.PrivateKeySize { + panic("packed public key must be of {{.Pkg}}.PrivateKeySize bytes") + } + var buf [{{.Pkg}}.PrivateKeySize]byte + copy(buf[:], data) + ret.Unpack(&buf) + return &ret +} + +func (m *{{.Impl}}) SeedSize() int { + return {{.Pkg}}.SeedSize +} + +func (m *{{.Impl}}) PublicKeySize() int { + return {{.Pkg}}.PublicKeySize +} + +func (m *{{.Impl}}) PrivateKeySize() int { + return {{.Pkg}}.PrivateKeySize +} + +func (m *{{.Impl}}) SignatureSize() int { + return {{.Pkg}}.SignatureSize +} + +func (m *{{.Impl}}) Name() string { + return "{{.Name}}" +} + +func init() { + modes["{{.Name}}"] = {{.Mode}} +} diff --git a/sign/mayo/templates/modePkg.templ.go b/sign/mayo/templates/modePkg.templ.go index 1fb5e743..28a49205 100644 --- a/sign/mayo/templates/modePkg.templ.go +++ b/sign/mayo/templates/modePkg.templ.go @@ -54,7 +54,7 @@ func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) { } // NewKeyFromSeed derives a public/private key pair using the given seed. -func NewKeyFromSeed(seed [SeedSize]byte) (*PublicKey, *PrivateKey) { +func NewKeyFromSeed(seed *[SeedSize]byte) (*PublicKey, *PrivateKey) { pk, sk := internal.NewKeyFromSeed(seed) return (*PublicKey)(pk), (*PrivateKey)(sk) } diff --git a/sign/mayo/templates/signapi.templ.go b/sign/mayo/templates/signapi.templ.go index 0bd50bdd..b996b05e 100644 --- a/sign/mayo/templates/signapi.templ.go +++ b/sign/mayo/templates/signapi.templ.go @@ -69,7 +69,7 @@ func (*scheme) DeriveKey(seed []byte) (sign.PublicKey, sign.PrivateKey) { } var tmp [SeedSize]byte copy(tmp[:], seed) - return NewKeyFromSeed(tmp) + return NewKeyFromSeed(&tmp) } func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (sign.PublicKey, error) {