forked from jshiffer/matterbridge
Update dependencies (#975)
This commit is contained in:
parent
b9354de8fd
commit
0f708daf2d
22
go.mod
22
go.mod
@ -5,25 +5,22 @@ require (
|
|||||||
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f
|
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f
|
||||||
github.com/Jeffail/gabs v1.1.1 // indirect
|
github.com/Jeffail/gabs v1.1.1 // indirect
|
||||||
github.com/Philipp15b/go-steam v1.0.1-0.20190816133340-b04c5a83c1c0
|
github.com/Philipp15b/go-steam v1.0.1-0.20190816133340-b04c5a83c1c0
|
||||||
github.com/Rhymen/go-whatsapp v0.0.3-0.20191003184814-fc3f792c814c
|
github.com/Rhymen/go-whatsapp v0.1.0
|
||||||
github.com/bwmarrin/discordgo v0.19.0
|
github.com/bwmarrin/discordgo v0.20.2
|
||||||
// github.com/bwmarrin/discordgo v0.19.0
|
|
||||||
github.com/d5/tengo v1.24.8
|
github.com/d5/tengo v1.24.8
|
||||||
github.com/dfordsoft/golib v0.0.0-20180902042739-76ee6ab99bec
|
github.com/dfordsoft/golib v0.0.0-20180902042739-76ee6ab99bec
|
||||||
github.com/fsnotify/fsnotify v1.4.7
|
github.com/fsnotify/fsnotify v1.4.7
|
||||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.5-0.20181225215658-ec221ba9ea45+incompatible
|
github.com/go-telegram-bot-api/telegram-bot-api v4.6.5-0.20181225215658-ec221ba9ea45+incompatible
|
||||||
github.com/gomarkdown/markdown v0.0.0-20190912180731-281270bc6d83
|
github.com/gomarkdown/markdown v0.0.0-20200105192015-0948ad373b2c
|
||||||
github.com/google/gops v0.3.6
|
github.com/google/gops v0.3.6
|
||||||
github.com/gopackage/ddp v0.0.0-20170117053602-652027933df4 // indirect
|
github.com/gopackage/ddp v0.0.0-20170117053602-652027933df4 // indirect
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20180628210949-0892b62f0d9f // indirect
|
|
||||||
github.com/gorilla/schema v1.1.0
|
github.com/gorilla/schema v1.1.0
|
||||||
github.com/gorilla/websocket v1.4.1
|
github.com/gorilla/websocket v1.4.1
|
||||||
github.com/hashicorp/golang-lru v0.5.3
|
github.com/hashicorp/golang-lru v0.5.3
|
||||||
github.com/hpcloud/tail v1.0.0 // indirect
|
github.com/hpcloud/tail v1.0.0 // indirect
|
||||||
github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7
|
github.com/jpillora/backoff v1.0.0
|
||||||
github.com/jtolds/gls v4.2.1+incompatible // indirect
|
|
||||||
github.com/keybase/go-keybase-chat-bot v0.0.0-20190816161829-561f10822eb2
|
github.com/keybase/go-keybase-chat-bot v0.0.0-20190816161829-561f10822eb2
|
||||||
github.com/labstack/echo/v4 v4.1.10
|
github.com/labstack/echo/v4 v4.1.13
|
||||||
github.com/lrstanley/girc v0.0.0-20190801035559-4fc93959e1a7
|
github.com/lrstanley/girc v0.0.0-20190801035559-4fc93959e1a7
|
||||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20190210153444-cc9d05784d5d
|
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20190210153444-cc9d05784d5d
|
||||||
github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible
|
github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible
|
||||||
@ -38,7 +35,6 @@ require (
|
|||||||
github.com/nelsonken/gomf v0.0.0-20180504123937-a9dd2f9deae9
|
github.com/nelsonken/gomf v0.0.0-20180504123937-a9dd2f9deae9
|
||||||
github.com/nicksnyder/go-i18n v1.4.0 // indirect
|
github.com/nicksnyder/go-i18n v1.4.0 // indirect
|
||||||
github.com/nlopes/slack v0.6.0
|
github.com/nlopes/slack v0.6.0
|
||||||
//github.com/nlopes/slack v0.6.0
|
|
||||||
github.com/onsi/ginkgo v1.6.0 // indirect
|
github.com/onsi/ginkgo v1.6.0 // indirect
|
||||||
github.com/onsi/gomega v1.4.1 // indirect
|
github.com/onsi/gomega v1.4.1 // indirect
|
||||||
github.com/paulrosania/go-charset v0.0.0-20190326053356-55c9d7a5834c
|
github.com/paulrosania/go-charset v0.0.0-20190326053356-55c9d7a5834c
|
||||||
@ -48,14 +44,12 @@ require (
|
|||||||
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca
|
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca
|
||||||
github.com/shazow/ssh-chat v1.8.2
|
github.com/shazow/ssh-chat v1.8.2
|
||||||
github.com/sirupsen/logrus v1.4.2
|
github.com/sirupsen/logrus v1.4.2
|
||||||
github.com/smartystreets/assertions v0.0.0-20180803164922-886ec427f6b9 // indirect
|
github.com/spf13/viper v1.6.1
|
||||||
github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a // indirect
|
|
||||||
github.com/spf13/viper v1.4.0
|
|
||||||
github.com/stretchr/testify v1.4.0
|
github.com/stretchr/testify v1.4.0
|
||||||
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
|
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
|
||||||
github.com/x-cray/logrus-prefixed-formatter v0.5.2 // indirect
|
github.com/x-cray/logrus-prefixed-formatter v0.5.2 // indirect
|
||||||
github.com/zfjagann/golang-ring v0.0.0-20190106091943-a88bb6aef447
|
github.com/zfjagann/golang-ring v0.0.0-20190106091943-a88bb6aef447
|
||||||
golang.org/x/image v0.0.0-20190220214146-31aff87c08e9
|
golang.org/x/image v0.0.0-20191214001246-9130b4cfad52
|
||||||
gopkg.in/fsnotify.v1 v1.4.7 // indirect
|
gopkg.in/fsnotify.v1 v1.4.7 // indirect
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||||
@ -63,6 +57,6 @@ require (
|
|||||||
|
|
||||||
replace github.com/nlopes/slack v0.6.0 => github.com/matterbridge/slack v0.1.1-0.20191208194820-95190f11bfb6
|
replace github.com/nlopes/slack v0.6.0 => github.com/matterbridge/slack v0.1.1-0.20191208194820-95190f11bfb6
|
||||||
|
|
||||||
replace github.com/bwmarrin/discordgo v0.19.0 => github.com/matterbridge/discordgo v0.0.0-20191026232317-01823f4ebba4
|
replace github.com/bwmarrin/discordgo v0.20.2 => github.com/matterbridge/discordgo v0.18.1-0.20200109173909-ed873362fa43
|
||||||
|
|
||||||
go 1.13
|
go 1.13
|
||||||
|
76
go.sum
76
go.sum
@ -11,8 +11,8 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE
|
|||||||
github.com/Philipp15b/go-steam v1.0.1-0.20190816133340-b04c5a83c1c0 h1:TO7d4rocnNFng6ZQrPe7U6WqHtK5eHEMrgrnnM/72IQ=
|
github.com/Philipp15b/go-steam v1.0.1-0.20190816133340-b04c5a83c1c0 h1:TO7d4rocnNFng6ZQrPe7U6WqHtK5eHEMrgrnnM/72IQ=
|
||||||
github.com/Philipp15b/go-steam v1.0.1-0.20190816133340-b04c5a83c1c0/go.mod h1:HuVM+sZFzumUdKPWiz+IlCMb4RdsKdT3T+nQBKL+sYg=
|
github.com/Philipp15b/go-steam v1.0.1-0.20190816133340-b04c5a83c1c0/go.mod h1:HuVM+sZFzumUdKPWiz+IlCMb4RdsKdT3T+nQBKL+sYg=
|
||||||
github.com/Rhymen/go-whatsapp v0.0.0/go.mod h1:rdQr95g2C1xcOfM7QGOhza58HeI3I+tZ/bbluv7VazA=
|
github.com/Rhymen/go-whatsapp v0.0.0/go.mod h1:rdQr95g2C1xcOfM7QGOhza58HeI3I+tZ/bbluv7VazA=
|
||||||
github.com/Rhymen/go-whatsapp v0.0.3-0.20191003184814-fc3f792c814c h1:+yAllLxP+WjpuVVE1WNm0/Oigbeob9+liYEyk/v4nj8=
|
github.com/Rhymen/go-whatsapp v0.1.0 h1:XTXhFIQ/fx9jKObUnUX2Q+nh58EyeHNhX7DniE8xeuA=
|
||||||
github.com/Rhymen/go-whatsapp v0.0.3-0.20191003184814-fc3f792c814c/go.mod h1:qf/2PQi82Okxw/igghu/oMGzTeUYuKBq1JNo3tdQyNg=
|
github.com/Rhymen/go-whatsapp v0.1.0/go.mod h1:xJSy+okeRjKkQEH/lEYrnekXB3PG33fqL0I6ncAkV50=
|
||||||
github.com/Rhymen/go-whatsapp/examples/echo v0.0.0-20190325075644-cc2581bbf24d/go.mod h1:zgCiQtBtZ4P4gFWvwl9aashsdwOcbb/EHOGRmSzM8ME=
|
github.com/Rhymen/go-whatsapp/examples/echo v0.0.0-20190325075644-cc2581bbf24d/go.mod h1:zgCiQtBtZ4P4gFWvwl9aashsdwOcbb/EHOGRmSzM8ME=
|
||||||
github.com/Rhymen/go-whatsapp/examples/restoreSession v0.0.0-20190325075644-cc2581bbf24d/go.mod h1:5sCUSpG616ZoSJhlt9iBNI/KXBqrVLcNUJqg7J9+8pU=
|
github.com/Rhymen/go-whatsapp/examples/restoreSession v0.0.0-20190325075644-cc2581bbf24d/go.mod h1:5sCUSpG616ZoSJhlt9iBNI/KXBqrVLcNUJqg7J9+8pU=
|
||||||
github.com/Rhymen/go-whatsapp/examples/sendImage v0.0.0-20190325075644-cc2581bbf24d/go.mod h1:RdiyhanVEGXTam+mZ3k6Y3VDCCvXYCwReOoxGozqhHw=
|
github.com/Rhymen/go-whatsapp/examples/sendImage v0.0.0-20190325075644-cc2581bbf24d/go.mod h1:RdiyhanVEGXTam+mZ3k6Y3VDCCvXYCwReOoxGozqhHw=
|
||||||
@ -64,16 +64,16 @@ github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk
|
|||||||
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
|
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
|
||||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/gomarkdown/markdown v0.0.0-20190912180731-281270bc6d83 h1:w5VNUHB0SP2tr1+boQJWKvnyn3P61UFErZ2e2ih6x0A=
|
github.com/gomarkdown/markdown v0.0.0-20200105192015-0948ad373b2c h1:YQi5cVUn3bbQSS7fadb1G9LLp+sqYk5bQEw+VYes7MQ=
|
||||||
github.com/gomarkdown/markdown v0.0.0-20190912180731-281270bc6d83/go.mod h1:aii0r/K0ZnHv7G0KF7xy1v0A7s2Ljrb5byB7MO5p6TU=
|
github.com/gomarkdown/markdown v0.0.0-20200105192015-0948ad373b2c/go.mod h1:aii0r/K0ZnHv7G0KF7xy1v0A7s2Ljrb5byB7MO5p6TU=
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/gops v0.3.6 h1:6akvbMlpZrEYOuoebn2kR+ZJekbZqJ28fJXTs84+8to=
|
github.com/google/gops v0.3.6 h1:6akvbMlpZrEYOuoebn2kR+ZJekbZqJ28fJXTs84+8to=
|
||||||
github.com/google/gops v0.3.6/go.mod h1:RZ1rH95wsAGX4vMWKmqBOIWynmWisBf4QFdgT/k/xOI=
|
github.com/google/gops v0.3.6/go.mod h1:RZ1rH95wsAGX4vMWKmqBOIWynmWisBf4QFdgT/k/xOI=
|
||||||
github.com/gopackage/ddp v0.0.0-20170117053602-652027933df4 h1:4EZlYQIiyecYJlUbVkFXCXHz1QPhVXcHnQKAzBTPfQo=
|
github.com/gopackage/ddp v0.0.0-20170117053602-652027933df4 h1:4EZlYQIiyecYJlUbVkFXCXHz1QPhVXcHnQKAzBTPfQo=
|
||||||
github.com/gopackage/ddp v0.0.0-20170117053602-652027933df4/go.mod h1:lEO7XoHJ/xNRBCxrn4h/CEB67h0kW1B0t4ooP2yrjUA=
|
github.com/gopackage/ddp v0.0.0-20170117053602-652027933df4/go.mod h1:lEO7XoHJ/xNRBCxrn4h/CEB67h0kW1B0t4ooP2yrjUA=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20180628210949-0892b62f0d9f h1:FDM3EtwZLyhW48YRiyqjivNlNZjAObv4xt4NnJaU+NQ=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20180628210949-0892b62f0d9f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY=
|
github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY=
|
||||||
github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
|
github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
|
||||||
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
@ -93,10 +93,10 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
|||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7 h1:K//n/AqR5HjG3qxbrBCL4vJPW0MVFSs9CPK1OOJdRME=
|
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
|
||||||
github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0=
|
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||||
github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE=
|
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||||
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1 h1:PJPDf8OUfOK1bb/NeTKd4f1QXZItOX389VN3B6qC8ro=
|
github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1 h1:PJPDf8OUfOK1bb/NeTKd4f1QXZItOX389VN3B6qC8ro=
|
||||||
github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
|
github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
|
||||||
@ -114,18 +114,20 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
|||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/labstack/echo/v4 v4.1.10 h1:/yhIpO50CBInUbE/nHJtGIyhBv0dJe2cDAYxc3V3uMo=
|
github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=
|
||||||
github.com/labstack/echo/v4 v4.1.10/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
|
github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
|
||||||
|
github.com/labstack/echo/v4 v4.1.13 h1:JYgKq6NQQSaKbQcsOadAKX1kUVLCUzLGwu8sxN5tC34=
|
||||||
|
github.com/labstack/echo/v4 v4.1.13/go.mod h1:3WZNypykZ3tnqpF2Qb4fPg27XDunFqgP3HGDmCMgv7U=
|
||||||
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
|
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
|
||||||
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
||||||
github.com/lrstanley/girc v0.0.0-20190801035559-4fc93959e1a7 h1:BS9tqL0OCiOGuy/CYYk2gc33fxqaqh5/rhqMKu4tcYA=
|
github.com/lrstanley/girc v0.0.0-20190801035559-4fc93959e1a7 h1:BS9tqL0OCiOGuy/CYYk2gc33fxqaqh5/rhqMKu4tcYA=
|
||||||
github.com/lrstanley/girc v0.0.0-20190801035559-4fc93959e1a7/go.mod h1:liX5MxHPrwgHaKowoLkYGwbXfYABh1jbZ6FpElbGF1I=
|
github.com/lrstanley/girc v0.0.0-20190801035559-4fc93959e1a7/go.mod h1:liX5MxHPrwgHaKowoLkYGwbXfYABh1jbZ6FpElbGF1I=
|
||||||
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
|
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20190210153444-cc9d05784d5d h1:F+Sr+C0ojSlYQ37BLylQtSFmyQULe3jbAygcyXQ9mVs=
|
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20190210153444-cc9d05784d5d h1:F+Sr+C0ojSlYQ37BLylQtSFmyQULe3jbAygcyXQ9mVs=
|
||||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20190210153444-cc9d05784d5d/go.mod h1:c6MxwqHD+0HvtAJjsHMIdPCiAwGiQwPRPTp69ACMg8A=
|
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20190210153444-cc9d05784d5d/go.mod h1:c6MxwqHD+0HvtAJjsHMIdPCiAwGiQwPRPTp69ACMg8A=
|
||||||
github.com/matterbridge/discordgo v0.0.0-20191026232317-01823f4ebba4 h1:RvH3lC4bEp+bieca+Yh5xPU8tLJgnk7ridiSwMFHrrw=
|
github.com/matterbridge/discordgo v0.18.1-0.20200109173909-ed873362fa43 h1:xTcLiEPMp9jVh/lHEPpLc87RZ4sRWRZe0rM578/waOk=
|
||||||
github.com/matterbridge/discordgo v0.0.0-20191026232317-01823f4ebba4/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q=
|
github.com/matterbridge/discordgo v0.18.1-0.20200109173909-ed873362fa43/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q=
|
||||||
github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible h1:oaOqwbg5HxHRxvAbd84ks0Okwoc1ISyUZ87EiVJFhGI=
|
github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible h1:oaOqwbg5HxHRxvAbd84ks0Okwoc1ISyUZ87EiVJFhGI=
|
||||||
github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible/go.mod h1:igE6rUAn3jai2wCdsjFHfhUoekjrFthoEjFObKKwSb4=
|
github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible/go.mod h1:igE6rUAn3jai2wCdsjFHfhUoekjrFthoEjFObKKwSb4=
|
||||||
github.com/matterbridge/go-xmpp v0.0.0-20180529212104-cd19799fba91 h1:KzDEcy8eDbTx881giW8a6llsAck3e2bJvMyKvh1IK+k=
|
github.com/matterbridge/go-xmpp v0.0.0-20180529212104-cd19799fba91 h1:KzDEcy8eDbTx881giW8a6llsAck3e2bJvMyKvh1IK+k=
|
||||||
@ -144,12 +146,16 @@ github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0X
|
|||||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||||
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
|
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
|
||||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
|
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
||||||
|
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw=
|
github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw=
|
||||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
|
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
|
||||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
|
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
|
||||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||||
|
github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM=
|
||||||
|
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
||||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||||
@ -209,10 +215,10 @@ github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4
|
|||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9 h1:lpEzuenPuO1XNTeikEmvqYFcU37GVLl8SRNblzyvGBE=
|
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9 h1:lpEzuenPuO1XNTeikEmvqYFcU37GVLl8SRNblzyvGBE=
|
||||||
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9/go.mod h1:PLPIyL7ikehBD1OAjmKKiOEhbvWyHGaNDjquXMcYABo=
|
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9/go.mod h1:PLPIyL7ikehBD1OAjmKKiOEhbvWyHGaNDjquXMcYABo=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180803164922-886ec427f6b9 h1:lXQ+j+KwZcbwrbgU0Rp4Eglg3EJLHbuZU3BbOqAGBmg=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180803164922-886ec427f6b9/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a h1:JSvGDIbmil4Ui/dDdFBExb7/cmkNjyX5F97oglmvCDo=
|
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||||
github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
|
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
|
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
|
||||||
@ -223,13 +229,16 @@ github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9
|
|||||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
|
github.com/spf13/viper v1.6.1 h1:VPZzIkznI1YhVMRi6vNFLHSwhnhReBfgTxIPccpfdZk=
|
||||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
github.com/spf13/viper v1.6.1/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||||
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
|
github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
|
||||||
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
|
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
@ -238,6 +247,8 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw
|
|||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8=
|
github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8=
|
||||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||||
|
github.com/valyala/fasttemplate v1.1.0 h1:RZqt0yGBsps8NGvLSGW804QQqCUYYLsaOjTVHy1Ocw4=
|
||||||
|
github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||||
github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg=
|
github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg=
|
||||||
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
|
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
@ -260,10 +271,10 @@ golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613/go.mod h1:6SG95UA2DQfeDnf
|
|||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
|
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876 h1:sKJQZMuxjOAR/Uo2LBfU90onWEf1dF4C+0hPJCc9Mpc=
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/image v0.0.0-20190220214146-31aff87c08e9 h1:+vH8qNweCrORN49012OX3h0oWEXO3p+rRnpAGQinddk=
|
golang.org/x/image v0.0.0-20191214001246-9130b4cfad52 h1:2fktqPPvDiVEEVT/vSTeoUPXfmRxRaGy6GU8jypvEn0=
|
||||||
golang.org/x/image v0.0.0-20190220214146-31aff87c08e9/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20191214001246-9130b4cfad52/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@ -274,6 +285,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco=
|
golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco=
|
||||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
|
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
|
||||||
|
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@ -291,12 +304,19 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
|
||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8 h1:JA8d3MPx/IToSyXZG/RhwYEtfrKO1Fxrqe8KrkiLXKM=
|
||||||
|
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
@ -308,6 +328,8 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33
|
|||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
|
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
|
||||||
|
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||||
@ -317,6 +339,8 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl
|
|||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||||
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
rsc.io/goversion v1.0.0 h1:/IhXBiai89TyuerPquiZZ39IQkTfAUbZB2awsyYZ/2c=
|
rsc.io/goversion v1.0.0 h1:/IhXBiai89TyuerPquiZZ39IQkTfAUbZB2awsyYZ/2c=
|
||||||
rsc.io/goversion v1.0.0/go.mod h1:Eih9y/uIBS3ulggl7KNJ09xGSLcuNaLgmvvqa07sgfo=
|
rsc.io/goversion v1.0.0/go.mod h1:Eih9y/uIBS3ulggl7KNJ09xGSLcuNaLgmvvqa07sgfo=
|
||||||
|
21
vendor/github.com/Rhymen/go-whatsapp/README.md
generated
vendored
21
vendor/github.com/Rhymen/go-whatsapp/README.md
generated
vendored
@ -23,7 +23,7 @@ qrChan := make(chan string)
|
|||||||
go func() {
|
go func() {
|
||||||
fmt.Printf("qr code: %v\n", <-qrChan)
|
fmt.Printf("qr code: %v\n", <-qrChan)
|
||||||
//show qr code or save it somewhere to scan
|
//show qr code or save it somewhere to scan
|
||||||
}
|
}()
|
||||||
sess, err := wac.Login(qrChan)
|
sess, err := wac.Login(qrChan)
|
||||||
```
|
```
|
||||||
The authentication process requires you to scan the qr code, that is send through the channel, with the device you are using whatsapp on. The session struct that is returned can be saved and used to restore the login without scanning the qr code again. The qr code has a ttl of 20 seconds and the login function throws a timeout err if the time has passed or any other request fails.
|
The authentication process requires you to scan the qr code, that is send through the channel, with the device you are using whatsapp on. The session struct that is returned can be saved and used to restore the login without scanning the qr code again. The qr code has a ttl of 20 seconds and the login function throws a timeout err if the time has passed or any other request fails.
|
||||||
@ -66,6 +66,10 @@ func (myHandler) HandleJsonMessage(message string) {
|
|||||||
fmt.Println(message)
|
fmt.Println(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (myHandler) HandleContactMessage(message whatsapp.ContactMessage) {
|
||||||
|
fmt.Println(message)
|
||||||
|
}
|
||||||
|
|
||||||
wac.AddHandler(myHandler{})
|
wac.AddHandler(myHandler{})
|
||||||
```
|
```
|
||||||
The message handlers are all optional, you don't need to implement anything but the error handler to implement the interface. The ImageMessage, VideoMessage, AudioMessage and DocumentMessage provide a Download function to get the media data.
|
The message handlers are all optional, you don't need to implement anything but the error handler to implement the interface. The ImageMessage, VideoMessage, AudioMessage and DocumentMessage provide a Download function to get the media data.
|
||||||
@ -81,6 +85,21 @@ text := whatsapp.TextMessage{
|
|||||||
|
|
||||||
err := wac.Send(text)
|
err := wac.Send(text)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Sending Contact Messages
|
||||||
|
```go
|
||||||
|
contactMessage := whatsapp.ContactMessage{
|
||||||
|
Info: whatsapp.MessageInfo{
|
||||||
|
RemoteJid: "0123456789@s.whatsapp.net",
|
||||||
|
},
|
||||||
|
DisplayName: "Luke Skylwallker",
|
||||||
|
Vcard: "BEGIN:VCARD\nVERSION:3.0\nN:Skyllwalker;Luke;;\nFN:Luke Skywallker\nitem1.TEL;waid=0123456789:+1 23 456789789\nitem1.X-ABLabel:Mobile\nEND:VCARD",
|
||||||
|
}
|
||||||
|
|
||||||
|
id, error := client.WaConn.Send(contactMessage)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
The message will be send over the websocket. The attributes seen above are the required ones. All other relevant attributes (id, timestamp, fromMe, status) are set if they are missing in the struct. For the time being we only support text messages, but other types are planned for the near future.
|
The message will be send over the websocket. The attributes seen above are the required ones. All other relevant attributes (id, timestamp, fromMe, status) are set if they are missing in the struct. For the time being we only support text messages, but other types are planned for the near future.
|
||||||
|
|
||||||
## Legal
|
## Legal
|
||||||
|
9
vendor/github.com/Rhymen/go-whatsapp/binary/node.go
generated
vendored
9
vendor/github.com/Rhymen/go-whatsapp/binary/node.go
generated
vendored
@ -66,9 +66,12 @@ func Unmarshal(data []byte) (*Node, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if n != nil && n.Attributes != nil && n.Content != nil {
|
if n != nil && n.Attributes != nil && n.Content != nil {
|
||||||
n.Content, err = unmarshalMessageArray(n.Content.([]Node))
|
nContent, ok := n.Content.([]Node)
|
||||||
if err != nil {
|
if ok {
|
||||||
return nil, err
|
n.Content, err = unmarshalMessageArray(nContent)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1401
vendor/github.com/Rhymen/go-whatsapp/binary/proto/def.pb.go
generated
vendored
1401
vendor/github.com/Rhymen/go-whatsapp/binary/proto/def.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
65
vendor/github.com/Rhymen/go-whatsapp/binary/proto/def.proto
generated
vendored
65
vendor/github.com/Rhymen/go-whatsapp/binary/proto/def.proto
generated
vendored
@ -3,7 +3,7 @@ package proto;
|
|||||||
|
|
||||||
message HydratedQuickReplyButton {
|
message HydratedQuickReplyButton {
|
||||||
optional string displayText = 1;
|
optional string displayText = 1;
|
||||||
optional string buttonId = 2;
|
optional string id = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message HydratedURLButton {
|
message HydratedURLButton {
|
||||||
@ -17,6 +17,7 @@ message HydratedCallButton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message HydratedTemplateButton {
|
message HydratedTemplateButton {
|
||||||
|
optional uint32 index = 4;
|
||||||
oneof hydratedButton {
|
oneof hydratedButton {
|
||||||
HydratedQuickReplyButton quickReplyButton = 1;
|
HydratedQuickReplyButton quickReplyButton = 1;
|
||||||
HydratedURLButton urlButton = 2;
|
HydratedURLButton urlButton = 2;
|
||||||
@ -26,7 +27,7 @@ message HydratedTemplateButton {
|
|||||||
|
|
||||||
message QuickReplyButton {
|
message QuickReplyButton {
|
||||||
optional HighlyStructuredMessage displayText = 1;
|
optional HighlyStructuredMessage displayText = 1;
|
||||||
optional string buttonId = 2;
|
optional string id = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message URLButton {
|
message URLButton {
|
||||||
@ -40,6 +41,7 @@ message CallButton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message TemplateButton {
|
message TemplateButton {
|
||||||
|
optional uint32 index = 4;
|
||||||
oneof button {
|
oneof button {
|
||||||
QuickReplyButton quickReplyButton = 1;
|
QuickReplyButton quickReplyButton = 1;
|
||||||
URLButton urlButton = 2;
|
URLButton urlButton = 2;
|
||||||
@ -89,6 +91,8 @@ message ContextInfo {
|
|||||||
optional uint32 forwardingScore = 21;
|
optional uint32 forwardingScore = 21;
|
||||||
optional bool isForwarded = 22;
|
optional bool isForwarded = 22;
|
||||||
optional AdReplyInfo quotedAd = 23;
|
optional AdReplyInfo quotedAd = 23;
|
||||||
|
optional MessageKey placeholderKey = 24;
|
||||||
|
optional uint32 expiration = 25;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SenderKeyDistributionMessage {
|
message SenderKeyDistributionMessage {
|
||||||
@ -114,6 +118,10 @@ message ImageMessage {
|
|||||||
optional bytes firstScanSidecar = 18;
|
optional bytes firstScanSidecar = 18;
|
||||||
optional uint32 firstScanLength = 19;
|
optional uint32 firstScanLength = 19;
|
||||||
optional uint32 experimentGroupId = 20;
|
optional uint32 experimentGroupId = 20;
|
||||||
|
optional bytes scansSidecar = 21;
|
||||||
|
repeated uint32 scanLengths = 22;
|
||||||
|
optional bytes midQualityFileSha256 = 23;
|
||||||
|
optional bytes midQualityFileEncSha256 = 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ContactMessage {
|
message ContactMessage {
|
||||||
@ -156,6 +164,7 @@ message ExtendedTextMessage {
|
|||||||
optional EXTENDED_TEXT_MESSAGE_PREVIEWTYPE previewType = 10;
|
optional EXTENDED_TEXT_MESSAGE_PREVIEWTYPE previewType = 10;
|
||||||
optional bytes jpegThumbnail = 16;
|
optional bytes jpegThumbnail = 16;
|
||||||
optional ContextInfo contextInfo = 17;
|
optional ContextInfo contextInfo = 17;
|
||||||
|
optional bool doNotPlayInline = 18;
|
||||||
}
|
}
|
||||||
|
|
||||||
message DocumentMessage {
|
message DocumentMessage {
|
||||||
@ -228,8 +237,10 @@ message ProtocolMessage {
|
|||||||
optional MessageKey key = 1;
|
optional MessageKey key = 1;
|
||||||
enum PROTOCOL_MESSAGE_TYPE {
|
enum PROTOCOL_MESSAGE_TYPE {
|
||||||
REVOKE = 0;
|
REVOKE = 0;
|
||||||
|
EPHEMERAL_SETTING = 3;
|
||||||
}
|
}
|
||||||
optional PROTOCOL_MESSAGE_TYPE type = 2;
|
optional PROTOCOL_MESSAGE_TYPE type = 2;
|
||||||
|
optional uint32 ephemeralExpiration = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ContactsArrayMessage {
|
message ContactsArrayMessage {
|
||||||
@ -294,6 +305,7 @@ message HighlyStructuredMessage {
|
|||||||
repeated HSMLocalizableParameter localizableParams = 6;
|
repeated HSMLocalizableParameter localizableParams = 6;
|
||||||
optional string deterministicLg = 7;
|
optional string deterministicLg = 7;
|
||||||
optional string deterministicLc = 8;
|
optional string deterministicLc = 8;
|
||||||
|
optional TemplateMessage hydratedHsm = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SendPaymentMessage {
|
message SendPaymentMessage {
|
||||||
@ -341,7 +353,8 @@ message StickerMessage {
|
|||||||
optional string directPath = 8;
|
optional string directPath = 8;
|
||||||
optional uint64 fileLength = 9;
|
optional uint64 fileLength = 9;
|
||||||
optional int64 mediaKeyTimestamp = 10;
|
optional int64 mediaKeyTimestamp = 10;
|
||||||
optional bytes pngThumbnail = 16;
|
optional uint32 firstFrameLength = 11;
|
||||||
|
optional bytes firstFrameSidecar = 12;
|
||||||
optional ContextInfo contextInfo = 17;
|
optional ContextInfo contextInfo = 17;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,7 +374,8 @@ message FourRowTemplate {
|
|||||||
message HydratedFourRowTemplate {
|
message HydratedFourRowTemplate {
|
||||||
optional string hydratedContentText = 6;
|
optional string hydratedContentText = 6;
|
||||||
optional string hydratedFooterText = 7;
|
optional string hydratedFooterText = 7;
|
||||||
repeated HydratedTemplateButton hydratedButtons = 9;
|
repeated HydratedTemplateButton hydratedButtons = 8;
|
||||||
|
optional string templateId = 9;
|
||||||
oneof title {
|
oneof title {
|
||||||
DocumentMessage documentMessage = 1;
|
DocumentMessage documentMessage = 1;
|
||||||
string hydratedTitleText = 2;
|
string hydratedTitleText = 2;
|
||||||
@ -372,6 +386,8 @@ message HydratedFourRowTemplate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message TemplateMessage {
|
message TemplateMessage {
|
||||||
|
optional ContextInfo contextInfo = 3;
|
||||||
|
optional HydratedFourRowTemplate hydratedTemplate = 4;
|
||||||
oneof format {
|
oneof format {
|
||||||
FourRowTemplate fourRowTemplate = 1;
|
FourRowTemplate fourRowTemplate = 1;
|
||||||
HydratedFourRowTemplate hydratedFourRowTemplate = 2;
|
HydratedFourRowTemplate hydratedFourRowTemplate = 2;
|
||||||
@ -379,9 +395,10 @@ message TemplateMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message TemplateButtonReplyMessage {
|
message TemplateButtonReplyMessage {
|
||||||
optional string selectedButtonId = 1;
|
optional string selectedId = 1;
|
||||||
repeated string selectedButtonDisplayText = 2;
|
optional string selectedDisplayText = 2;
|
||||||
optional ContextInfo contextInfo = 3;
|
optional ContextInfo contextInfo = 3;
|
||||||
|
optional uint32 selectedIndex = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ProductSnapshot {
|
message ProductSnapshot {
|
||||||
@ -394,6 +411,7 @@ message ProductSnapshot {
|
|||||||
optional string retailerId = 7;
|
optional string retailerId = 7;
|
||||||
optional string url = 8;
|
optional string url = 8;
|
||||||
optional uint32 productImageCount = 9;
|
optional uint32 productImageCount = 9;
|
||||||
|
optional string firstImageId = 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ProductMessage {
|
message ProductMessage {
|
||||||
@ -409,6 +427,16 @@ message GroupInviteMessage {
|
|||||||
optional string groupName = 4;
|
optional string groupName = 4;
|
||||||
optional bytes jpegThumbnail = 5;
|
optional bytes jpegThumbnail = 5;
|
||||||
optional string caption = 6;
|
optional string caption = 6;
|
||||||
|
optional ContextInfo contextInfo = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DeviceSentMessage {
|
||||||
|
optional string destinationJid = 1;
|
||||||
|
optional Message message = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DeviceSyncMessage {
|
||||||
|
optional bytes serializedXmlBytes = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Message {
|
message Message {
|
||||||
@ -434,8 +462,11 @@ message Message {
|
|||||||
optional CancelPaymentRequestMessage cancelPaymentRequestMessage = 24;
|
optional CancelPaymentRequestMessage cancelPaymentRequestMessage = 24;
|
||||||
optional TemplateMessage templateMessage = 25;
|
optional TemplateMessage templateMessage = 25;
|
||||||
optional StickerMessage stickerMessage = 26;
|
optional StickerMessage stickerMessage = 26;
|
||||||
optional ProductMessage productMessage = 27;
|
|
||||||
optional GroupInviteMessage groupInviteMessage = 28;
|
optional GroupInviteMessage groupInviteMessage = 28;
|
||||||
|
optional TemplateButtonReplyMessage templateButtonReplyMessage = 29;
|
||||||
|
optional ProductMessage productMessage = 30;
|
||||||
|
optional DeviceSentMessage deviceSentMessage = 31;
|
||||||
|
optional DeviceSyncMessage deviceSyncMessage = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
message MessageKey {
|
message MessageKey {
|
||||||
@ -447,9 +478,10 @@ message MessageKey {
|
|||||||
|
|
||||||
message WebFeatures {
|
message WebFeatures {
|
||||||
enum WEB_FEATURES_FLAG {
|
enum WEB_FEATURES_FLAG {
|
||||||
NOT_IMPLEMENTED = 0;
|
NOT_STARTED = 0;
|
||||||
IMPLEMENTED = 1;
|
FORCE_UPGRADE = 1;
|
||||||
OPTIONAL = 2;
|
DEVELOPMENT = 2;
|
||||||
|
PRODUCTION = 3;
|
||||||
}
|
}
|
||||||
optional WEB_FEATURES_FLAG labelsDisplay = 1;
|
optional WEB_FEATURES_FLAG labelsDisplay = 1;
|
||||||
optional WEB_FEATURES_FLAG voipIndividualOutgoing = 2;
|
optional WEB_FEATURES_FLAG voipIndividualOutgoing = 2;
|
||||||
@ -473,6 +505,14 @@ message WebFeatures {
|
|||||||
optional WEB_FEATURES_FLAG voipIndividualVideo = 22;
|
optional WEB_FEATURES_FLAG voipIndividualVideo = 22;
|
||||||
optional WEB_FEATURES_FLAG thirdPartyStickers = 23;
|
optional WEB_FEATURES_FLAG thirdPartyStickers = 23;
|
||||||
optional WEB_FEATURES_FLAG frequentlyForwardedSetting = 24;
|
optional WEB_FEATURES_FLAG frequentlyForwardedSetting = 24;
|
||||||
|
optional WEB_FEATURES_FLAG groupsV4JoinPermission = 25;
|
||||||
|
optional WEB_FEATURES_FLAG recentStickers = 26;
|
||||||
|
optional WEB_FEATURES_FLAG catalog = 27;
|
||||||
|
optional WEB_FEATURES_FLAG starredStickers = 28;
|
||||||
|
optional WEB_FEATURES_FLAG voipGroupCall = 29;
|
||||||
|
optional WEB_FEATURES_FLAG templateMessage = 30;
|
||||||
|
optional WEB_FEATURES_FLAG templateMessageInteractivity = 31;
|
||||||
|
optional WEB_FEATURES_FLAG ephemeralMessages = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
message TabletNotificationsInfo {
|
message TabletNotificationsInfo {
|
||||||
@ -614,6 +654,9 @@ message WebMessageInfo {
|
|||||||
BIZ_TWO_TIER_MIGRATION_BOTTOM = 67;
|
BIZ_TWO_TIER_MIGRATION_BOTTOM = 67;
|
||||||
OVERSIZED = 68;
|
OVERSIZED = 68;
|
||||||
GROUP_CHANGE_NO_FREQUENTLY_FORWARDED = 69;
|
GROUP_CHANGE_NO_FREQUENTLY_FORWARDED = 69;
|
||||||
|
GROUP_V4_ADD_INVITE_SENT = 70;
|
||||||
|
GROUP_PARTICIPANT_ADD_REQUEST_JOIN = 71;
|
||||||
|
CHANGE_EPHEMERAL_SETTING = 72;
|
||||||
}
|
}
|
||||||
optional WEB_MESSAGE_INFO_STUBTYPE messageStubType = 24;
|
optional WEB_MESSAGE_INFO_STUBTYPE messageStubType = 24;
|
||||||
optional bool clearMedia = 25;
|
optional bool clearMedia = 25;
|
||||||
@ -623,4 +666,6 @@ message WebMessageInfo {
|
|||||||
optional PaymentInfo paymentInfo = 29;
|
optional PaymentInfo paymentInfo = 29;
|
||||||
optional LiveLocationMessage finalLiveLocation = 30;
|
optional LiveLocationMessage finalLiveLocation = 30;
|
||||||
optional PaymentInfo quotedPaymentInfo = 31;
|
optional PaymentInfo quotedPaymentInfo = 31;
|
||||||
|
optional uint64 ephemeralStartTimestamp = 32;
|
||||||
|
optional uint32 ephemeralDuration = 33;
|
||||||
}
|
}
|
2
vendor/github.com/Rhymen/go-whatsapp/conn.go
generated
vendored
2
vendor/github.com/Rhymen/go-whatsapp/conn.go
generated
vendored
@ -93,6 +93,8 @@ type Conn struct {
|
|||||||
|
|
||||||
loginSessionLock sync.RWMutex
|
loginSessionLock sync.RWMutex
|
||||||
Proxy func(*http.Request) (*url.URL, error)
|
Proxy func(*http.Request) (*url.URL, error)
|
||||||
|
|
||||||
|
writerLock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
type websocketWrapper struct {
|
type websocketWrapper struct {
|
||||||
|
10
vendor/github.com/Rhymen/go-whatsapp/contact.go
generated
vendored
10
vendor/github.com/Rhymen/go-whatsapp/contact.go
generated
vendored
@ -10,11 +10,11 @@ import (
|
|||||||
type Presence string
|
type Presence string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PresenceAvailable = "available"
|
PresenceAvailable Presence = "available"
|
||||||
PresenceUnavailable = "unavailable"
|
PresenceUnavailable Presence = "unavailable"
|
||||||
PresenceComposing = "composing"
|
PresenceComposing Presence = "composing"
|
||||||
PresenceRecording = "recording"
|
PresenceRecording Presence = "recording"
|
||||||
PresencePaused = "paused"
|
PresencePaused Presence = "paused"
|
||||||
)
|
)
|
||||||
|
|
||||||
//TODO: filename? WhatsApp uses Store.Contacts for these functions
|
//TODO: filename? WhatsApp uses Store.Contacts for these functions
|
||||||
|
2
vendor/github.com/Rhymen/go-whatsapp/go.mod
generated
vendored
2
vendor/github.com/Rhymen/go-whatsapp/go.mod
generated
vendored
@ -10,3 +10,5 @@ require (
|
|||||||
github.com/pkg/errors v0.8.1
|
github.com/pkg/errors v0.8.1
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
go 1.13
|
||||||
|
21
vendor/github.com/Rhymen/go-whatsapp/handler.go
generated
vendored
21
vendor/github.com/Rhymen/go-whatsapp/handler.go
generated
vendored
@ -82,13 +82,21 @@ type LocationMessageHandler interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The StickerMessageHandler interface needs to be implemented to receive location messages dispatched by the dispatcher.
|
The StickerMessageHandler interface needs to be implemented to receive sticker messages dispatched by the dispatcher.
|
||||||
*/
|
*/
|
||||||
type StickerMessageHandler interface {
|
type StickerMessageHandler interface {
|
||||||
Handler
|
Handler
|
||||||
HandleStickerMessage(message StickerMessage)
|
HandleStickerMessage(message StickerMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The ContactMessageHandler interface needs to be implemented to receive contact messages dispatched by the dispatcher.
|
||||||
|
*/
|
||||||
|
type ContactMessageHandler interface {
|
||||||
|
Handler
|
||||||
|
HandleContactMessage(message ContactMessage)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The JsonMessageHandler interface needs to be implemented to receive json messages dispatched by the dispatcher.
|
The JsonMessageHandler interface needs to be implemented to receive json messages dispatched by the dispatcher.
|
||||||
These json messages contain status updates of every kind sent by WhatsAppWeb servers. WhatsAppWeb uses these messages
|
These json messages contain status updates of every kind sent by WhatsAppWeb servers. WhatsAppWeb uses these messages
|
||||||
@ -267,6 +275,17 @@ func (wac *Conn) handleWithCustomHandlers(message interface{}, handlers []Handle
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case ContactMessage:
|
||||||
|
for _, h := range handlers {
|
||||||
|
if x, ok := h.(ContactMessageHandler); ok {
|
||||||
|
if wac.shouldCallSynchronously(h) {
|
||||||
|
x.HandleContactMessage(m)
|
||||||
|
} else {
|
||||||
|
go x.HandleContactMessage(m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case *proto.WebMessageInfo:
|
case *proto.WebMessageInfo:
|
||||||
for _, h := range handlers {
|
for _, h := range handlers {
|
||||||
if x, ok := h.(RawMessageHandler); ok {
|
if x, ok := h.(RawMessageHandler); ok {
|
||||||
|
200
vendor/github.com/Rhymen/go-whatsapp/message.go
generated
vendored
200
vendor/github.com/Rhymen/go-whatsapp/message.go
generated
vendored
@ -23,64 +23,53 @@ const (
|
|||||||
MediaDocument MediaType = "WhatsApp Document Keys"
|
MediaDocument MediaType = "WhatsApp Document Keys"
|
||||||
)
|
)
|
||||||
|
|
||||||
var msgInfo MessageInfo
|
|
||||||
|
|
||||||
func (wac *Conn) Send(msg interface{}) (string, error) {
|
func (wac *Conn) Send(msg interface{}) (string, error) {
|
||||||
var err error
|
|
||||||
var ch <-chan string
|
|
||||||
var msgProto *proto.WebMessageInfo
|
var msgProto *proto.WebMessageInfo
|
||||||
|
|
||||||
switch m := msg.(type) {
|
switch m := msg.(type) {
|
||||||
case *proto.WebMessageInfo:
|
case *proto.WebMessageInfo:
|
||||||
ch, err = wac.sendProto(m)
|
msgProto = m
|
||||||
case TextMessage:
|
case TextMessage:
|
||||||
msgProto = getTextProto(m)
|
msgProto = getTextProto(m)
|
||||||
msgInfo = getMessageInfo(msgProto)
|
|
||||||
ch, err = wac.sendProto(msgProto)
|
|
||||||
case ImageMessage:
|
case ImageMessage:
|
||||||
|
var err error
|
||||||
m.url, m.mediaKey, m.fileEncSha256, m.fileSha256, m.fileLength, err = wac.Upload(m.Content, MediaImage)
|
m.url, m.mediaKey, m.fileEncSha256, m.fileSha256, m.fileLength, err = wac.Upload(m.Content, MediaImage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "ERROR", fmt.Errorf("image upload failed: %v", err)
|
return "ERROR", fmt.Errorf("image upload failed: %v", err)
|
||||||
}
|
}
|
||||||
msgProto = getImageProto(m)
|
msgProto = getImageProto(m)
|
||||||
msgInfo = getMessageInfo(msgProto)
|
|
||||||
ch, err = wac.sendProto(msgProto)
|
|
||||||
case VideoMessage:
|
case VideoMessage:
|
||||||
|
var err error
|
||||||
m.url, m.mediaKey, m.fileEncSha256, m.fileSha256, m.fileLength, err = wac.Upload(m.Content, MediaVideo)
|
m.url, m.mediaKey, m.fileEncSha256, m.fileSha256, m.fileLength, err = wac.Upload(m.Content, MediaVideo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "ERROR", fmt.Errorf("video upload failed: %v", err)
|
return "ERROR", fmt.Errorf("video upload failed: %v", err)
|
||||||
}
|
}
|
||||||
msgProto = getVideoProto(m)
|
msgProto = getVideoProto(m)
|
||||||
msgInfo = getMessageInfo(msgProto)
|
|
||||||
ch, err = wac.sendProto(msgProto)
|
|
||||||
case DocumentMessage:
|
case DocumentMessage:
|
||||||
|
var err error
|
||||||
m.url, m.mediaKey, m.fileEncSha256, m.fileSha256, m.fileLength, err = wac.Upload(m.Content, MediaDocument)
|
m.url, m.mediaKey, m.fileEncSha256, m.fileSha256, m.fileLength, err = wac.Upload(m.Content, MediaDocument)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "ERROR", fmt.Errorf("document upload failed: %v", err)
|
return "ERROR", fmt.Errorf("document upload failed: %v", err)
|
||||||
}
|
}
|
||||||
msgProto = getDocumentProto(m)
|
msgProto = getDocumentProto(m)
|
||||||
msgInfo = getMessageInfo(msgProto)
|
|
||||||
ch, err = wac.sendProto(msgProto)
|
|
||||||
case AudioMessage:
|
case AudioMessage:
|
||||||
|
var err error
|
||||||
m.url, m.mediaKey, m.fileEncSha256, m.fileSha256, m.fileLength, err = wac.Upload(m.Content, MediaAudio)
|
m.url, m.mediaKey, m.fileEncSha256, m.fileSha256, m.fileLength, err = wac.Upload(m.Content, MediaAudio)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "ERROR", fmt.Errorf("audio upload failed: %v", err)
|
return "ERROR", fmt.Errorf("audio upload failed: %v", err)
|
||||||
}
|
}
|
||||||
msgProto = getAudioProto(m)
|
msgProto = getAudioProto(m)
|
||||||
msgInfo = getMessageInfo(msgProto)
|
|
||||||
ch, err = wac.sendProto(msgProto)
|
|
||||||
case LocationMessage:
|
case LocationMessage:
|
||||||
msgProto = GetLocationProto(m)
|
msgProto = GetLocationProto(m)
|
||||||
msgInfo = getMessageInfo(msgProto)
|
|
||||||
ch, err = wac.sendProto(msgProto)
|
|
||||||
case LiveLocationMessage:
|
case LiveLocationMessage:
|
||||||
msgProto = GetLiveLocationProto(m)
|
msgProto = GetLiveLocationProto(m)
|
||||||
msgInfo = getMessageInfo(msgProto)
|
case ContactMessage:
|
||||||
ch, err = wac.sendProto(msgProto)
|
msgProto = getContactMessageProto(m)
|
||||||
default:
|
default:
|
||||||
return "ERROR", fmt.Errorf("cannot match type %T, use message types declared in the package", msg)
|
return "ERROR", fmt.Errorf("cannot match type %T, use message types declared in the package", msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ch, err := wac.sendProto(msgProto)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "ERROR", fmt.Errorf("could not send proto: %v", err)
|
return "ERROR", fmt.Errorf("could not send proto: %v", err)
|
||||||
}
|
}
|
||||||
@ -95,7 +84,7 @@ func (wac *Conn) Send(msg interface{}) (string, error) {
|
|||||||
return "ERROR", fmt.Errorf("message sending responded with %d", resp["status"])
|
return "ERROR", fmt.Errorf("message sending responded with %d", resp["status"])
|
||||||
}
|
}
|
||||||
if int(resp["status"].(float64)) == 200 {
|
if int(resp["status"].(float64)) == 200 {
|
||||||
return msgInfo.Id, nil
|
return getMessageInfo(msgProto).Id, nil
|
||||||
}
|
}
|
||||||
case <-time.After(wac.msgTimeout):
|
case <-time.After(wac.msgTimeout):
|
||||||
return "ERROR", fmt.Errorf("sending message timed out")
|
return "ERROR", fmt.Errorf("sending message timed out")
|
||||||
@ -124,15 +113,13 @@ func init() {
|
|||||||
MessageInfo contains general message information. It is part of every of every message type.
|
MessageInfo contains general message information. It is part of every of every message type.
|
||||||
*/
|
*/
|
||||||
type MessageInfo struct {
|
type MessageInfo struct {
|
||||||
Id string
|
Id string
|
||||||
RemoteJid string
|
RemoteJid string
|
||||||
SenderJid string
|
SenderJid string
|
||||||
FromMe bool
|
FromMe bool
|
||||||
Timestamp uint64
|
Timestamp uint64
|
||||||
PushName string
|
PushName string
|
||||||
Status MessageStatus
|
Status MessageStatus
|
||||||
QuotedMessageID string
|
|
||||||
QuotedMessage proto.Message
|
|
||||||
|
|
||||||
Source *proto.WebMessageInfo
|
Source *proto.WebMessageInfo
|
||||||
}
|
}
|
||||||
@ -185,14 +172,35 @@ func getInfoProto(info *MessageInfo) *proto.WebMessageInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getContextInfoProto(info *MessageInfo) *proto.ContextInfo {
|
/*
|
||||||
if len(info.QuotedMessageID) > 0 {
|
ContextInfo represents contextinfo of every message
|
||||||
|
*/
|
||||||
|
type ContextInfo struct {
|
||||||
|
QuotedMessageID string //StanzaId
|
||||||
|
QuotedMessage *proto.Message
|
||||||
|
Participant string
|
||||||
|
IsForwarded bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMessageContext(msg *proto.ContextInfo) ContextInfo {
|
||||||
|
|
||||||
|
return ContextInfo{
|
||||||
|
QuotedMessageID: msg.GetStanzaId(), //StanzaId
|
||||||
|
QuotedMessage: msg.GetQuotedMessage(),
|
||||||
|
Participant: msg.GetParticipant(),
|
||||||
|
IsForwarded: msg.GetIsForwarded(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getContextInfoProto(context *ContextInfo) *proto.ContextInfo {
|
||||||
|
if len(context.QuotedMessageID) > 0 {
|
||||||
contextInfo := &proto.ContextInfo{
|
contextInfo := &proto.ContextInfo{
|
||||||
StanzaId: &info.QuotedMessageID,
|
StanzaId: &context.QuotedMessageID,
|
||||||
}
|
}
|
||||||
|
|
||||||
if &info.QuotedMessage != nil {
|
if &context.QuotedMessage != nil {
|
||||||
contextInfo.QuotedMessage = &info.QuotedMessage
|
contextInfo.QuotedMessage = context.QuotedMessage
|
||||||
|
contextInfo.Participant = &context.Participant
|
||||||
}
|
}
|
||||||
|
|
||||||
return contextInfo
|
return contextInfo
|
||||||
@ -205,24 +213,28 @@ func getContextInfoProto(info *MessageInfo) *proto.ContextInfo {
|
|||||||
TextMessage represents a text message.
|
TextMessage represents a text message.
|
||||||
*/
|
*/
|
||||||
type TextMessage struct {
|
type TextMessage struct {
|
||||||
Info MessageInfo
|
Info MessageInfo
|
||||||
Text string
|
Text string
|
||||||
|
ContextInfo ContextInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTextMessage(msg *proto.WebMessageInfo) TextMessage {
|
func getTextMessage(msg *proto.WebMessageInfo) TextMessage {
|
||||||
text := TextMessage{Info: getMessageInfo(msg)}
|
text := TextMessage{Info: getMessageInfo(msg)}
|
||||||
if m := msg.GetMessage().GetExtendedTextMessage(); m != nil {
|
if m := msg.GetMessage().GetExtendedTextMessage(); m != nil {
|
||||||
text.Text = m.GetText()
|
text.Text = m.GetText()
|
||||||
text.Info.QuotedMessageID = m.GetContextInfo().GetStanzaId()
|
|
||||||
|
text.ContextInfo = getMessageContext(m.GetContextInfo())
|
||||||
} else {
|
} else {
|
||||||
text.Text = msg.GetMessage().GetConversation()
|
text.Text = msg.GetMessage().GetConversation()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTextProto(msg TextMessage) *proto.WebMessageInfo {
|
func getTextProto(msg TextMessage) *proto.WebMessageInfo {
|
||||||
p := getInfoProto(&msg.Info)
|
p := getInfoProto(&msg.Info)
|
||||||
contextInfo := getContextInfoProto(&msg.Info)
|
contextInfo := getContextInfoProto(&msg.ContextInfo)
|
||||||
|
|
||||||
if contextInfo == nil {
|
if contextInfo == nil {
|
||||||
p.Message = &proto.Message{
|
p.Message = &proto.Message{
|
||||||
@ -255,6 +267,7 @@ type ImageMessage struct {
|
|||||||
fileEncSha256 []byte
|
fileEncSha256 []byte
|
||||||
fileSha256 []byte
|
fileSha256 []byte
|
||||||
fileLength uint64
|
fileLength uint64
|
||||||
|
ContextInfo ContextInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func getImageMessage(msg *proto.WebMessageInfo) ImageMessage {
|
func getImageMessage(msg *proto.WebMessageInfo) ImageMessage {
|
||||||
@ -270,10 +283,7 @@ func getImageMessage(msg *proto.WebMessageInfo) ImageMessage {
|
|||||||
fileEncSha256: image.GetFileEncSha256(),
|
fileEncSha256: image.GetFileEncSha256(),
|
||||||
fileSha256: image.GetFileSha256(),
|
fileSha256: image.GetFileSha256(),
|
||||||
fileLength: image.GetFileLength(),
|
fileLength: image.GetFileLength(),
|
||||||
}
|
ContextInfo: getMessageContext(image.GetContextInfo()),
|
||||||
|
|
||||||
if contextInfo := image.GetContextInfo(); contextInfo != nil {
|
|
||||||
imageMessage.Info.QuotedMessageID = contextInfo.GetStanzaId()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return imageMessage
|
return imageMessage
|
||||||
@ -281,7 +291,7 @@ func getImageMessage(msg *proto.WebMessageInfo) ImageMessage {
|
|||||||
|
|
||||||
func getImageProto(msg ImageMessage) *proto.WebMessageInfo {
|
func getImageProto(msg ImageMessage) *proto.WebMessageInfo {
|
||||||
p := getInfoProto(&msg.Info)
|
p := getInfoProto(&msg.Info)
|
||||||
contextInfo := getContextInfoProto(&msg.Info)
|
contextInfo := getContextInfoProto(&msg.ContextInfo)
|
||||||
|
|
||||||
p.Message = &proto.Message{
|
p.Message = &proto.Message{
|
||||||
ImageMessage: &proto.ImageMessage{
|
ImageMessage: &proto.ImageMessage{
|
||||||
@ -323,6 +333,7 @@ type VideoMessage struct {
|
|||||||
fileEncSha256 []byte
|
fileEncSha256 []byte
|
||||||
fileSha256 []byte
|
fileSha256 []byte
|
||||||
fileLength uint64
|
fileLength uint64
|
||||||
|
ContextInfo ContextInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func getVideoMessage(msg *proto.WebMessageInfo) VideoMessage {
|
func getVideoMessage(msg *proto.WebMessageInfo) VideoMessage {
|
||||||
@ -340,10 +351,7 @@ func getVideoMessage(msg *proto.WebMessageInfo) VideoMessage {
|
|||||||
fileEncSha256: vid.GetFileEncSha256(),
|
fileEncSha256: vid.GetFileEncSha256(),
|
||||||
fileSha256: vid.GetFileSha256(),
|
fileSha256: vid.GetFileSha256(),
|
||||||
fileLength: vid.GetFileLength(),
|
fileLength: vid.GetFileLength(),
|
||||||
}
|
ContextInfo: getMessageContext(vid.GetContextInfo()),
|
||||||
|
|
||||||
if contextInfo := vid.GetContextInfo(); contextInfo != nil {
|
|
||||||
videoMessage.Info.QuotedMessageID = contextInfo.GetStanzaId()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return videoMessage
|
return videoMessage
|
||||||
@ -351,7 +359,7 @@ func getVideoMessage(msg *proto.WebMessageInfo) VideoMessage {
|
|||||||
|
|
||||||
func getVideoProto(msg VideoMessage) *proto.WebMessageInfo {
|
func getVideoProto(msg VideoMessage) *proto.WebMessageInfo {
|
||||||
p := getInfoProto(&msg.Info)
|
p := getInfoProto(&msg.Info)
|
||||||
contextInfo := getContextInfoProto(&msg.Info)
|
contextInfo := getContextInfoProto(&msg.ContextInfo)
|
||||||
|
|
||||||
p.Message = &proto.Message{
|
p.Message = &proto.Message{
|
||||||
VideoMessage: &proto.VideoMessage{
|
VideoMessage: &proto.VideoMessage{
|
||||||
@ -393,6 +401,7 @@ type AudioMessage struct {
|
|||||||
fileEncSha256 []byte
|
fileEncSha256 []byte
|
||||||
fileSha256 []byte
|
fileSha256 []byte
|
||||||
fileLength uint64
|
fileLength uint64
|
||||||
|
ContextInfo ContextInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAudioMessage(msg *proto.WebMessageInfo) AudioMessage {
|
func getAudioMessage(msg *proto.WebMessageInfo) AudioMessage {
|
||||||
@ -407,10 +416,7 @@ func getAudioMessage(msg *proto.WebMessageInfo) AudioMessage {
|
|||||||
fileEncSha256: aud.GetFileEncSha256(),
|
fileEncSha256: aud.GetFileEncSha256(),
|
||||||
fileSha256: aud.GetFileSha256(),
|
fileSha256: aud.GetFileSha256(),
|
||||||
fileLength: aud.GetFileLength(),
|
fileLength: aud.GetFileLength(),
|
||||||
}
|
ContextInfo: getMessageContext(aud.GetContextInfo()),
|
||||||
|
|
||||||
if contextInfo := aud.GetContextInfo(); contextInfo != nil {
|
|
||||||
audioMessage.Info.QuotedMessageID = contextInfo.GetStanzaId()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return audioMessage
|
return audioMessage
|
||||||
@ -418,7 +424,7 @@ func getAudioMessage(msg *proto.WebMessageInfo) AudioMessage {
|
|||||||
|
|
||||||
func getAudioProto(msg AudioMessage) *proto.WebMessageInfo {
|
func getAudioProto(msg AudioMessage) *proto.WebMessageInfo {
|
||||||
p := getInfoProto(&msg.Info)
|
p := getInfoProto(&msg.Info)
|
||||||
contextInfo := getContextInfoProto(&msg.Info)
|
contextInfo := getContextInfoProto(&msg.ContextInfo)
|
||||||
p.Message = &proto.Message{
|
p.Message = &proto.Message{
|
||||||
AudioMessage: &proto.AudioMessage{
|
AudioMessage: &proto.AudioMessage{
|
||||||
Url: &msg.url,
|
Url: &msg.url,
|
||||||
@ -459,6 +465,7 @@ type DocumentMessage struct {
|
|||||||
fileEncSha256 []byte
|
fileEncSha256 []byte
|
||||||
fileSha256 []byte
|
fileSha256 []byte
|
||||||
fileLength uint64
|
fileLength uint64
|
||||||
|
ContextInfo ContextInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDocumentMessage(msg *proto.WebMessageInfo) DocumentMessage {
|
func getDocumentMessage(msg *proto.WebMessageInfo) DocumentMessage {
|
||||||
@ -476,10 +483,7 @@ func getDocumentMessage(msg *proto.WebMessageInfo) DocumentMessage {
|
|||||||
fileEncSha256: doc.GetFileEncSha256(),
|
fileEncSha256: doc.GetFileEncSha256(),
|
||||||
fileSha256: doc.GetFileSha256(),
|
fileSha256: doc.GetFileSha256(),
|
||||||
fileLength: doc.GetFileLength(),
|
fileLength: doc.GetFileLength(),
|
||||||
}
|
ContextInfo: getMessageContext(doc.GetContextInfo()),
|
||||||
|
|
||||||
if contextInfo := doc.GetContextInfo(); contextInfo != nil {
|
|
||||||
documentMessage.Info.QuotedMessageID = contextInfo.GetStanzaId()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return documentMessage
|
return documentMessage
|
||||||
@ -487,7 +491,7 @@ func getDocumentMessage(msg *proto.WebMessageInfo) DocumentMessage {
|
|||||||
|
|
||||||
func getDocumentProto(msg DocumentMessage) *proto.WebMessageInfo {
|
func getDocumentProto(msg DocumentMessage) *proto.WebMessageInfo {
|
||||||
p := getInfoProto(&msg.Info)
|
p := getInfoProto(&msg.Info)
|
||||||
contextInfo := getContextInfoProto(&msg.Info)
|
contextInfo := getContextInfoProto(&msg.ContextInfo)
|
||||||
p.Message = &proto.Message{
|
p.Message = &proto.Message{
|
||||||
DocumentMessage: &proto.DocumentMessage{
|
DocumentMessage: &proto.DocumentMessage{
|
||||||
JpegThumbnail: msg.Thumbnail,
|
JpegThumbnail: msg.Thumbnail,
|
||||||
@ -523,6 +527,7 @@ type LocationMessage struct {
|
|||||||
Address string
|
Address string
|
||||||
Url string
|
Url string
|
||||||
JpegThumbnail []byte
|
JpegThumbnail []byte
|
||||||
|
ContextInfo ContextInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetLocationMessage(msg *proto.WebMessageInfo) LocationMessage {
|
func GetLocationMessage(msg *proto.WebMessageInfo) LocationMessage {
|
||||||
@ -536,10 +541,7 @@ func GetLocationMessage(msg *proto.WebMessageInfo) LocationMessage {
|
|||||||
Address: loc.GetAddress(),
|
Address: loc.GetAddress(),
|
||||||
Url: loc.GetUrl(),
|
Url: loc.GetUrl(),
|
||||||
JpegThumbnail: loc.GetJpegThumbnail(),
|
JpegThumbnail: loc.GetJpegThumbnail(),
|
||||||
}
|
ContextInfo: getMessageContext(loc.GetContextInfo()),
|
||||||
|
|
||||||
if contextInfo := loc.GetContextInfo(); contextInfo != nil {
|
|
||||||
locationMessage.Info.QuotedMessageID = contextInfo.GetStanzaId()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return locationMessage
|
return locationMessage
|
||||||
@ -547,7 +549,7 @@ func GetLocationMessage(msg *proto.WebMessageInfo) LocationMessage {
|
|||||||
|
|
||||||
func GetLocationProto(msg LocationMessage) *proto.WebMessageInfo {
|
func GetLocationProto(msg LocationMessage) *proto.WebMessageInfo {
|
||||||
p := getInfoProto(&msg.Info)
|
p := getInfoProto(&msg.Info)
|
||||||
contextInfo := getContextInfoProto(&msg.Info)
|
contextInfo := getContextInfoProto(&msg.ContextInfo)
|
||||||
|
|
||||||
p.Message = &proto.Message{
|
p.Message = &proto.Message{
|
||||||
LocationMessage: &proto.LocationMessage{
|
LocationMessage: &proto.LocationMessage{
|
||||||
@ -576,6 +578,7 @@ type LiveLocationMessage struct {
|
|||||||
Caption string
|
Caption string
|
||||||
SequenceNumber int64
|
SequenceNumber int64
|
||||||
JpegThumbnail []byte
|
JpegThumbnail []byte
|
||||||
|
ContextInfo ContextInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetLiveLocationMessage(msg *proto.WebMessageInfo) LiveLocationMessage {
|
func GetLiveLocationMessage(msg *proto.WebMessageInfo) LiveLocationMessage {
|
||||||
@ -591,10 +594,7 @@ func GetLiveLocationMessage(msg *proto.WebMessageInfo) LiveLocationMessage {
|
|||||||
Caption: loc.GetCaption(),
|
Caption: loc.GetCaption(),
|
||||||
SequenceNumber: loc.GetSequenceNumber(),
|
SequenceNumber: loc.GetSequenceNumber(),
|
||||||
JpegThumbnail: loc.GetJpegThumbnail(),
|
JpegThumbnail: loc.GetJpegThumbnail(),
|
||||||
}
|
ContextInfo: getMessageContext(loc.GetContextInfo()),
|
||||||
|
|
||||||
if contextInfo := loc.GetContextInfo(); contextInfo != nil {
|
|
||||||
liveLocationMessage.Info.QuotedMessageID = contextInfo.GetStanzaId()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return liveLocationMessage
|
return liveLocationMessage
|
||||||
@ -602,7 +602,7 @@ func GetLiveLocationMessage(msg *proto.WebMessageInfo) LiveLocationMessage {
|
|||||||
|
|
||||||
func GetLiveLocationProto(msg LiveLocationMessage) *proto.WebMessageInfo {
|
func GetLiveLocationProto(msg LiveLocationMessage) *proto.WebMessageInfo {
|
||||||
p := getInfoProto(&msg.Info)
|
p := getInfoProto(&msg.Info)
|
||||||
contextInfo := getContextInfoProto(&msg.Info)
|
contextInfo := getContextInfoProto(&msg.ContextInfo)
|
||||||
p.Message = &proto.Message{
|
p.Message = &proto.Message{
|
||||||
LiveLocationMessage: &proto.LiveLocationMessage{
|
LiveLocationMessage: &proto.LiveLocationMessage{
|
||||||
DegreesLatitude: &msg.DegreesLatitude,
|
DegreesLatitude: &msg.DegreesLatitude,
|
||||||
@ -625,7 +625,6 @@ StickerMessage represents a sticker message.
|
|||||||
type StickerMessage struct {
|
type StickerMessage struct {
|
||||||
Info MessageInfo
|
Info MessageInfo
|
||||||
|
|
||||||
Thumbnail []byte
|
|
||||||
Type string
|
Type string
|
||||||
Content io.Reader
|
Content io.Reader
|
||||||
url string
|
url string
|
||||||
@ -633,30 +632,79 @@ type StickerMessage struct {
|
|||||||
fileEncSha256 []byte
|
fileEncSha256 []byte
|
||||||
fileSha256 []byte
|
fileSha256 []byte
|
||||||
fileLength uint64
|
fileLength uint64
|
||||||
|
|
||||||
|
ContextInfo ContextInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func getStickerMessage(msg *proto.WebMessageInfo) StickerMessage {
|
func getStickerMessage(msg *proto.WebMessageInfo) StickerMessage {
|
||||||
sticker := msg.GetMessage().GetStickerMessage()
|
sticker := msg.GetMessage().GetStickerMessage()
|
||||||
|
|
||||||
StickerMessage := StickerMessage{
|
stickerMessage := StickerMessage{
|
||||||
Info: getMessageInfo(msg),
|
Info: getMessageInfo(msg),
|
||||||
Thumbnail: sticker.GetPngThumbnail(),
|
|
||||||
url: sticker.GetUrl(),
|
url: sticker.GetUrl(),
|
||||||
mediaKey: sticker.GetMediaKey(),
|
mediaKey: sticker.GetMediaKey(),
|
||||||
Type: sticker.GetMimetype(),
|
Type: sticker.GetMimetype(),
|
||||||
fileEncSha256: sticker.GetFileEncSha256(),
|
fileEncSha256: sticker.GetFileEncSha256(),
|
||||||
fileSha256: sticker.GetFileSha256(),
|
fileSha256: sticker.GetFileSha256(),
|
||||||
fileLength: sticker.GetFileLength(),
|
fileLength: sticker.GetFileLength(),
|
||||||
|
ContextInfo: getMessageContext(sticker.GetContextInfo()),
|
||||||
}
|
}
|
||||||
|
|
||||||
if contextInfo := sticker.GetContextInfo(); contextInfo != nil {
|
return stickerMessage
|
||||||
StickerMessage.Info.QuotedMessageID = contextInfo.GetStanzaId()
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Download is the function to retrieve Sticker media data. The media gets downloaded, validated and returned.
|
||||||
|
*/
|
||||||
|
|
||||||
|
func (m *StickerMessage) Download() ([]byte, error) {
|
||||||
|
return Download(m.url, m.mediaKey, MediaImage, int(m.fileLength))
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
ContactMessage represents a contact message.
|
||||||
|
*/
|
||||||
|
type ContactMessage struct {
|
||||||
|
Info MessageInfo
|
||||||
|
|
||||||
|
DisplayName string
|
||||||
|
Vcard string
|
||||||
|
|
||||||
|
ContextInfo ContextInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func getContactMessage(msg *proto.WebMessageInfo) ContactMessage {
|
||||||
|
contact := msg.GetMessage().GetContactMessage()
|
||||||
|
|
||||||
|
contactMessage := ContactMessage{
|
||||||
|
Info: getMessageInfo(msg),
|
||||||
|
|
||||||
|
DisplayName: contact.GetDisplayName(),
|
||||||
|
Vcard: contact.GetVcard(),
|
||||||
|
|
||||||
|
ContextInfo: getMessageContext(contact.GetContextInfo()),
|
||||||
}
|
}
|
||||||
|
|
||||||
return StickerMessage
|
return contactMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
func getContactMessageProto(msg ContactMessage) *proto.WebMessageInfo {
|
||||||
|
p := getInfoProto(&msg.Info)
|
||||||
|
contextInfo := getContextInfoProto(&msg.ContextInfo)
|
||||||
|
|
||||||
|
p.Message = &proto.Message{
|
||||||
|
ContactMessage: &proto.ContactMessage{
|
||||||
|
DisplayName: &msg.DisplayName,
|
||||||
|
Vcard: &msg.Vcard,
|
||||||
|
ContextInfo: contextInfo,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseProtoMessage(msg *proto.WebMessageInfo) interface{} {
|
func ParseProtoMessage(msg *proto.WebMessageInfo) interface{} {
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
|
||||||
case msg.GetMessage().GetAudioMessage() != nil:
|
case msg.GetMessage().GetAudioMessage() != nil:
|
||||||
@ -686,8 +734,12 @@ func ParseProtoMessage(msg *proto.WebMessageInfo) interface{} {
|
|||||||
case msg.GetMessage().GetStickerMessage() != nil:
|
case msg.GetMessage().GetStickerMessage() != nil:
|
||||||
return getStickerMessage(msg)
|
return getStickerMessage(msg)
|
||||||
|
|
||||||
|
case msg.GetMessage().GetContactMessage() != nil:
|
||||||
|
return getContactMessage(msg)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
//cannot match message
|
//cannot match message
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
43
vendor/github.com/Rhymen/go-whatsapp/profile.go
generated
vendored
Normal file
43
vendor/github.com/Rhymen/go-whatsapp/profile.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package whatsapp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/Rhymen/go-whatsapp/binary"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Pictures must be JPG 640x640 and 96x96, respectively
|
||||||
|
func (wac *Conn) UploadProfilePic(image, preview []byte) (<-chan string, error) {
|
||||||
|
tag := fmt.Sprintf("%d.--%d", time.Now().Unix(), wac.msgCount*19)
|
||||||
|
n := binary.Node{
|
||||||
|
Description: "action",
|
||||||
|
Attributes: map[string]string{
|
||||||
|
"type": "set",
|
||||||
|
"epoch": strconv.Itoa(wac.msgCount),
|
||||||
|
},
|
||||||
|
Content: []interface{}{
|
||||||
|
binary.Node{
|
||||||
|
Description: "picture",
|
||||||
|
Attributes: map[string]string{
|
||||||
|
"id": tag,
|
||||||
|
"jid": wac.Info.Wid,
|
||||||
|
"type": "set",
|
||||||
|
},
|
||||||
|
Content: []binary.Node{
|
||||||
|
{
|
||||||
|
Description: "image",
|
||||||
|
Attributes: nil,
|
||||||
|
Content: image,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Description: "preview",
|
||||||
|
Attributes: nil,
|
||||||
|
Content: preview,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return wac.writeBinary(n, profile, 136, tag)
|
||||||
|
}
|
13
vendor/github.com/Rhymen/go-whatsapp/write.go
generated
vendored
13
vendor/github.com/Rhymen/go-whatsapp/write.go
generated
vendored
@ -5,16 +5,22 @@ import (
|
|||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/Rhymen/go-whatsapp/binary"
|
"github.com/Rhymen/go-whatsapp/binary"
|
||||||
"github.com/Rhymen/go-whatsapp/crypto/cbc"
|
"github.com/Rhymen/go-whatsapp/crypto/cbc"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//writeJson enqueues a json message into the writeChan
|
//writeJson enqueues a json message into the writeChan
|
||||||
func (wac *Conn) writeJson(data []interface{}) (<-chan string, error) {
|
func (wac *Conn) writeJson(data []interface{}) (<-chan string, error) {
|
||||||
|
|
||||||
|
wac.writerLock.Lock()
|
||||||
|
defer wac.writerLock.Unlock()
|
||||||
|
|
||||||
d, err := json.Marshal(data)
|
d, err := json.Marshal(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -38,6 +44,9 @@ func (wac *Conn) writeBinary(node binary.Node, metric metric, flag flag, message
|
|||||||
return nil, ErrMissingMessageTag
|
return nil, ErrMissingMessageTag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wac.writerLock.Lock()
|
||||||
|
defer wac.writerLock.Unlock()
|
||||||
|
|
||||||
data, err := wac.encryptBinaryMessage(node)
|
data, err := wac.encryptBinaryMessage(node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "encryptBinaryMessage(node) failed")
|
return nil, errors.Wrap(err, "encryptBinaryMessage(node) failed")
|
||||||
|
2
vendor/github.com/bwmarrin/discordgo/discord.go
generated
vendored
2
vendor/github.com/bwmarrin/discordgo/discord.go
generated
vendored
@ -21,7 +21,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// VERSION of DiscordGo, follows Semantic Versioning. (http://semver.org/)
|
// VERSION of DiscordGo, follows Semantic Versioning. (http://semver.org/)
|
||||||
const VERSION = "0.20.1"
|
const VERSION = "0.20.2"
|
||||||
|
|
||||||
// ErrMFA will be risen by New when the user has 2FA.
|
// ErrMFA will be risen by New when the user has 2FA.
|
||||||
var ErrMFA = errors.New("account has 2FA enabled")
|
var ErrMFA = errors.New("account has 2FA enabled")
|
||||||
|
7
vendor/github.com/bwmarrin/discordgo/restapi.go
generated
vendored
7
vendor/github.com/bwmarrin/discordgo/restapi.go
generated
vendored
@ -88,7 +88,12 @@ func (s *Session) RequestWithLockedBucket(method, urlStr, contentType string, b
|
|||||||
req.Header.Set("authorization", s.Token)
|
req.Header.Set("authorization", s.Token)
|
||||||
}
|
}
|
||||||
|
|
||||||
req.Header.Set("Content-Type", contentType)
|
// Discord's API returns a 400 Bad Request is Content-Type is set, but the
|
||||||
|
// request body is empty.
|
||||||
|
if b != nil {
|
||||||
|
req.Header.Set("Content-Type", contentType)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Make a configurable static variable.
|
// TODO: Make a configurable static variable.
|
||||||
req.Header.Set("User-Agent", s.UserAgent)
|
req.Header.Set("User-Agent", s.UserAgent)
|
||||||
|
|
||||||
|
17
vendor/github.com/gomarkdown/markdown/.travis.yml
generated
vendored
17
vendor/github.com/gomarkdown/markdown/.travis.yml
generated
vendored
@ -1,17 +0,0 @@
|
|||||||
dist: bionic
|
|
||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- "1.12.x"
|
|
||||||
|
|
||||||
install:
|
|
||||||
- go build -v ./...
|
|
||||||
|
|
||||||
script:
|
|
||||||
- go test -v ./...
|
|
||||||
- go test -run=^$ -bench=BenchmarkReference -benchmem
|
|
||||||
- ./s/test_with_codecoverage.sh
|
|
||||||
- ./s/ci_fuzzit.sh
|
|
||||||
|
|
||||||
after_success:
|
|
||||||
- bash <(curl -s https://codecov.io/bash)
|
|
15
vendor/github.com/gomarkdown/markdown/README.md
generated
vendored
15
vendor/github.com/gomarkdown/markdown/README.md
generated
vendored
@ -17,6 +17,19 @@ API Docs:
|
|||||||
- https://godoc.org/github.com/gomarkdown/markdown/parser : parser
|
- https://godoc.org/github.com/gomarkdown/markdown/parser : parser
|
||||||
- https://godoc.org/github.com/gomarkdown/markdown/html : html renderer
|
- https://godoc.org/github.com/gomarkdown/markdown/html : html renderer
|
||||||
|
|
||||||
|
## Users
|
||||||
|
|
||||||
|
Some tools using this package:
|
||||||
|
|
||||||
|
- https://github.com/MichaelMure/go-term-markdown : markdown renderer for the terminal
|
||||||
|
- https://github.com/artyom/mdserver : web server that serves markdown files
|
||||||
|
- https://github.com/rsdoiel/mkpage : content management system generating static websites
|
||||||
|
- https://github.com/cugu/dashboard : creates a badge dashboard from a yaml file
|
||||||
|
- https://github.com/ieyasu/go-bwiki : simple wiki
|
||||||
|
- https://github.com/romanyx/mdopen : view markdown files in the default browser
|
||||||
|
- https://github.com/ystyle/sqlmanager : a library for manager sql with markdown like beetsql
|
||||||
|
- https://gitlab.com/kendellfab/fazer : library for making templates
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
To convert markdown text to HTML using reasonable defaults:
|
To convert markdown text to HTML using reasonable defaults:
|
||||||
@ -295,7 +308,7 @@ implements the following extensions:
|
|||||||
|
|
||||||
Will convert into `<h1 id="id3" class="myclass" fontsize="tiny">Header 1</h1>`.
|
Will convert into `<h1 id="id3" class="myclass" fontsize="tiny">Header 1</h1>`.
|
||||||
|
|
||||||
- **Mmark support**, see <https://mmark.nl/syntax> for all new syntax elements this adds.
|
- **Mmark support**, see <https://mmark.miek.nl/post/syntax/> for all new syntax elements this adds.
|
||||||
|
|
||||||
## Todo
|
## Todo
|
||||||
|
|
||||||
|
7
vendor/github.com/gomarkdown/markdown/ast/print.go
generated
vendored
7
vendor/github.com/gomarkdown/markdown/ast/print.go
generated
vendored
@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Print is for debugging. It prints a string representation of parsed
|
// Print is for debugging. It prints a string representation of parsed
|
||||||
@ -63,11 +64,11 @@ func shortenString(s string, maxLen int) string {
|
|||||||
if maxLen < 0 {
|
if maxLen < 0 {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
if len(s) < maxLen {
|
if utf8.RuneCountInString(s) < maxLen {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
// add "..." to indicate truncation
|
// add "…" to indicate truncation
|
||||||
return s[:maxLen-3] + "..."
|
return string(append([]rune(s)[:maxLen-3], '…'))
|
||||||
}
|
}
|
||||||
|
|
||||||
// get a short name of the type of v which excludes package name
|
// get a short name of the type of v which excludes package name
|
||||||
|
2
vendor/github.com/gomarkdown/markdown/doc.go
generated
vendored
2
vendor/github.com/gomarkdown/markdown/doc.go
generated
vendored
@ -21,7 +21,7 @@ You can customize parser and HTML renderer:
|
|||||||
"github.com/gomarkdown/markdown"
|
"github.com/gomarkdown/markdown"
|
||||||
)
|
)
|
||||||
extensions := parser.CommonExtensions | parser.AutoHeadingIDs
|
extensions := parser.CommonExtensions | parser.AutoHeadingIDs
|
||||||
p := parser.NewWithExensions(extensions)
|
p := parser.NewWithExtensions(extensions)
|
||||||
|
|
||||||
htmlFlags := html.CommonFlags | html.HrefTargetBlank
|
htmlFlags := html.CommonFlags | html.HrefTargetBlank
|
||||||
opts := html.RendererOptions{Flags: htmlFlags}
|
opts := html.RendererOptions{Flags: htmlFlags}
|
||||||
|
2
vendor/github.com/gomarkdown/markdown/html/renderer.go
generated
vendored
2
vendor/github.com/gomarkdown/markdown/html/renderer.go
generated
vendored
@ -1298,7 +1298,7 @@ func BlockAttrs(node ast.Node) []string {
|
|||||||
|
|
||||||
// sort the attributes so it remain stable between runs
|
// sort the attributes so it remain stable between runs
|
||||||
var keys = []string{}
|
var keys = []string{}
|
||||||
for k, _ := range attr.Attrs {
|
for k := range attr.Attrs {
|
||||||
keys = append(keys, k)
|
keys = append(keys, k)
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
|
76
vendor/github.com/gomarkdown/markdown/parser/block.go
generated
vendored
76
vendor/github.com/gomarkdown/markdown/parser/block.go
generated
vendored
@ -24,46 +24,46 @@ var (
|
|||||||
// blockTags is a set of tags that are recognized as HTML block tags.
|
// blockTags is a set of tags that are recognized as HTML block tags.
|
||||||
// Any of these can be included in markdown text without special escaping.
|
// Any of these can be included in markdown text without special escaping.
|
||||||
blockTags = map[string]struct{}{
|
blockTags = map[string]struct{}{
|
||||||
"blockquote": struct{}{},
|
"blockquote": {},
|
||||||
"del": struct{}{},
|
"del": {},
|
||||||
"div": struct{}{},
|
"div": {},
|
||||||
"dl": struct{}{},
|
"dl": {},
|
||||||
"fieldset": struct{}{},
|
"fieldset": {},
|
||||||
"form": struct{}{},
|
"form": {},
|
||||||
"h1": struct{}{},
|
"h1": {},
|
||||||
"h2": struct{}{},
|
"h2": {},
|
||||||
"h3": struct{}{},
|
"h3": {},
|
||||||
"h4": struct{}{},
|
"h4": {},
|
||||||
"h5": struct{}{},
|
"h5": {},
|
||||||
"h6": struct{}{},
|
"h6": {},
|
||||||
"iframe": struct{}{},
|
"iframe": {},
|
||||||
"ins": struct{}{},
|
"ins": {},
|
||||||
"math": struct{}{},
|
"math": {},
|
||||||
"noscript": struct{}{},
|
"noscript": {},
|
||||||
"ol": struct{}{},
|
"ol": {},
|
||||||
"pre": struct{}{},
|
"pre": {},
|
||||||
"p": struct{}{},
|
"p": {},
|
||||||
"script": struct{}{},
|
"script": {},
|
||||||
"style": struct{}{},
|
"style": {},
|
||||||
"table": struct{}{},
|
"table": {},
|
||||||
"ul": struct{}{},
|
"ul": {},
|
||||||
|
|
||||||
// HTML5
|
// HTML5
|
||||||
"address": struct{}{},
|
"address": {},
|
||||||
"article": struct{}{},
|
"article": {},
|
||||||
"aside": struct{}{},
|
"aside": {},
|
||||||
"canvas": struct{}{},
|
"canvas": {},
|
||||||
"figcaption": struct{}{},
|
"figcaption": {},
|
||||||
"figure": struct{}{},
|
"figure": {},
|
||||||
"footer": struct{}{},
|
"footer": {},
|
||||||
"header": struct{}{},
|
"header": {},
|
||||||
"hgroup": struct{}{},
|
"hgroup": {},
|
||||||
"main": struct{}{},
|
"main": {},
|
||||||
"nav": struct{}{},
|
"nav": {},
|
||||||
"output": struct{}{},
|
"output": {},
|
||||||
"progress": struct{}{},
|
"progress": {},
|
||||||
"section": struct{}{},
|
"section": {},
|
||||||
"video": struct{}{},
|
"video": {},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
5
vendor/github.com/gomarkdown/markdown/parser/inline.go
generated
vendored
5
vendor/github.com/gomarkdown/markdown/parser/inline.go
generated
vendored
@ -228,7 +228,7 @@ func maybeInlineFootnoteOrSuper(p *Parser, data []byte, offset int) (int, ast.No
|
|||||||
}
|
}
|
||||||
sup := &ast.Superscript{}
|
sup := &ast.Superscript{}
|
||||||
sup.Literal = data[offset+1 : offset+ret]
|
sup.Literal = data[offset+1 : offset+ret]
|
||||||
return offset + ret, sup
|
return ret + 1, sup
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0, nil
|
return 0, nil
|
||||||
@ -536,6 +536,9 @@ func link(p *Parser, data []byte, offset int) (int, ast.Node) {
|
|||||||
// if inline footnote, title == footnote contents
|
// if inline footnote, title == footnote contents
|
||||||
title = lr.title
|
title = lr.title
|
||||||
noteID = lr.noteID
|
noteID = lr.noteID
|
||||||
|
if len(lr.text) > 0 {
|
||||||
|
altContent = lr.text
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// rewind the whitespace
|
// rewind the whitespace
|
||||||
|
17
vendor/github.com/jpillora/backoff/backoff.go
generated
vendored
17
vendor/github.com/jpillora/backoff/backoff.go
generated
vendored
@ -4,6 +4,7 @@ package backoff
|
|||||||
import (
|
import (
|
||||||
"math"
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -14,19 +15,19 @@ import (
|
|||||||
// Backoff is not generally concurrent-safe, but the ForAttempt method can
|
// Backoff is not generally concurrent-safe, but the ForAttempt method can
|
||||||
// be used concurrently.
|
// be used concurrently.
|
||||||
type Backoff struct {
|
type Backoff struct {
|
||||||
//Factor is the multiplying factor for each increment step
|
attempt uint64
|
||||||
attempt, Factor float64
|
// Factor is the multiplying factor for each increment step
|
||||||
//Jitter eases contention by randomizing backoff steps
|
Factor float64
|
||||||
|
// Jitter eases contention by randomizing backoff steps
|
||||||
Jitter bool
|
Jitter bool
|
||||||
//Min and Max are the minimum and maximum values of the counter
|
// Min and Max are the minimum and maximum values of the counter
|
||||||
Min, Max time.Duration
|
Min, Max time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// Duration returns the duration for the current attempt before incrementing
|
// Duration returns the duration for the current attempt before incrementing
|
||||||
// the attempt counter. See ForAttempt.
|
// the attempt counter. See ForAttempt.
|
||||||
func (b *Backoff) Duration() time.Duration {
|
func (b *Backoff) Duration() time.Duration {
|
||||||
d := b.ForAttempt(b.attempt)
|
d := b.ForAttempt(float64(atomic.AddUint64(&b.attempt, 1) - 1))
|
||||||
b.attempt++
|
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,12 +81,12 @@ func (b *Backoff) ForAttempt(attempt float64) time.Duration {
|
|||||||
|
|
||||||
// Reset restarts the current attempt counter at zero.
|
// Reset restarts the current attempt counter at zero.
|
||||||
func (b *Backoff) Reset() {
|
func (b *Backoff) Reset() {
|
||||||
b.attempt = 0
|
atomic.StoreUint64(&b.attempt, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt returns the current attempt counter value.
|
// Attempt returns the current attempt counter value.
|
||||||
func (b *Backoff) Attempt() float64 {
|
func (b *Backoff) Attempt() float64 {
|
||||||
return b.attempt
|
return float64(atomic.LoadUint64(&b.attempt))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy returns a backoff with equals constraints as the original
|
// Copy returns a backoff with equals constraints as the original
|
||||||
|
3
vendor/github.com/jpillora/backoff/go.mod
generated
vendored
Normal file
3
vendor/github.com/jpillora/backoff/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module github.com/jpillora/backoff
|
||||||
|
|
||||||
|
go 1.13
|
2
vendor/github.com/labstack/echo/v4/.travis.yml
generated
vendored
2
vendor/github.com/labstack/echo/v4/.travis.yml
generated
vendored
@ -1,7 +1,7 @@
|
|||||||
language: go
|
language: go
|
||||||
go:
|
go:
|
||||||
- 1.11.x
|
|
||||||
- 1.12.x
|
- 1.12.x
|
||||||
|
- 1.13.x
|
||||||
- tip
|
- tip
|
||||||
env:
|
env:
|
||||||
- GO111MODULE=on
|
- GO111MODULE=on
|
||||||
|
18
vendor/github.com/labstack/echo/v4/bind.go
generated
vendored
18
vendor/github.com/labstack/echo/v4/bind.go
generated
vendored
@ -43,15 +43,11 @@ func (b *DefaultBinder) Bind(i interface{}, c Context) (err error) {
|
|||||||
if err := b.bindData(i, params, "param"); err != nil {
|
if err := b.bindData(i, params, "param"); err != nil {
|
||||||
return NewHTTPError(http.StatusBadRequest, err.Error()).SetInternal(err)
|
return NewHTTPError(http.StatusBadRequest, err.Error()).SetInternal(err)
|
||||||
}
|
}
|
||||||
|
if err = b.bindData(i, c.QueryParams(), "query"); err != nil {
|
||||||
|
return NewHTTPError(http.StatusBadRequest, err.Error()).SetInternal(err)
|
||||||
|
}
|
||||||
if req.ContentLength == 0 {
|
if req.ContentLength == 0 {
|
||||||
if req.Method == http.MethodGet || req.Method == http.MethodDelete {
|
return
|
||||||
if err = b.bindData(i, c.QueryParams(), "query"); err != nil {
|
|
||||||
return NewHTTPError(http.StatusBadRequest, err.Error()).SetInternal(err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return NewHTTPError(http.StatusBadRequest, "Request body can't be empty")
|
|
||||||
}
|
}
|
||||||
ctype := req.Header.Get(HeaderContentType)
|
ctype := req.Header.Get(HeaderContentType)
|
||||||
switch {
|
switch {
|
||||||
@ -94,13 +90,15 @@ func (b *DefaultBinder) bindData(ptr interface{}, data map[string][]string, tag
|
|||||||
typ := reflect.TypeOf(ptr).Elem()
|
typ := reflect.TypeOf(ptr).Elem()
|
||||||
val := reflect.ValueOf(ptr).Elem()
|
val := reflect.ValueOf(ptr).Elem()
|
||||||
|
|
||||||
if m, ok := ptr.(*map[string]interface{}); ok {
|
// Map
|
||||||
|
if typ.Kind() == reflect.Map {
|
||||||
for k, v := range data {
|
for k, v := range data {
|
||||||
(*m)[k] = v[0]
|
val.SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(v[0]))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// !struct
|
||||||
if typ.Kind() != reflect.Struct {
|
if typ.Kind() != reflect.Struct {
|
||||||
return errors.New("binding element must be a struct")
|
return errors.New("binding element must be a struct")
|
||||||
}
|
}
|
||||||
|
20
vendor/github.com/labstack/echo/v4/context.go
generated
vendored
20
vendor/github.com/labstack/echo/v4/context.go
generated
vendored
@ -183,6 +183,9 @@ type (
|
|||||||
// Logger returns the `Logger` instance.
|
// Logger returns the `Logger` instance.
|
||||||
Logger() Logger
|
Logger() Logger
|
||||||
|
|
||||||
|
// Set the logger
|
||||||
|
SetLogger(l Logger)
|
||||||
|
|
||||||
// Echo returns the `Echo` instance.
|
// Echo returns the `Echo` instance.
|
||||||
Echo() *Echo
|
Echo() *Echo
|
||||||
|
|
||||||
@ -202,6 +205,7 @@ type (
|
|||||||
handler HandlerFunc
|
handler HandlerFunc
|
||||||
store Map
|
store Map
|
||||||
echo *Echo
|
echo *Echo
|
||||||
|
logger Logger
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -347,7 +351,8 @@ func (c *context) FormParams() (url.Values, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) FormFile(name string) (*multipart.FileHeader, error) {
|
func (c *context) FormFile(name string) (*multipart.FileHeader, error) {
|
||||||
_, fh, err := c.request.FormFile(name)
|
f, fh, err := c.request.FormFile(name)
|
||||||
|
defer f.Close()
|
||||||
return fh, err
|
return fh, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -597,9 +602,17 @@ func (c *context) SetHandler(h HandlerFunc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) Logger() Logger {
|
func (c *context) Logger() Logger {
|
||||||
|
res := c.logger
|
||||||
|
if res != nil {
|
||||||
|
return res
|
||||||
|
}
|
||||||
return c.echo.Logger
|
return c.echo.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *context) SetLogger(l Logger) {
|
||||||
|
c.logger = l
|
||||||
|
}
|
||||||
|
|
||||||
func (c *context) Reset(r *http.Request, w http.ResponseWriter) {
|
func (c *context) Reset(r *http.Request, w http.ResponseWriter) {
|
||||||
c.request = r
|
c.request = r
|
||||||
c.response.reset(w)
|
c.response.reset(w)
|
||||||
@ -608,6 +621,9 @@ func (c *context) Reset(r *http.Request, w http.ResponseWriter) {
|
|||||||
c.store = nil
|
c.store = nil
|
||||||
c.path = ""
|
c.path = ""
|
||||||
c.pnames = nil
|
c.pnames = nil
|
||||||
|
c.logger = nil
|
||||||
// NOTE: Don't reset because it has to have length c.echo.maxParam at all times
|
// NOTE: Don't reset because it has to have length c.echo.maxParam at all times
|
||||||
// c.pvalues = nil
|
for i := 0; i < *c.echo.maxParam; i++ {
|
||||||
|
c.pvalues[i] = ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
14
vendor/github.com/labstack/echo/v4/echo.go
generated
vendored
14
vendor/github.com/labstack/echo/v4/echo.go
generated
vendored
@ -227,7 +227,7 @@ const (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// Version of Echo
|
// Version of Echo
|
||||||
Version = "4.1.10"
|
Version = "4.1.13"
|
||||||
website = "https://echo.labstack.com"
|
website = "https://echo.labstack.com"
|
||||||
// http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo
|
// http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo
|
||||||
banner = `
|
banner = `
|
||||||
@ -354,10 +354,14 @@ func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) {
|
|||||||
Message: http.StatusText(http.StatusInternalServerError),
|
Message: http.StatusText(http.StatusInternalServerError),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue #1426
|
||||||
|
code := he.Code
|
||||||
|
message := he.Message
|
||||||
if e.Debug {
|
if e.Debug {
|
||||||
he.Message = err.Error()
|
message = err.Error()
|
||||||
} else if m, ok := he.Message.(string); ok {
|
} else if m, ok := message.(string); ok {
|
||||||
he.Message = Map{"message": m}
|
message = Map{"message": m}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send response
|
// Send response
|
||||||
@ -365,7 +369,7 @@ func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) {
|
|||||||
if c.Request().Method == http.MethodHead { // Issue #608
|
if c.Request().Method == http.MethodHead { // Issue #608
|
||||||
err = c.NoContent(he.Code)
|
err = c.NoContent(he.Code)
|
||||||
} else {
|
} else {
|
||||||
err = c.JSON(he.Code, he.Message)
|
err = c.JSON(code, message)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e.Logger.Error(err)
|
e.Logger.Error(err)
|
||||||
|
10
vendor/github.com/labstack/echo/v4/go.mod
generated
vendored
10
vendor/github.com/labstack/echo/v4/go.mod
generated
vendored
@ -4,8 +4,14 @@ go 1.12
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||||
|
github.com/labstack/echo v3.3.10+incompatible // indirect
|
||||||
github.com/labstack/gommon v0.3.0
|
github.com/labstack/gommon v0.3.0
|
||||||
|
github.com/mattn/go-colorable v0.1.4 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.11 // indirect
|
||||||
github.com/stretchr/testify v1.4.0
|
github.com/stretchr/testify v1.4.0
|
||||||
github.com/valyala/fasttemplate v1.0.1
|
github.com/valyala/fasttemplate v1.1.0
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
|
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876
|
||||||
|
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8 // indirect
|
||||||
|
golang.org/x/text v0.3.2 // indirect
|
||||||
)
|
)
|
||||||
|
28
vendor/github.com/labstack/echo/v4/go.sum
generated
vendored
28
vendor/github.com/labstack/echo/v4/go.sum
generated
vendored
@ -2,13 +2,21 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
|
|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
|
github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=
|
||||||
|
github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
|
||||||
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
|
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
|
||||||
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
||||||
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
|
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
|
||||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
|
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
||||||
|
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
|
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
|
||||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||||
|
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
|
||||||
|
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||||
|
github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM=
|
||||||
|
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
@ -18,17 +26,37 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw
|
|||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8=
|
github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8=
|
||||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||||
|
github.com/valyala/fasttemplate v1.1.0 h1:RZqt0yGBsps8NGvLSGW804QQqCUYYLsaOjTVHy1Ocw4=
|
||||||
|
github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
|
||||||
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876 h1:sKJQZMuxjOAR/Uo2LBfU90onWEf1dF4C+0hPJCc9Mpc=
|
||||||
|
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20191021144547-ec77196f6094 h1:5O4U9trLjNpuhpynaDsqwCk+Tw6seqJz1EbqbnzHrc8=
|
||||||
|
golang.org/x/net v0.0.0-20191021144547-ec77196f6094/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
|
||||||
|
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
|
||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191024172528-b4ff53e7a1cb h1:ZxSglHghKPYD8WDeRUzRJrUJtDF0PxsTUSxyqr9/5BI=
|
||||||
|
golang.org/x/sys v0.0.0-20191024172528-b4ff53e7a1cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8 h1:JA8d3MPx/IToSyXZG/RhwYEtfrKO1Fxrqe8KrkiLXKM=
|
||||||
|
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
2
vendor/github.com/labstack/echo/v4/middleware/body_dump.go
generated
vendored
2
vendor/github.com/labstack/echo/v4/middleware/body_dump.go
generated
vendored
@ -40,7 +40,7 @@ var (
|
|||||||
|
|
||||||
// BodyDump returns a BodyDump middleware.
|
// BodyDump returns a BodyDump middleware.
|
||||||
//
|
//
|
||||||
// BodyLimit middleware captures the request and response payload and calls the
|
// BodyDump middleware captures the request and response payload and calls the
|
||||||
// registered handler.
|
// registered handler.
|
||||||
func BodyDump(handler BodyDumpHandler) echo.MiddlewareFunc {
|
func BodyDump(handler BodyDumpHandler) echo.MiddlewareFunc {
|
||||||
c := DefaultBodyDumpConfig
|
c := DefaultBodyDumpConfig
|
||||||
|
13
vendor/github.com/labstack/echo/v4/middleware/proxy.go
generated
vendored
13
vendor/github.com/labstack/echo/v4/middleware/proxy.go
generated
vendored
@ -92,15 +92,14 @@ func proxyRaw(t *ProxyTarget, c echo.Context) http.Handler {
|
|||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
in, _, err := c.Response().Hijack()
|
in, _, err := c.Response().Hijack()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Error(fmt.Errorf("proxy raw, hijack error=%v, url=%s", t.URL, err))
|
c.Set("_error", fmt.Sprintf("proxy raw, hijack error=%v, url=%s", t.URL, err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer in.Close()
|
defer in.Close()
|
||||||
|
|
||||||
out, err := net.Dial("tcp", t.URL.Host)
|
out, err := net.Dial("tcp", t.URL.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
he := echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf("proxy raw, dial error=%v, url=%s", t.URL, err))
|
c.Set("_error", echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf("proxy raw, dial error=%v, url=%s", t.URL, err)))
|
||||||
c.Error(he)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer out.Close()
|
defer out.Close()
|
||||||
@ -108,8 +107,7 @@ func proxyRaw(t *ProxyTarget, c echo.Context) http.Handler {
|
|||||||
// Write header
|
// Write header
|
||||||
err = r.Write(out)
|
err = r.Write(out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
he := echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf("proxy raw, request header copy error=%v, url=%s", t.URL, err))
|
c.Set("_error", echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf("proxy raw, request header copy error=%v, url=%s", t.URL, err)))
|
||||||
c.Error(he)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +121,7 @@ func proxyRaw(t *ProxyTarget, c echo.Context) http.Handler {
|
|||||||
go cp(in, out)
|
go cp(in, out)
|
||||||
err = <-errCh
|
err = <-errCh
|
||||||
if err != nil && err != io.EOF {
|
if err != nil && err != io.EOF {
|
||||||
c.Logger().Errorf("proxy raw, copy body error=%v, url=%s", t.URL, err)
|
c.Set("_error", fmt.Errorf("proxy raw, copy body error=%v, url=%s", t.URL, err))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -251,6 +249,9 @@ func ProxyWithConfig(config ProxyConfig) echo.MiddlewareFunc {
|
|||||||
default:
|
default:
|
||||||
proxyHTTP(tgt, c, config).ServeHTTP(res, req)
|
proxyHTTP(tgt, c, config).ServeHTTP(res, req)
|
||||||
}
|
}
|
||||||
|
if e, ok := c.Get("_error").(error); ok {
|
||||||
|
err = e
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
3
vendor/github.com/labstack/echo/v4/middleware/proxy_1_11.go
generated
vendored
3
vendor/github.com/labstack/echo/v4/middleware/proxy_1_11.go
generated
vendored
@ -17,8 +17,7 @@ func proxyHTTP(tgt *ProxyTarget, c echo.Context, config ProxyConfig) http.Handle
|
|||||||
if tgt.Name != "" {
|
if tgt.Name != "" {
|
||||||
desc = fmt.Sprintf("%s(%s)", tgt.Name, tgt.URL.String())
|
desc = fmt.Sprintf("%s(%s)", tgt.Name, tgt.URL.String())
|
||||||
}
|
}
|
||||||
c.Logger().Errorf("remote %s unreachable, could not forward: %v", desc, err)
|
c.Set("_error", echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf("remote %s unreachable, could not forward: %v", desc, err)))
|
||||||
c.Error(echo.NewHTTPError(http.StatusServiceUnavailable))
|
|
||||||
}
|
}
|
||||||
proxy.Transport = config.Transport
|
proxy.Transport = config.Transport
|
||||||
return proxy
|
return proxy
|
||||||
|
50
vendor/github.com/labstack/echo/v4/router.go
generated
vendored
50
vendor/github.com/labstack/echo/v4/router.go
generated
vendored
@ -1,6 +1,9 @@
|
|||||||
package echo
|
package echo
|
||||||
|
|
||||||
import "net/http"
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// Router is the registry of all registered routes for an `Echo` instance for
|
// Router is the registry of all registered routes for an `Echo` instance for
|
||||||
@ -20,8 +23,8 @@ type (
|
|||||||
pnames []string
|
pnames []string
|
||||||
methodHandler *methodHandler
|
methodHandler *methodHandler
|
||||||
}
|
}
|
||||||
kind uint8
|
kind uint8
|
||||||
children []*node
|
children []*node
|
||||||
methodHandler struct {
|
methodHandler struct {
|
||||||
connect HandlerFunc
|
connect HandlerFunc
|
||||||
delete HandlerFunc
|
delete HandlerFunc
|
||||||
@ -133,6 +136,11 @@ func (r *Router) insert(method, path string, h HandlerFunc, t kind, ppath string
|
|||||||
// Split node
|
// Split node
|
||||||
n := newNode(cn.kind, cn.prefix[l:], cn, cn.children, cn.methodHandler, cn.ppath, cn.pnames)
|
n := newNode(cn.kind, cn.prefix[l:], cn, cn.children, cn.methodHandler, cn.ppath, cn.pnames)
|
||||||
|
|
||||||
|
// Update parent path for all children to new node
|
||||||
|
for _, child := range cn.children {
|
||||||
|
child.parent = n
|
||||||
|
}
|
||||||
|
|
||||||
// Reset parent node
|
// Reset parent node
|
||||||
cn.kind = skind
|
cn.kind = skind
|
||||||
cn.label = cn.prefix[0]
|
cn.label = cn.prefix[0]
|
||||||
@ -336,7 +344,6 @@ func (r *Router) Find(method, path string, c Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if l == pl {
|
if l == pl {
|
||||||
// Continue search
|
// Continue search
|
||||||
search = search[l:]
|
search = search[l:]
|
||||||
@ -398,16 +405,33 @@ func (r *Router) Find(method, path string, c Context) {
|
|||||||
Any:
|
Any:
|
||||||
if cn = cn.findChildByKind(akind); cn == nil {
|
if cn = cn.findChildByKind(akind); cn == nil {
|
||||||
if nn != nil {
|
if nn != nil {
|
||||||
cn = nn
|
// No next node to go down in routing (issue #954)
|
||||||
nn = cn.parent // Next (Issue #954)
|
// Find nearest "any" route going up the routing tree
|
||||||
if nn != nil {
|
|
||||||
nk = nn.kind
|
|
||||||
}
|
|
||||||
search = ns
|
search = ns
|
||||||
if nk == pkind {
|
np := nn.parent
|
||||||
goto Param
|
// Consider param route one level up only
|
||||||
} else if nk == akind {
|
// if no slash is remaining in search string
|
||||||
goto Any
|
if cn = nn.findChildByKind(pkind); cn != nil && strings.IndexByte(ns, '/') == -1 {
|
||||||
|
pvalues[len(cn.pnames)-1] = search
|
||||||
|
break
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
np = nn.parent
|
||||||
|
if cn = nn.findChildByKind(akind); cn != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if np == nil {
|
||||||
|
break // no further parent nodes in tree, abort
|
||||||
|
}
|
||||||
|
var str strings.Builder
|
||||||
|
str.WriteString(nn.prefix)
|
||||||
|
str.WriteString(search)
|
||||||
|
search = str.String()
|
||||||
|
nn = np
|
||||||
|
}
|
||||||
|
if cn != nil { // use the found "any" route and update path
|
||||||
|
pvalues[len(cn.pnames)-1] = search
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return // Not found
|
return // Not found
|
||||||
|
2
vendor/github.com/magiconair/properties/.travis.yml
generated
vendored
2
vendor/github.com/magiconair/properties/.travis.yml
generated
vendored
@ -7,4 +7,6 @@ go:
|
|||||||
- 1.8.x
|
- 1.8.x
|
||||||
- 1.9.x
|
- 1.9.x
|
||||||
- "1.10.x"
|
- "1.10.x"
|
||||||
|
- "1.11.x"
|
||||||
|
- "1.12.x"
|
||||||
- tip
|
- tip
|
||||||
|
8
vendor/github.com/magiconair/properties/CHANGELOG.md
generated
vendored
8
vendor/github.com/magiconair/properties/CHANGELOG.md
generated
vendored
@ -1,5 +1,13 @@
|
|||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
### [1.8.1](https://github.com/magiconair/properties/tree/v1.8.1) - 10 May 2019
|
||||||
|
|
||||||
|
* [PR #26](https://github.com/magiconair/properties/pull/35): Close body always after request
|
||||||
|
|
||||||
|
This patch ensures that in `LoadURL` the response body is always closed.
|
||||||
|
|
||||||
|
Thanks to [@liubog2008](https://github.com/liubog2008) for the patch.
|
||||||
|
|
||||||
### [1.8](https://github.com/magiconair/properties/tree/v1.8) - 15 May 2018
|
### [1.8](https://github.com/magiconair/properties/tree/v1.8) - 15 May 2018
|
||||||
|
|
||||||
* [PR #26](https://github.com/magiconair/properties/pull/26): Disable expansion during loading
|
* [PR #26](https://github.com/magiconair/properties/pull/26): Disable expansion during loading
|
||||||
|
4
vendor/github.com/magiconair/properties/README.md
generated
vendored
4
vendor/github.com/magiconair/properties/README.md
generated
vendored
@ -1,6 +1,6 @@
|
|||||||
[![](https://img.shields.io/github/tag/magiconair/properties.svg?style=flat-square&label=release)](https://github.com/magiconair/properties/releases)
|
[![](https://img.shields.io/github/tag/magiconair/properties.svg?style=flat-square&label=release)](https://github.com/magiconair/properties/releases)
|
||||||
[![Travis CI Status](https://img.shields.io/travis/magiconair/properties.svg?branch=master&style=flat-square&label=travis)](https://travis-ci.org/magiconair/properties)
|
[![Travis CI Status](https://img.shields.io/travis/magiconair/properties.svg?branch=master&style=flat-square&label=travis)](https://travis-ci.org/magiconair/properties)
|
||||||
[![Codeship CI Status](https://img.shields.io/codeship/16aaf660-f615-0135-b8f0-7e33b70920c0/master.svg?label=codeship&style=flat-square)](https://app.codeship.com/projects/274177")
|
[![CircleCI Status](https://img.shields.io/circleci/project/github/magiconair/properties.svg?label=circle+ci&style=flat-square)](https://circleci.com/gh/magiconair/properties)
|
||||||
[![License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg?style=flat-square)](https://raw.githubusercontent.com/magiconair/properties/master/LICENSE)
|
[![License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg?style=flat-square)](https://raw.githubusercontent.com/magiconair/properties/master/LICENSE)
|
||||||
[![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/magiconair/properties)
|
[![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/magiconair/properties)
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ changed from `panic` to `log.Fatal` but this is configurable and custom
|
|||||||
error handling functions can be provided. See the package documentation for
|
error handling functions can be provided. See the package documentation for
|
||||||
details.
|
details.
|
||||||
|
|
||||||
Read the full documentation on [GoDoc](https://godoc.org/github.com/magiconair/properties) [![GoDoc](https://godoc.org/github.com/magiconair/properties?status.png)](https://godoc.org/github.com/magiconair/properties)
|
Read the full documentation on [![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/magiconair/properties)
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
|
1
vendor/github.com/magiconair/properties/go.mod
generated
vendored
Normal file
1
vendor/github.com/magiconair/properties/go.mod
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
module github.com/magiconair/properties
|
2
vendor/github.com/magiconair/properties/load.go
generated
vendored
2
vendor/github.com/magiconair/properties/load.go
generated
vendored
@ -115,6 +115,7 @@ func (l *Loader) LoadURL(url string) (*Properties, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("properties: error fetching %q. %s", url, err)
|
return nil, fmt.Errorf("properties: error fetching %q. %s", url, err)
|
||||||
}
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode == 404 && l.IgnoreMissing {
|
if resp.StatusCode == 404 && l.IgnoreMissing {
|
||||||
LogPrintf("properties: %s returned %d. skipping", url, resp.StatusCode)
|
LogPrintf("properties: %s returned %d. skipping", url, resp.StatusCode)
|
||||||
@ -129,7 +130,6 @@ func (l *Loader) LoadURL(url string) (*Properties, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("properties: %s error reading response. %s", url, err)
|
return nil, fmt.Errorf("properties: %s error reading response. %s", url, err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
ct := resp.Header.Get("Content-Type")
|
ct := resp.Header.Get("Content-Type")
|
||||||
var enc Encoding
|
var enc Encoding
|
||||||
|
6
vendor/github.com/mattn/go-colorable/colorable_appengine.go
generated
vendored
6
vendor/github.com/mattn/go-colorable/colorable_appengine.go
generated
vendored
@ -9,7 +9,7 @@ import (
|
|||||||
_ "github.com/mattn/go-isatty"
|
_ "github.com/mattn/go-isatty"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewColorable return new instance of Writer which handle escape sequence.
|
// NewColorable returns new instance of Writer which handles escape sequence.
|
||||||
func NewColorable(file *os.File) io.Writer {
|
func NewColorable(file *os.File) io.Writer {
|
||||||
if file == nil {
|
if file == nil {
|
||||||
panic("nil passed instead of *os.File to NewColorable()")
|
panic("nil passed instead of *os.File to NewColorable()")
|
||||||
@ -18,12 +18,12 @@ func NewColorable(file *os.File) io.Writer {
|
|||||||
return file
|
return file
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewColorableStdout return new instance of Writer which handle escape sequence for stdout.
|
// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout.
|
||||||
func NewColorableStdout() io.Writer {
|
func NewColorableStdout() io.Writer {
|
||||||
return os.Stdout
|
return os.Stdout
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewColorableStderr return new instance of Writer which handle escape sequence for stderr.
|
// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr.
|
||||||
func NewColorableStderr() io.Writer {
|
func NewColorableStderr() io.Writer {
|
||||||
return os.Stderr
|
return os.Stderr
|
||||||
}
|
}
|
||||||
|
6
vendor/github.com/mattn/go-colorable/colorable_others.go
generated
vendored
6
vendor/github.com/mattn/go-colorable/colorable_others.go
generated
vendored
@ -10,7 +10,7 @@ import (
|
|||||||
_ "github.com/mattn/go-isatty"
|
_ "github.com/mattn/go-isatty"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewColorable return new instance of Writer which handle escape sequence.
|
// NewColorable returns new instance of Writer which handles escape sequence.
|
||||||
func NewColorable(file *os.File) io.Writer {
|
func NewColorable(file *os.File) io.Writer {
|
||||||
if file == nil {
|
if file == nil {
|
||||||
panic("nil passed instead of *os.File to NewColorable()")
|
panic("nil passed instead of *os.File to NewColorable()")
|
||||||
@ -19,12 +19,12 @@ func NewColorable(file *os.File) io.Writer {
|
|||||||
return file
|
return file
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewColorableStdout return new instance of Writer which handle escape sequence for stdout.
|
// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout.
|
||||||
func NewColorableStdout() io.Writer {
|
func NewColorableStdout() io.Writer {
|
||||||
return os.Stdout
|
return os.Stdout
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewColorableStderr return new instance of Writer which handle escape sequence for stderr.
|
// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr.
|
||||||
func NewColorableStderr() io.Writer {
|
func NewColorableStderr() io.Writer {
|
||||||
return os.Stderr
|
return os.Stderr
|
||||||
}
|
}
|
||||||
|
43
vendor/github.com/mattn/go-colorable/colorable_windows.go
generated
vendored
43
vendor/github.com/mattn/go-colorable/colorable_windows.go
generated
vendored
@ -81,7 +81,7 @@ var (
|
|||||||
procCreateConsoleScreenBuffer = kernel32.NewProc("CreateConsoleScreenBuffer")
|
procCreateConsoleScreenBuffer = kernel32.NewProc("CreateConsoleScreenBuffer")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Writer provide colorable Writer to the console
|
// Writer provides colorable Writer to the console
|
||||||
type Writer struct {
|
type Writer struct {
|
||||||
out io.Writer
|
out io.Writer
|
||||||
handle syscall.Handle
|
handle syscall.Handle
|
||||||
@ -91,7 +91,7 @@ type Writer struct {
|
|||||||
rest bytes.Buffer
|
rest bytes.Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewColorable return new instance of Writer which handle escape sequence from File.
|
// NewColorable returns new instance of Writer which handles escape sequence from File.
|
||||||
func NewColorable(file *os.File) io.Writer {
|
func NewColorable(file *os.File) io.Writer {
|
||||||
if file == nil {
|
if file == nil {
|
||||||
panic("nil passed instead of *os.File to NewColorable()")
|
panic("nil passed instead of *os.File to NewColorable()")
|
||||||
@ -106,12 +106,12 @@ func NewColorable(file *os.File) io.Writer {
|
|||||||
return file
|
return file
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewColorableStdout return new instance of Writer which handle escape sequence for stdout.
|
// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout.
|
||||||
func NewColorableStdout() io.Writer {
|
func NewColorableStdout() io.Writer {
|
||||||
return NewColorable(os.Stdout)
|
return NewColorable(os.Stdout)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewColorableStderr return new instance of Writer which handle escape sequence for stderr.
|
// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr.
|
||||||
func NewColorableStderr() io.Writer {
|
func NewColorableStderr() io.Writer {
|
||||||
return NewColorable(os.Stderr)
|
return NewColorable(os.Stderr)
|
||||||
}
|
}
|
||||||
@ -414,7 +414,15 @@ func doTitleSequence(er *bytes.Reader) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write write data on console
|
// returns Atoi(s) unless s == "" in which case it returns def
|
||||||
|
func atoiWithDefault(s string, def int) (int, error) {
|
||||||
|
if s == "" {
|
||||||
|
return def, nil
|
||||||
|
}
|
||||||
|
return strconv.Atoi(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write writes data on console
|
||||||
func (w *Writer) Write(data []byte) (n int, err error) {
|
func (w *Writer) Write(data []byte) (n int, err error) {
|
||||||
var csbi consoleScreenBufferInfo
|
var csbi consoleScreenBufferInfo
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
@ -500,7 +508,7 @@ loop:
|
|||||||
|
|
||||||
switch m {
|
switch m {
|
||||||
case 'A':
|
case 'A':
|
||||||
n, err = strconv.Atoi(buf.String())
|
n, err = atoiWithDefault(buf.String(), 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -508,7 +516,7 @@ loop:
|
|||||||
csbi.cursorPosition.y -= short(n)
|
csbi.cursorPosition.y -= short(n)
|
||||||
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||||
case 'B':
|
case 'B':
|
||||||
n, err = strconv.Atoi(buf.String())
|
n, err = atoiWithDefault(buf.String(), 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -516,7 +524,7 @@ loop:
|
|||||||
csbi.cursorPosition.y += short(n)
|
csbi.cursorPosition.y += short(n)
|
||||||
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||||
case 'C':
|
case 'C':
|
||||||
n, err = strconv.Atoi(buf.String())
|
n, err = atoiWithDefault(buf.String(), 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -524,7 +532,7 @@ loop:
|
|||||||
csbi.cursorPosition.x += short(n)
|
csbi.cursorPosition.x += short(n)
|
||||||
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||||
case 'D':
|
case 'D':
|
||||||
n, err = strconv.Atoi(buf.String())
|
n, err = atoiWithDefault(buf.String(), 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -557,6 +565,9 @@ loop:
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if n < 1 {
|
||||||
|
n = 1
|
||||||
|
}
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
csbi.cursorPosition.x = short(n - 1)
|
csbi.cursorPosition.x = short(n - 1)
|
||||||
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||||
@ -635,6 +646,20 @@ loop:
|
|||||||
}
|
}
|
||||||
procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
||||||
procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
||||||
|
case 'X':
|
||||||
|
n := 0
|
||||||
|
if buf.Len() > 0 {
|
||||||
|
n, err = strconv.Atoi(buf.String())
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
|
var cursor coord
|
||||||
|
var written dword
|
||||||
|
cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
|
||||||
|
procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(n), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
||||||
|
procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(n), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
||||||
case 'm':
|
case 'm':
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
attr := csbi.attributes
|
attr := csbi.attributes
|
||||||
|
6
vendor/github.com/mattn/go-colorable/noncolorable.go
generated
vendored
6
vendor/github.com/mattn/go-colorable/noncolorable.go
generated
vendored
@ -5,17 +5,17 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NonColorable hold writer but remove escape sequence.
|
// NonColorable holds writer but removes escape sequence.
|
||||||
type NonColorable struct {
|
type NonColorable struct {
|
||||||
out io.Writer
|
out io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNonColorable return new instance of Writer which remove escape sequence from Writer.
|
// NewNonColorable returns new instance of Writer which removes escape sequence from Writer.
|
||||||
func NewNonColorable(w io.Writer) io.Writer {
|
func NewNonColorable(w io.Writer) io.Writer {
|
||||||
return &NonColorable{out: w}
|
return &NonColorable{out: w}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write write data on console
|
// Write writes data on console
|
||||||
func (w *NonColorable) Write(data []byte) (n int, err error) {
|
func (w *NonColorable) Write(data []byte) (n int, err error) {
|
||||||
er := bytes.NewReader(data)
|
er := bytes.NewReader(data)
|
||||||
var bw [1]byte
|
var bw [1]byte
|
||||||
|
4
vendor/github.com/mattn/go-isatty/go.mod
generated
vendored
4
vendor/github.com/mattn/go-isatty/go.mod
generated
vendored
@ -1,3 +1,5 @@
|
|||||||
module github.com/mattn/go-isatty
|
module github.com/mattn/go-isatty
|
||||||
|
|
||||||
require golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a
|
go 1.12
|
||||||
|
|
||||||
|
require golang.org/x/sys v0.0.0-20191026070338-33540a1f6037
|
||||||
|
4
vendor/github.com/mattn/go-isatty/go.sum
generated
vendored
4
vendor/github.com/mattn/go-isatty/go.sum
generated
vendored
@ -1,2 +1,2 @@
|
|||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
|
||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
22
vendor/github.com/mattn/go-isatty/isatty_plan9.go
generated
vendored
Normal file
22
vendor/github.com/mattn/go-isatty/isatty_plan9.go
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// +build plan9
|
||||||
|
|
||||||
|
package isatty
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||||
|
func IsTerminal(fd uintptr) bool {
|
||||||
|
path, err := syscall.Fd2path(int(fd))
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return path == "/dev/cons" || path == "/mnt/term/dev/cons"
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
|
||||||
|
// terminal. This is also always false on this environment.
|
||||||
|
func IsCygwinTerminal(fd uintptr) bool {
|
||||||
|
return false
|
||||||
|
}
|
39
vendor/github.com/mattn/go-isatty/isatty_windows.go
generated
vendored
39
vendor/github.com/mattn/go-isatty/isatty_windows.go
generated
vendored
@ -4,6 +4,7 @@
|
|||||||
package isatty
|
package isatty
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unicode/utf16"
|
"unicode/utf16"
|
||||||
@ -11,15 +12,18 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
fileNameInfo uintptr = 2
|
objectNameInfo uintptr = 1
|
||||||
fileTypePipe = 3
|
fileNameInfo = 2
|
||||||
|
fileTypePipe = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||||
|
ntdll = syscall.NewLazyDLL("ntdll.dll")
|
||||||
procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
|
procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
|
||||||
procGetFileInformationByHandleEx = kernel32.NewProc("GetFileInformationByHandleEx")
|
procGetFileInformationByHandleEx = kernel32.NewProc("GetFileInformationByHandleEx")
|
||||||
procGetFileType = kernel32.NewProc("GetFileType")
|
procGetFileType = kernel32.NewProc("GetFileType")
|
||||||
|
procNtQueryObject = ntdll.NewProc("NtQueryObject")
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -45,7 +49,10 @@ func isCygwinPipeName(name string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if token[0] != `\msys` && token[0] != `\cygwin` {
|
if token[0] != `\msys` &&
|
||||||
|
token[0] != `\cygwin` &&
|
||||||
|
token[0] != `\Device\NamedPipe\msys` &&
|
||||||
|
token[0] != `\Device\NamedPipe\cygwin` {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,11 +75,35 @@ func isCygwinPipeName(name string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getFileNameByHandle use the undocomented ntdll NtQueryObject to get file full name from file handler
|
||||||
|
// since GetFileInformationByHandleEx is not avilable under windows Vista and still some old fashion
|
||||||
|
// guys are using Windows XP, this is a workaround for those guys, it will also work on system from
|
||||||
|
// Windows vista to 10
|
||||||
|
// see https://stackoverflow.com/a/18792477 for details
|
||||||
|
func getFileNameByHandle(fd uintptr) (string, error) {
|
||||||
|
if procNtQueryObject == nil {
|
||||||
|
return "", errors.New("ntdll.dll: NtQueryObject not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf [4 + syscall.MAX_PATH]uint16
|
||||||
|
var result int
|
||||||
|
r, _, e := syscall.Syscall6(procNtQueryObject.Addr(), 5,
|
||||||
|
fd, objectNameInfo, uintptr(unsafe.Pointer(&buf)), uintptr(2*len(buf)), uintptr(unsafe.Pointer(&result)), 0)
|
||||||
|
if r != 0 {
|
||||||
|
return "", e
|
||||||
|
}
|
||||||
|
return string(utf16.Decode(buf[4 : 4+buf[0]/2])), nil
|
||||||
|
}
|
||||||
|
|
||||||
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
|
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
|
||||||
// terminal.
|
// terminal.
|
||||||
func IsCygwinTerminal(fd uintptr) bool {
|
func IsCygwinTerminal(fd uintptr) bool {
|
||||||
if procGetFileInformationByHandleEx == nil {
|
if procGetFileInformationByHandleEx == nil {
|
||||||
return false
|
name, err := getFileNameByHandle(fd)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return isCygwinPipeName(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cygwin/msys's pty is a pipe.
|
// Cygwin/msys's pty is a pipe.
|
||||||
|
47
vendor/github.com/spf13/viper/.gitignore
generated
vendored
47
vendor/github.com/spf13/viper/.gitignore
generated
vendored
@ -1,29 +1,20 @@
|
|||||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
/bin/
|
||||||
*.o
|
/build/
|
||||||
*.a
|
/var/
|
||||||
*.so
|
/vendor/
|
||||||
|
|
||||||
# Folders
|
# IDE integration
|
||||||
_obj
|
/.vscode/*
|
||||||
_test
|
!/.vscode/launch.json
|
||||||
|
!/.vscode/tasks.json
|
||||||
# Architecture specific extensions/prefixes
|
/.idea/*
|
||||||
*.[568vq]
|
!/.idea/codeStyles/
|
||||||
[568vq].out
|
!/.idea/copyright/
|
||||||
|
!/.idea/dataSources.xml
|
||||||
*.cgo1.go
|
!/.idea/*.iml
|
||||||
*.cgo2.c
|
!/.idea/externalDependencies.xml
|
||||||
_cgo_defun.c
|
!/.idea/go.imports.xml
|
||||||
_cgo_gotypes.go
|
!/.idea/modules.xml
|
||||||
_cgo_export.*
|
!/.idea/runConfigurations/
|
||||||
|
!/.idea/scopes/
|
||||||
_testmain.go
|
!/.idea/sqldialects.xml
|
||||||
|
|
||||||
*.exe
|
|
||||||
*.test
|
|
||||||
*.bench
|
|
||||||
|
|
||||||
.vscode
|
|
||||||
|
|
||||||
# exclude dependencies in the `/vendor` folder
|
|
||||||
vendor
|
|
||||||
|
24
vendor/github.com/spf13/viper/.golangci.yml
generated
vendored
Normal file
24
vendor/github.com/spf13/viper/.golangci.yml
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
linters-settings:
|
||||||
|
golint:
|
||||||
|
min-confidence: 0.1
|
||||||
|
goimports:
|
||||||
|
local-prefixes: github.com/spf13/viper
|
||||||
|
|
||||||
|
linters:
|
||||||
|
enable-all: true
|
||||||
|
disable:
|
||||||
|
- funlen
|
||||||
|
- maligned
|
||||||
|
|
||||||
|
# TODO: fix me
|
||||||
|
- wsl
|
||||||
|
- gochecknoinits
|
||||||
|
- gosimple
|
||||||
|
- gochecknoglobals
|
||||||
|
- errcheck
|
||||||
|
- lll
|
||||||
|
- godox
|
||||||
|
- scopelint
|
||||||
|
- gocyclo
|
||||||
|
- gocognit
|
||||||
|
- gocritic
|
7
vendor/github.com/spf13/viper/.travis.yml
generated
vendored
7
vendor/github.com/spf13/viper/.travis.yml
generated
vendored
@ -4,10 +4,13 @@ language: go
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- GO111MODULE="on"
|
- GO111MODULE="on"
|
||||||
|
- GOFLAGS="-mod=readonly"
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.11.x
|
- 1.11.x
|
||||||
|
- 1.12.x
|
||||||
|
- 1.13.x
|
||||||
- tip
|
- tip
|
||||||
|
|
||||||
os:
|
os:
|
||||||
@ -27,5 +30,3 @@ script:
|
|||||||
after_success:
|
after_success:
|
||||||
- go get -u -d github.com/spf13/hugo
|
- go get -u -d github.com/spf13/hugo
|
||||||
- cd $GOPATH/src/github.com/spf13/hugo && make && ./hugo -s docs && cd -
|
- cd $GOPATH/src/github.com/spf13/hugo && make && ./hugo -s docs && cd -
|
||||||
|
|
||||||
sudo: false
|
|
||||||
|
71
vendor/github.com/spf13/viper/Makefile
generated
vendored
Normal file
71
vendor/github.com/spf13/viper/Makefile
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
# A Self-Documenting Makefile: http://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
|
||||||
|
|
||||||
|
OS = $(shell uname | tr A-Z a-z)
|
||||||
|
|
||||||
|
# Build variables
|
||||||
|
BUILD_DIR ?= build
|
||||||
|
ifeq (${VERBOSE}, 1)
|
||||||
|
ifeq ($(filter -v,${GOARGS}),)
|
||||||
|
GOARGS += -v
|
||||||
|
endif
|
||||||
|
TEST_FORMAT = short-verbose
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Dependency versions
|
||||||
|
GOTESTSUM_VERSION = 0.3.5
|
||||||
|
GOLANGCI_VERSION = 1.21.0
|
||||||
|
|
||||||
|
# Add the ability to override some variables
|
||||||
|
# Use with care
|
||||||
|
-include override.mk
|
||||||
|
|
||||||
|
.PHONY: clear
|
||||||
|
clear: ## Clear the working area and the project
|
||||||
|
rm -rf bin/
|
||||||
|
|
||||||
|
.PHONY: check
|
||||||
|
check: test lint ## Run tests and linters
|
||||||
|
|
||||||
|
bin/gotestsum: bin/gotestsum-${GOTESTSUM_VERSION}
|
||||||
|
@ln -sf gotestsum-${GOTESTSUM_VERSION} bin/gotestsum
|
||||||
|
bin/gotestsum-${GOTESTSUM_VERSION}:
|
||||||
|
@mkdir -p bin
|
||||||
|
curl -L https://github.com/gotestyourself/gotestsum/releases/download/v${GOTESTSUM_VERSION}/gotestsum_${GOTESTSUM_VERSION}_${OS}_amd64.tar.gz | tar -zOxf - gotestsum > ./bin/gotestsum-${GOTESTSUM_VERSION} && chmod +x ./bin/gotestsum-${GOTESTSUM_VERSION}
|
||||||
|
|
||||||
|
TEST_PKGS ?= ./...
|
||||||
|
TEST_REPORT_NAME ?= results.xml
|
||||||
|
.PHONY: test
|
||||||
|
test: TEST_REPORT ?= main
|
||||||
|
test: TEST_FORMAT ?= short
|
||||||
|
test: SHELL = /bin/bash
|
||||||
|
test: bin/gotestsum ## Run tests
|
||||||
|
@mkdir -p ${BUILD_DIR}/test_results/${TEST_REPORT}
|
||||||
|
bin/gotestsum --no-summary=skipped --junitfile ${BUILD_DIR}/test_results/${TEST_REPORT}/${TEST_REPORT_NAME} --format ${TEST_FORMAT} -- $(filter-out -v,${GOARGS}) $(if ${TEST_PKGS},${TEST_PKGS},./...)
|
||||||
|
|
||||||
|
bin/golangci-lint: bin/golangci-lint-${GOLANGCI_VERSION}
|
||||||
|
@ln -sf golangci-lint-${GOLANGCI_VERSION} bin/golangci-lint
|
||||||
|
bin/golangci-lint-${GOLANGCI_VERSION}:
|
||||||
|
@mkdir -p bin
|
||||||
|
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | BINARY=golangci-lint bash -s -- v${GOLANGCI_VERSION}
|
||||||
|
@mv bin/golangci-lint $@
|
||||||
|
|
||||||
|
.PHONY: lint
|
||||||
|
lint: bin/golangci-lint ## Run linter
|
||||||
|
bin/golangci-lint run
|
||||||
|
|
||||||
|
.PHONY: fix
|
||||||
|
fix: bin/golangci-lint ## Fix lint violations
|
||||||
|
bin/golangci-lint run --fix
|
||||||
|
|
||||||
|
.PHONY: list
|
||||||
|
list: ## List all make targets
|
||||||
|
@${MAKE} -pRrn : -f $(MAKEFILE_LIST) 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | sort
|
||||||
|
|
||||||
|
.PHONY: help
|
||||||
|
.DEFAULT_GOAL := help
|
||||||
|
help:
|
||||||
|
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||||
|
|
||||||
|
# Variable outputting/exporting rules
|
||||||
|
var-%: ; @echo $($*)
|
||||||
|
varexport-%: ; @echo $*=$($*)
|
150
vendor/github.com/spf13/viper/README.md
generated
vendored
150
vendor/github.com/spf13/viper/README.md
generated
vendored
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
Go configuration with fangs!
|
Go configuration with fangs!
|
||||||
|
|
||||||
|
[![Actions](https://github.com/spf13/viper/workflows/CI/badge.svg)](https://github.com/spf13/viper)
|
||||||
|
[![Join the chat at https://gitter.im/spf13/viper](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
[![GoDoc](https://godoc.org/github.com/spf13/viper?status.svg)](https://godoc.org/github.com/spf13/viper)
|
||||||
|
|
||||||
Many Go projects are built using Viper including:
|
Many Go projects are built using Viper including:
|
||||||
|
|
||||||
* [Hugo](http://gohugo.io)
|
* [Hugo](http://gohugo.io)
|
||||||
@ -12,8 +16,14 @@ Many Go projects are built using Viper including:
|
|||||||
* [BloomApi](https://www.bloomapi.com/)
|
* [BloomApi](https://www.bloomapi.com/)
|
||||||
* [doctl](https://github.com/digitalocean/doctl)
|
* [doctl](https://github.com/digitalocean/doctl)
|
||||||
* [Clairctl](https://github.com/jgsqware/clairctl)
|
* [Clairctl](https://github.com/jgsqware/clairctl)
|
||||||
|
* [Mercure](https://mercure.rocks)
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/spf13/viper.svg)](https://travis-ci.org/spf13/viper) [![Join the chat at https://gitter.im/spf13/viper](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![GoDoc](https://godoc.org/github.com/spf13/viper?status.svg)](https://godoc.org/github.com/spf13/viper)
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```console
|
||||||
|
go get github.com/spf13/viper
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## What is Viper?
|
## What is Viper?
|
||||||
@ -23,7 +33,7 @@ to work within an application, and can handle all types of configuration needs
|
|||||||
and formats. It supports:
|
and formats. It supports:
|
||||||
|
|
||||||
* setting defaults
|
* setting defaults
|
||||||
* reading from JSON, TOML, YAML, HCL, and Java properties config files
|
* reading from JSON, TOML, YAML, HCL, envfile and Java properties config files
|
||||||
* live watching and re-reading of config files (optional)
|
* live watching and re-reading of config files (optional)
|
||||||
* reading from environment variables
|
* reading from environment variables
|
||||||
* reading from remote config systems (etcd or Consul), and watching changes
|
* reading from remote config systems (etcd or Consul), and watching changes
|
||||||
@ -31,8 +41,8 @@ and formats. It supports:
|
|||||||
* reading from buffer
|
* reading from buffer
|
||||||
* setting explicit values
|
* setting explicit values
|
||||||
|
|
||||||
Viper can be thought of as a registry for all of your applications
|
Viper can be thought of as a registry for all of your applications configuration needs.
|
||||||
configuration needs.
|
|
||||||
|
|
||||||
## Why Viper?
|
## Why Viper?
|
||||||
|
|
||||||
@ -42,34 +52,31 @@ Viper is here to help with that.
|
|||||||
|
|
||||||
Viper does the following for you:
|
Viper does the following for you:
|
||||||
|
|
||||||
1. Find, load, and unmarshal a configuration file in JSON, TOML, YAML, HCL, or Java properties formats.
|
1. Find, load, and unmarshal a configuration file in JSON, TOML, YAML, HCL, INI, envfile or Java properties formats.
|
||||||
2. Provide a mechanism to set default values for your different
|
2. Provide a mechanism to set default values for your different configuration options.
|
||||||
configuration options.
|
3. Provide a mechanism to set override values for options specified through command line flags.
|
||||||
3. Provide a mechanism to set override values for options specified through
|
4. Provide an alias system to easily rename parameters without breaking existing code.
|
||||||
command line flags.
|
5. Make it easy to tell the difference between when a user has provided a command line or config file which is the same as the default.
|
||||||
4. Provide an alias system to easily rename parameters without breaking existing
|
|
||||||
code.
|
|
||||||
5. Make it easy to tell the difference between when a user has provided a
|
|
||||||
command line or config file which is the same as the default.
|
|
||||||
|
|
||||||
Viper uses the following precedence order. Each item takes precedence over the
|
Viper uses the following precedence order. Each item takes precedence over the item below it:
|
||||||
item below it:
|
|
||||||
|
|
||||||
* explicit call to Set
|
* explicit call to `Set`
|
||||||
* flag
|
* flag
|
||||||
* env
|
* env
|
||||||
* config
|
* config
|
||||||
* key/value store
|
* key/value store
|
||||||
* default
|
* default
|
||||||
|
|
||||||
Viper configuration keys are case insensitive.
|
**Important:** Viper configuration keys are case insensitive.
|
||||||
|
There are ongoing discussions about making that optional.
|
||||||
|
|
||||||
|
|
||||||
## Putting Values into Viper
|
## Putting Values into Viper
|
||||||
|
|
||||||
### Establishing Defaults
|
### Establishing Defaults
|
||||||
|
|
||||||
A good configuration system will support default values. A default value is not
|
A good configuration system will support default values. A default value is not
|
||||||
required for a key, but it’s useful in the event that a key hasn’t been set via
|
required for a key, but it’s useful in the event that a key hasn't been set via
|
||||||
config file, environment variable, remote configuration or flag.
|
config file, environment variable, remote configuration or flag.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
@ -83,7 +90,7 @@ viper.SetDefault("Taxonomies", map[string]string{"tag": "tags", "category": "cat
|
|||||||
### Reading Config Files
|
### Reading Config Files
|
||||||
|
|
||||||
Viper requires minimal configuration so it knows where to look for config files.
|
Viper requires minimal configuration so it knows where to look for config files.
|
||||||
Viper supports JSON, TOML, YAML, HCL, and Java Properties files. Viper can search multiple paths, but
|
Viper supports JSON, TOML, YAML, HCL, INI, envfile and Java Properties files. Viper can search multiple paths, but
|
||||||
currently a single Viper instance only supports a single configuration file.
|
currently a single Viper instance only supports a single configuration file.
|
||||||
Viper does not default to any configuration search paths leaving defaults decision
|
Viper does not default to any configuration search paths leaving defaults decision
|
||||||
to an application.
|
to an application.
|
||||||
@ -103,6 +110,44 @@ if err != nil { // Handle errors reading the config file
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can handle the specific case where no config file is found like this:
|
||||||
|
|
||||||
|
```go
|
||||||
|
if err := viper.ReadInConfig(); err != nil {
|
||||||
|
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
|
||||||
|
// Config file not found; ignore error if desired
|
||||||
|
} else {
|
||||||
|
// Config file was found but another error was produced
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config file found and successfully parsed
|
||||||
|
```
|
||||||
|
|
||||||
|
*NOTE:* You can also have a file without an extension and specify the format programmaticaly. For those configuration files that lie in the home of the user without any extension like `.bashrc`
|
||||||
|
|
||||||
|
### Writing Config Files
|
||||||
|
|
||||||
|
Reading from config files is useful, but at times you want to store all modifications made at run time.
|
||||||
|
For that, a bunch of commands are available, each with its own purpose:
|
||||||
|
|
||||||
|
* WriteConfig - writes the current viper configuration to the predefined path, if exists. Errors if no predefined path. Will overwrite the current config file, if it exists.
|
||||||
|
* SafeWriteConfig - writes the current viper configuration to the predefined path. Errors if no predefined path. Will not overwrite the current config file, if it exists.
|
||||||
|
* WriteConfigAs - writes the current viper configuration to the given filepath. Will overwrite the given file, if it exists.
|
||||||
|
* SafeWriteConfigAs - writes the current viper configuration to the given filepath. Will not overwrite the given file, if it exists.
|
||||||
|
|
||||||
|
As a rule of the thumb, everything marked with safe won't overwrite any file, but just create if not existent, whilst the default behavior is to create or truncate.
|
||||||
|
|
||||||
|
A small examples section:
|
||||||
|
|
||||||
|
```go
|
||||||
|
viper.WriteConfig() // writes current config to predefined path set by 'viper.AddConfigPath()' and 'viper.SetConfigName'
|
||||||
|
viper.SafeWriteConfig()
|
||||||
|
viper.WriteConfigAs("/path/to/my/.config")
|
||||||
|
viper.SafeWriteConfigAs("/path/to/my/.config") // will error since it has already been written
|
||||||
|
viper.SafeWriteConfigAs("/path/to/my/.other_config")
|
||||||
|
```
|
||||||
|
|
||||||
### Watching and re-reading config files
|
### Watching and re-reading config files
|
||||||
|
|
||||||
Viper supports the ability to have your application live read a config file while running.
|
Viper supports the ability to have your application live read a config file while running.
|
||||||
@ -186,7 +231,7 @@ with ENV:
|
|||||||
* `BindEnv(string...) : error`
|
* `BindEnv(string...) : error`
|
||||||
* `SetEnvPrefix(string)`
|
* `SetEnvPrefix(string)`
|
||||||
* `SetEnvKeyReplacer(string...) *strings.Replacer`
|
* `SetEnvKeyReplacer(string...) *strings.Replacer`
|
||||||
* `AllowEmptyEnvVar(bool)`
|
* `AllowEmptyEnv(bool)`
|
||||||
|
|
||||||
_When working with ENV variables, it’s important to recognize that Viper
|
_When working with ENV variables, it’s important to recognize that Viper
|
||||||
treats ENV variables as case sensitive._
|
treats ENV variables as case sensitive._
|
||||||
@ -199,9 +244,9 @@ prefix.
|
|||||||
`BindEnv` takes one or two parameters. The first parameter is the key name, the
|
`BindEnv` takes one or two parameters. The first parameter is the key name, the
|
||||||
second is the name of the environment variable. The name of the environment
|
second is the name of the environment variable. The name of the environment
|
||||||
variable is case sensitive. If the ENV variable name is not provided, then
|
variable is case sensitive. If the ENV variable name is not provided, then
|
||||||
Viper will automatically assume that the key name matches the ENV variable name,
|
Viper will automatically assume that the ENV variable matches the following format: prefix + "_" + the key name in ALL CAPS. When you explicitly provide the ENV variable name (the second parameter),
|
||||||
but the ENV variable is IN ALL CAPS. When you explicitly provide the ENV
|
it **does not** automatically add the prefix. For example if the second parameter is "id",
|
||||||
variable name, it **does not** automatically add the prefix.
|
Viper will look for the ENV variable "ID".
|
||||||
|
|
||||||
One important thing to recognize when working with ENV variables is that the
|
One important thing to recognize when working with ENV variables is that the
|
||||||
value will be read each time it is accessed. Viper does not fix the value when
|
value will be read each time it is accessed. Viper does not fix the value when
|
||||||
@ -218,6 +263,9 @@ keys to an extent. This is useful if you want to use `-` or something in your
|
|||||||
`Get()` calls, but want your environmental variables to use `_` delimiters. An
|
`Get()` calls, but want your environmental variables to use `_` delimiters. An
|
||||||
example of using it can be found in `viper_test.go`.
|
example of using it can be found in `viper_test.go`.
|
||||||
|
|
||||||
|
Alternatively, you can use `EnvKeyReplacer` with `NewWithOptions` factory function.
|
||||||
|
Unlike `SetEnvKeyReplacer`, it accepts a `StringReplacer` interface allowing you to write custom string replacing logic.
|
||||||
|
|
||||||
By default empty environment variables are considered unset and will fall back to
|
By default empty environment variables are considered unset and will fall back to
|
||||||
the next configuration source. To treat empty environment variables as set, use
|
the next configuration source. To treat empty environment variables as set, use
|
||||||
the `AllowEmptyEnv` method.
|
the `AllowEmptyEnv` method.
|
||||||
@ -346,7 +394,7 @@ package:
|
|||||||
|
|
||||||
`import _ "github.com/spf13/viper/remote"`
|
`import _ "github.com/spf13/viper/remote"`
|
||||||
|
|
||||||
Viper will read a config string (as JSON, TOML, YAML or HCL) retrieved from a path
|
Viper will read a config string (as JSON, TOML, YAML, HCL or envfile) retrieved from a path
|
||||||
in a Key/Value store such as etcd or Consul. These values take precedence over
|
in a Key/Value store such as etcd or Consul. These values take precedence over
|
||||||
default values, but are overridden by configuration values retrieved from disk,
|
default values, but are overridden by configuration values retrieved from disk,
|
||||||
flags, or environment variables.
|
flags, or environment variables.
|
||||||
@ -381,7 +429,7 @@ how to use Consul.
|
|||||||
#### etcd
|
#### etcd
|
||||||
```go
|
```go
|
||||||
viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001","/config/hugo.json")
|
viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001","/config/hugo.json")
|
||||||
viper.SetConfigType("json") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop"
|
viper.SetConfigType("json") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop", "env", "dotenv"
|
||||||
err := viper.ReadRemoteConfig()
|
err := viper.ReadRemoteConfig()
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -409,7 +457,7 @@ fmt.Println(viper.Get("hostname")) // myhostname.com
|
|||||||
|
|
||||||
```go
|
```go
|
||||||
viper.AddSecureRemoteProvider("etcd","http://127.0.0.1:4001","/config/hugo.json","/etc/secrets/mykeyring.gpg")
|
viper.AddSecureRemoteProvider("etcd","http://127.0.0.1:4001","/config/hugo.json","/etc/secrets/mykeyring.gpg")
|
||||||
viper.SetConfigType("json") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop"
|
viper.SetConfigType("json") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop", "env", "dotenv"
|
||||||
err := viper.ReadRemoteConfig()
|
err := viper.ReadRemoteConfig()
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -420,7 +468,7 @@ err := viper.ReadRemoteConfig()
|
|||||||
var runtime_viper = viper.New()
|
var runtime_viper = viper.New()
|
||||||
|
|
||||||
runtime_viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001", "/config/hugo.yml")
|
runtime_viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001", "/config/hugo.yml")
|
||||||
runtime_viper.SetConfigType("yaml") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop"
|
runtime_viper.SetConfigType("yaml") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop", "env", "dotenv"
|
||||||
|
|
||||||
// read from remote config the first time.
|
// read from remote config the first time.
|
||||||
err := runtime_viper.ReadRemoteConfig()
|
err := runtime_viper.ReadRemoteConfig()
|
||||||
@ -456,6 +504,7 @@ The following functions and methods exist:
|
|||||||
* `GetBool(key string) : bool`
|
* `GetBool(key string) : bool`
|
||||||
* `GetFloat64(key string) : float64`
|
* `GetFloat64(key string) : float64`
|
||||||
* `GetInt(key string) : int`
|
* `GetInt(key string) : int`
|
||||||
|
* `GetIntSlice(key string) : []int`
|
||||||
* `GetString(key string) : string`
|
* `GetString(key string) : string`
|
||||||
* `GetStringMap(key string) : map[string]interface{}`
|
* `GetStringMap(key string) : map[string]interface{}`
|
||||||
* `GetStringMapString(key string) : map[string]string`
|
* `GetStringMapString(key string) : map[string]string`
|
||||||
@ -611,15 +660,43 @@ type config struct {
|
|||||||
|
|
||||||
var C config
|
var C config
|
||||||
|
|
||||||
err := Unmarshal(&C)
|
err := viper.Unmarshal(&C)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to decode into struct, %v", err)
|
t.Fatalf("unable to decode into struct, %v", err)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you want to unmarshal configuration where the keys themselves contain dot (the default key delimiter),
|
||||||
|
you have to change the delimiter:
|
||||||
|
|
||||||
|
```go
|
||||||
|
v := viper.NewWithOptions(viper.KeyDelimiter("::"))
|
||||||
|
|
||||||
|
v.SetDefault("chart::values", map[string]interface{}{
|
||||||
|
"ingress": map[string]interface{}{
|
||||||
|
"annotations": map[string]interface{}{
|
||||||
|
"traefik.frontend.rule.type": "PathPrefix",
|
||||||
|
"traefik.ingress.kubernetes.io/ssl-redirect": "true",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
type config struct {
|
||||||
|
Chart struct{
|
||||||
|
Values map[string]interface{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var C config
|
||||||
|
|
||||||
|
v.Unmarshal(&C)
|
||||||
|
```
|
||||||
|
|
||||||
|
Viper uses [github.com/mitchellh/mapstructure](https://github.com/mitchellh/mapstructure) under the hood for unmarshaling values which uses `mapstructure` tags by default.
|
||||||
|
|
||||||
### Marshalling to string
|
### Marshalling to string
|
||||||
|
|
||||||
You may need to marhsal all the settings held in viper into a string rather than write them to a file.
|
You may need to marshal all the settings held in viper into a string rather than write them to a file.
|
||||||
You can use your favorite format's marshaller with the config returned by `AllSettings()`.
|
You can use your favorite format's marshaller with the config returned by `AllSettings()`.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@ -630,11 +707,11 @@ import (
|
|||||||
|
|
||||||
func yamlStringSettings() string {
|
func yamlStringSettings() string {
|
||||||
c := viper.AllSettings()
|
c := viper.AllSettings()
|
||||||
bs, err := yaml.Marshal(c)
|
bs, err := yaml.Marshal(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to marshal config to YAML: %v", err)
|
log.Fatalf("unable to marshal config to YAML: %v", err)
|
||||||
}
|
}
|
||||||
return string(bs)
|
return string(bs)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -672,13 +749,6 @@ different vipers.
|
|||||||
|
|
||||||
## Q & A
|
## Q & A
|
||||||
|
|
||||||
Q: Why not INI files?
|
|
||||||
|
|
||||||
A: Ini files are pretty awful. There’s no standard format, and they are hard to
|
|
||||||
validate. Viper is designed to work with JSON, TOML or YAML files. If someone
|
|
||||||
really wants to add this feature, I’d be happy to merge it. It’s easy to specify
|
|
||||||
which formats your application will permit.
|
|
||||||
|
|
||||||
Q: Why is it called “Viper”?
|
Q: Why is it called “Viper”?
|
||||||
|
|
||||||
A: Viper is designed to be a [companion](http://en.wikipedia.org/wiki/Viper_(G.I._Joe))
|
A: Viper is designed to be a [companion](http://en.wikipedia.org/wiki/Viper_(G.I._Joe))
|
||||||
|
2
vendor/github.com/spf13/viper/flags.go
generated
vendored
2
vendor/github.com/spf13/viper/flags.go
generated
vendored
@ -36,7 +36,7 @@ type pflagValue struct {
|
|||||||
flag *pflag.Flag
|
flag *pflag.Flag
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasChanges returns whether the flag has changes or not.
|
// HasChanged returns whether the flag has changes or not.
|
||||||
func (p pflagValue) HasChanged() bool {
|
func (p pflagValue) HasChanged() bool {
|
||||||
return p.flag.Changed
|
return p.flag.Changed
|
||||||
}
|
}
|
||||||
|
9
vendor/github.com/spf13/viper/go.mod
generated
vendored
9
vendor/github.com/spf13/viper/go.mod
generated
vendored
@ -1,5 +1,7 @@
|
|||||||
module github.com/spf13/viper
|
module github.com/spf13/viper
|
||||||
|
|
||||||
|
go 1.12
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6 // indirect
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6 // indirect
|
||||||
github.com/coreos/bbolt v1.3.2 // indirect
|
github.com/coreos/bbolt v1.3.2 // indirect
|
||||||
@ -18,16 +20,18 @@ require (
|
|||||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0 // indirect
|
github.com/grpc-ecosystem/grpc-gateway v1.9.0 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0
|
github.com/hashicorp/hcl v1.0.0
|
||||||
github.com/jonboulle/clockwork v0.1.0 // indirect
|
github.com/jonboulle/clockwork v0.1.0 // indirect
|
||||||
github.com/magiconair/properties v1.8.0
|
github.com/magiconair/properties v1.8.1
|
||||||
github.com/mitchellh/mapstructure v1.1.2
|
github.com/mitchellh/mapstructure v1.1.2
|
||||||
github.com/pelletier/go-toml v1.2.0
|
github.com/pelletier/go-toml v1.2.0
|
||||||
github.com/prometheus/client_golang v0.9.3 // indirect
|
github.com/prometheus/client_golang v0.9.3 // indirect
|
||||||
|
github.com/smartystreets/goconvey v1.6.4 // indirect
|
||||||
github.com/soheilhy/cmux v0.1.4 // indirect
|
github.com/soheilhy/cmux v0.1.4 // indirect
|
||||||
github.com/spf13/afero v1.1.2
|
github.com/spf13/afero v1.1.2
|
||||||
github.com/spf13/cast v1.3.0
|
github.com/spf13/cast v1.3.0
|
||||||
github.com/spf13/jwalterweatherman v1.0.0
|
github.com/spf13/jwalterweatherman v1.0.0
|
||||||
github.com/spf13/pflag v1.0.3
|
github.com/spf13/pflag v1.0.3
|
||||||
github.com/stretchr/testify v1.2.2
|
github.com/stretchr/testify v1.2.2
|
||||||
|
github.com/subosito/gotenv v1.2.0
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect
|
||||||
github.com/ugorji/go v1.1.4 // indirect
|
github.com/ugorji/go v1.1.4 // indirect
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
|
||||||
@ -39,5 +43,6 @@ require (
|
|||||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092 // indirect
|
golang.org/x/net v0.0.0-20190522155817-f3200d17e092 // indirect
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect
|
||||||
google.golang.org/grpc v1.21.0 // indirect
|
google.golang.org/grpc v1.21.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.2.2
|
gopkg.in/ini.v1 v1.51.0
|
||||||
|
gopkg.in/yaml.v2 v2.2.4
|
||||||
)
|
)
|
||||||
|
22
vendor/github.com/spf13/viper/go.sum
generated
vendored
22
vendor/github.com/spf13/viper/go.sum
generated
vendored
@ -48,6 +48,8 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
|
|||||||
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
|
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||||
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c=
|
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c=
|
||||||
@ -60,6 +62,8 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
|||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo=
|
github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo=
|
||||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
|
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||||
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
@ -71,8 +75,8 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
|||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
|
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||||
@ -101,6 +105,10 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T
|
|||||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
|
github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||||
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
|
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||||
|
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
|
github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
|
||||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
@ -115,6 +123,8 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
|
|||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||||
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ=
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
github.com/ugorji/go v1.1.4 h1:j4s+tAvLfL3bZyefP2SEWmhBzmuIlH/eqNuPdFPgngw=
|
github.com/ugorji/go v1.1.4 h1:j4s+tAvLfL3bZyefP2SEWmhBzmuIlH/eqNuPdFPgngw=
|
||||||
@ -159,6 +169,8 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb
|
|||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384 h1:TFlARGu6Czu1z7q93HTxcP1P+/ZFC/IKythI5RzrnRg=
|
||||||
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
@ -170,9 +182,11 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+
|
|||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
|
||||||
|
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
6
vendor/github.com/spf13/viper/util.go
generated
vendored
6
vendor/github.com/spf13/viper/util.go
generated
vendored
@ -114,11 +114,11 @@ func absPathify(inPath string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if File / Directory Exists
|
// Check if file Exists
|
||||||
func exists(fs afero.Fs, path string) (bool, error) {
|
func exists(fs afero.Fs, path string) (bool, error) {
|
||||||
_, err := fs.Stat(path)
|
stat, err := fs.Stat(path)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return true, nil
|
return !stat.IsDir(), nil
|
||||||
}
|
}
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return false, nil
|
return false, nil
|
||||||
|
265
vendor/github.com/spf13/viper/viper.go
generated
vendored
265
vendor/github.com/spf13/viper/viper.go
generated
vendored
@ -3,7 +3,7 @@
|
|||||||
// Use of this source code is governed by an MIT-style
|
// Use of this source code is governed by an MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Viper is a application configuration system.
|
// Viper is an application configuration system.
|
||||||
// It believes that applications can be configured a variety of ways
|
// It believes that applications can be configured a variety of ways
|
||||||
// via flags, ENVIRONMENT variables, configuration files retrieved
|
// via flags, ENVIRONMENT variables, configuration files retrieved
|
||||||
// from the file system, or a remote key/value store.
|
// from the file system, or a remote key/value store.
|
||||||
@ -23,6 +23,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/csv"
|
"encoding/csv"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
@ -33,18 +34,19 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
yaml "gopkg.in/yaml.v2"
|
|
||||||
|
|
||||||
"github.com/fsnotify/fsnotify"
|
"github.com/fsnotify/fsnotify"
|
||||||
"github.com/hashicorp/hcl"
|
"github.com/hashicorp/hcl"
|
||||||
"github.com/hashicorp/hcl/hcl/printer"
|
"github.com/hashicorp/hcl/hcl/printer"
|
||||||
"github.com/magiconair/properties"
|
"github.com/magiconair/properties"
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
toml "github.com/pelletier/go-toml"
|
"github.com/pelletier/go-toml"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/spf13/cast"
|
"github.com/spf13/cast"
|
||||||
jww "github.com/spf13/jwalterweatherman"
|
jww "github.com/spf13/jwalterweatherman"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
"github.com/subosito/gotenv"
|
||||||
|
"gopkg.in/ini.v1"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConfigMarshalError happens when failing to marshal the configuration.
|
// ConfigMarshalError happens when failing to marshal the configuration.
|
||||||
@ -114,6 +116,14 @@ func (fnfe ConfigFileNotFoundError) Error() string {
|
|||||||
return fmt.Sprintf("Config File %q Not Found in %q", fnfe.name, fnfe.locations)
|
return fmt.Sprintf("Config File %q Not Found in %q", fnfe.name, fnfe.locations)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConfigFileAlreadyExistsError denotes failure to write new configuration file.
|
||||||
|
type ConfigFileAlreadyExistsError string
|
||||||
|
|
||||||
|
// Error returns the formatted error when configuration already exists.
|
||||||
|
func (faee ConfigFileAlreadyExistsError) Error() string {
|
||||||
|
return fmt.Sprintf("Config File %q Already Exists", string(faee))
|
||||||
|
}
|
||||||
|
|
||||||
// A DecoderConfigOption can be passed to viper.Unmarshal to configure
|
// A DecoderConfigOption can be passed to viper.Unmarshal to configure
|
||||||
// mapstructure.DecoderConfig options
|
// mapstructure.DecoderConfig options
|
||||||
type DecoderConfigOption func(*mapstructure.DecoderConfig)
|
type DecoderConfigOption func(*mapstructure.DecoderConfig)
|
||||||
@ -187,7 +197,7 @@ type Viper struct {
|
|||||||
envPrefix string
|
envPrefix string
|
||||||
|
|
||||||
automaticEnvApplied bool
|
automaticEnvApplied bool
|
||||||
envKeyReplacer *strings.Replacer
|
envKeyReplacer StringReplacer
|
||||||
allowEmptyEnv bool
|
allowEmptyEnv bool
|
||||||
|
|
||||||
config map[string]interface{}
|
config map[string]interface{}
|
||||||
@ -225,12 +235,58 @@ func New() *Viper {
|
|||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Intended for testing, will reset all to default settings.
|
// Option configures Viper using the functional options paradigm popularized by Rob Pike and Dave Cheney.
|
||||||
|
// If you're unfamiliar with this style,
|
||||||
|
// see https://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html and
|
||||||
|
// https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis.
|
||||||
|
type Option interface {
|
||||||
|
apply(v *Viper)
|
||||||
|
}
|
||||||
|
|
||||||
|
type optionFunc func(v *Viper)
|
||||||
|
|
||||||
|
func (fn optionFunc) apply(v *Viper) {
|
||||||
|
fn(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyDelimiter sets the delimiter used for determining key parts.
|
||||||
|
// By default it's value is ".".
|
||||||
|
func KeyDelimiter(d string) Option {
|
||||||
|
return optionFunc(func(v *Viper) {
|
||||||
|
v.keyDelim = d
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringReplacer applies a set of replacements to a string.
|
||||||
|
type StringReplacer interface {
|
||||||
|
// Replace returns a copy of s with all replacements performed.
|
||||||
|
Replace(s string) string
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnvKeyReplacer sets a replacer used for mapping environment variables to internal keys.
|
||||||
|
func EnvKeyReplacer(r StringReplacer) Option {
|
||||||
|
return optionFunc(func(v *Viper) {
|
||||||
|
v.envKeyReplacer = r
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithOptions creates a new Viper instance.
|
||||||
|
func NewWithOptions(opts ...Option) *Viper {
|
||||||
|
v := New()
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt.apply(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset is intended for testing, will reset all to default settings.
|
||||||
// In the public interface for the viper package so applications
|
// In the public interface for the viper package so applications
|
||||||
// can use it in their testing as well.
|
// can use it in their testing as well.
|
||||||
func Reset() {
|
func Reset() {
|
||||||
v = New()
|
v = New()
|
||||||
SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl"}
|
SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "dotenv", "env", "ini"}
|
||||||
SupportedRemoteProviders = []string{"etcd", "consul"}
|
SupportedRemoteProviders = []string{"etcd", "consul"}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,7 +325,7 @@ type RemoteProvider interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SupportedExts are universally supported extensions.
|
// SupportedExts are universally supported extensions.
|
||||||
var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl"}
|
var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "dotenv", "env", "ini"}
|
||||||
|
|
||||||
// SupportedRemoteProviders are universally supported remote providers.
|
// SupportedRemoteProviders are universally supported remote providers.
|
||||||
var SupportedRemoteProviders = []string{"etcd", "consul"}
|
var SupportedRemoteProviders = []string{"etcd", "consul"}
|
||||||
@ -294,6 +350,7 @@ func (v *Viper) WatchConfig() {
|
|||||||
filename, err := v.getConfigFile()
|
filename, err := v.getConfigFile()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error: %v\n", err)
|
log.Printf("error: %v\n", err)
|
||||||
|
initWG.Done()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,7 +400,7 @@ func (v *Viper) WatchConfig() {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
watcher.Add(configDir)
|
watcher.Add(configDir)
|
||||||
initWG.Done() // done initalizing the watch in this go routine, so the parent routine can move on...
|
initWG.Done() // done initializing the watch in this go routine, so the parent routine can move on...
|
||||||
eventsWG.Wait() // now, wait for event loop to end in this go-routine...
|
eventsWG.Wait() // now, wait for event loop to end in this go-routine...
|
||||||
}()
|
}()
|
||||||
initWG.Wait() // make sure that the go routine above fully ended before returning
|
initWG.Wait() // make sure that the go routine above fully ended before returning
|
||||||
@ -668,7 +725,7 @@ func GetViper() *Viper {
|
|||||||
func Get(key string) interface{} { return v.Get(key) }
|
func Get(key string) interface{} { return v.Get(key) }
|
||||||
func (v *Viper) Get(key string) interface{} {
|
func (v *Viper) Get(key string) interface{} {
|
||||||
lcaseKey := strings.ToLower(key)
|
lcaseKey := strings.ToLower(key)
|
||||||
val := v.find(lcaseKey)
|
val := v.find(lcaseKey, true)
|
||||||
if val == nil {
|
if val == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -705,6 +762,8 @@ func (v *Viper) Get(key string) interface{} {
|
|||||||
return cast.ToDuration(val)
|
return cast.ToDuration(val)
|
||||||
case []string:
|
case []string:
|
||||||
return cast.ToStringSlice(val)
|
return cast.ToStringSlice(val)
|
||||||
|
case []int:
|
||||||
|
return cast.ToIntSlice(val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -794,6 +853,12 @@ func (v *Viper) GetDuration(key string) time.Duration {
|
|||||||
return cast.ToDuration(v.Get(key))
|
return cast.ToDuration(v.Get(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetIntSlice returns the value associated with the key as a slice of int values.
|
||||||
|
func GetIntSlice(key string) []int { return v.GetIntSlice(key) }
|
||||||
|
func (v *Viper) GetIntSlice(key string) []int {
|
||||||
|
return cast.ToIntSlice(v.Get(key))
|
||||||
|
}
|
||||||
|
|
||||||
// GetStringSlice returns the value associated with the key as a slice of strings.
|
// GetStringSlice returns the value associated with the key as a slice of strings.
|
||||||
func GetStringSlice(key string) []string { return v.GetStringSlice(key) }
|
func GetStringSlice(key string) []string { return v.GetStringSlice(key) }
|
||||||
func (v *Viper) GetStringSlice(key string) []string {
|
func (v *Viper) GetStringSlice(key string) []string {
|
||||||
@ -884,8 +949,11 @@ func decode(input interface{}, config *mapstructure.DecoderConfig) error {
|
|||||||
|
|
||||||
// UnmarshalExact unmarshals the config into a Struct, erroring if a field is nonexistent
|
// UnmarshalExact unmarshals the config into a Struct, erroring if a field is nonexistent
|
||||||
// in the destination struct.
|
// in the destination struct.
|
||||||
func (v *Viper) UnmarshalExact(rawVal interface{}) error {
|
func UnmarshalExact(rawVal interface{}, opts ...DecoderConfigOption) error {
|
||||||
config := defaultDecoderConfig(rawVal)
|
return v.UnmarshalExact(rawVal, opts...)
|
||||||
|
}
|
||||||
|
func (v *Viper) UnmarshalExact(rawVal interface{}, opts ...DecoderConfigOption) error {
|
||||||
|
config := defaultDecoderConfig(rawVal, opts...)
|
||||||
config.ErrorUnused = true
|
config.ErrorUnused = true
|
||||||
|
|
||||||
err := decode(v.AllSettings(), config)
|
err := decode(v.AllSettings(), config)
|
||||||
@ -950,7 +1018,7 @@ func BindEnv(input ...string) error { return v.BindEnv(input...) }
|
|||||||
func (v *Viper) BindEnv(input ...string) error {
|
func (v *Viper) BindEnv(input ...string) error {
|
||||||
var key, envkey string
|
var key, envkey string
|
||||||
if len(input) == 0 {
|
if len(input) == 0 {
|
||||||
return fmt.Errorf("BindEnv missing key to bind to")
|
return fmt.Errorf("missing key to bind to")
|
||||||
}
|
}
|
||||||
|
|
||||||
key = strings.ToLower(input[0])
|
key = strings.ToLower(input[0])
|
||||||
@ -967,12 +1035,15 @@ func (v *Viper) BindEnv(input ...string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Given a key, find the value.
|
// Given a key, find the value.
|
||||||
// Viper will check in the following order:
|
//
|
||||||
// flag, env, config file, key/value store, default.
|
|
||||||
// Viper will check to see if an alias exists first.
|
// Viper will check to see if an alias exists first.
|
||||||
|
// Viper will then check in the following order:
|
||||||
|
// flag, env, config file, key/value store.
|
||||||
|
// Lastly, if no value was found and flagDefault is true, and if the key
|
||||||
|
// corresponds to a flag, the flag's default value is returned.
|
||||||
|
//
|
||||||
// Note: this assumes a lower-cased key given.
|
// Note: this assumes a lower-cased key given.
|
||||||
func (v *Viper) find(lcaseKey string) interface{} {
|
func (v *Viper) find(lcaseKey string, flagDefault bool) interface{} {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
val interface{}
|
val interface{}
|
||||||
exists bool
|
exists bool
|
||||||
@ -1012,6 +1083,11 @@ func (v *Viper) find(lcaseKey string) interface{} {
|
|||||||
s = strings.TrimSuffix(s, "]")
|
s = strings.TrimSuffix(s, "]")
|
||||||
res, _ := readAsCSV(s)
|
res, _ := readAsCSV(s)
|
||||||
return res
|
return res
|
||||||
|
case "intSlice":
|
||||||
|
s := strings.TrimPrefix(flag.ValueString(), "[")
|
||||||
|
s = strings.TrimSuffix(s, "]")
|
||||||
|
res, _ := readAsCSV(s)
|
||||||
|
return cast.ToIntSlice(res)
|
||||||
default:
|
default:
|
||||||
return flag.ValueString()
|
return flag.ValueString()
|
||||||
}
|
}
|
||||||
@ -1068,24 +1144,31 @@ func (v *Viper) find(lcaseKey string) interface{} {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// last chance: if no other value is returned and a flag does exist for the value,
|
if flagDefault {
|
||||||
// get the flag's value even if the flag's value has not changed
|
// last chance: if no value is found and a flag does exist for the key,
|
||||||
if flag, exists := v.pflags[lcaseKey]; exists {
|
// get the flag's default value even if the flag's value has not been set.
|
||||||
switch flag.ValueType() {
|
if flag, exists := v.pflags[lcaseKey]; exists {
|
||||||
case "int", "int8", "int16", "int32", "int64":
|
switch flag.ValueType() {
|
||||||
return cast.ToInt(flag.ValueString())
|
case "int", "int8", "int16", "int32", "int64":
|
||||||
case "bool":
|
return cast.ToInt(flag.ValueString())
|
||||||
return cast.ToBool(flag.ValueString())
|
case "bool":
|
||||||
case "stringSlice":
|
return cast.ToBool(flag.ValueString())
|
||||||
s := strings.TrimPrefix(flag.ValueString(), "[")
|
case "stringSlice":
|
||||||
s = strings.TrimSuffix(s, "]")
|
s := strings.TrimPrefix(flag.ValueString(), "[")
|
||||||
res, _ := readAsCSV(s)
|
s = strings.TrimSuffix(s, "]")
|
||||||
return res
|
res, _ := readAsCSV(s)
|
||||||
default:
|
return res
|
||||||
return flag.ValueString()
|
case "intSlice":
|
||||||
|
s := strings.TrimPrefix(flag.ValueString(), "[")
|
||||||
|
s = strings.TrimSuffix(s, "]")
|
||||||
|
res, _ := readAsCSV(s)
|
||||||
|
return cast.ToIntSlice(res)
|
||||||
|
default:
|
||||||
|
return flag.ValueString()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// last item, no need to check shadowing
|
||||||
}
|
}
|
||||||
// last item, no need to check shadowing
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -1104,7 +1187,7 @@ func readAsCSV(val string) ([]string, error) {
|
|||||||
func IsSet(key string) bool { return v.IsSet(key) }
|
func IsSet(key string) bool { return v.IsSet(key) }
|
||||||
func (v *Viper) IsSet(key string) bool {
|
func (v *Viper) IsSet(key string) bool {
|
||||||
lcaseKey := strings.ToLower(key)
|
lcaseKey := strings.ToLower(key)
|
||||||
val := v.find(lcaseKey)
|
val := v.find(lcaseKey, false)
|
||||||
return val != nil
|
return val != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1123,8 +1206,8 @@ func (v *Viper) SetEnvKeyReplacer(r *strings.Replacer) {
|
|||||||
v.envKeyReplacer = r
|
v.envKeyReplacer = r
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aliases provide another accessor for the same key.
|
// RegisterAlias creates an alias that provides another accessor for the same key.
|
||||||
// This enables one to change a name without breaking the application
|
// This enables one to change a name without breaking the application.
|
||||||
func RegisterAlias(alias string, key string) { v.RegisterAlias(alias, key) }
|
func RegisterAlias(alias string, key string) { v.RegisterAlias(alias, key) }
|
||||||
func (v *Viper) RegisterAlias(alias string, key string) {
|
func (v *Viper) RegisterAlias(alias string, key string) {
|
||||||
v.registerAlias(alias, strings.ToLower(key))
|
v.registerAlias(alias, strings.ToLower(key))
|
||||||
@ -1311,11 +1394,10 @@ func (v *Viper) WriteConfig() error {
|
|||||||
// SafeWriteConfig writes current configuration to file only if the file does not exist.
|
// SafeWriteConfig writes current configuration to file only if the file does not exist.
|
||||||
func SafeWriteConfig() error { return v.SafeWriteConfig() }
|
func SafeWriteConfig() error { return v.SafeWriteConfig() }
|
||||||
func (v *Viper) SafeWriteConfig() error {
|
func (v *Viper) SafeWriteConfig() error {
|
||||||
filename, err := v.getConfigFile()
|
if len(v.configPaths) < 1 {
|
||||||
if err != nil {
|
return errors.New("missing configuration for 'configPath'")
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
return v.writeConfig(filename, false)
|
return v.SafeWriteConfigAs(filepath.Join(v.configPaths[0], v.configName+"."+v.configType))
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteConfigAs writes current configuration to a given filename.
|
// WriteConfigAs writes current configuration to a given filename.
|
||||||
@ -1327,15 +1409,18 @@ func (v *Viper) WriteConfigAs(filename string) error {
|
|||||||
// SafeWriteConfigAs writes current configuration to a given filename if it does not exist.
|
// SafeWriteConfigAs writes current configuration to a given filename if it does not exist.
|
||||||
func SafeWriteConfigAs(filename string) error { return v.SafeWriteConfigAs(filename) }
|
func SafeWriteConfigAs(filename string) error { return v.SafeWriteConfigAs(filename) }
|
||||||
func (v *Viper) SafeWriteConfigAs(filename string) error {
|
func (v *Viper) SafeWriteConfigAs(filename string) error {
|
||||||
|
alreadyExists, err := afero.Exists(v.fs, filename)
|
||||||
|
if alreadyExists && err == nil {
|
||||||
|
return ConfigFileAlreadyExistsError(filename)
|
||||||
|
}
|
||||||
return v.writeConfig(filename, false)
|
return v.writeConfig(filename, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeConfig(filename string, force bool) error { return v.writeConfig(filename, force) }
|
|
||||||
func (v *Viper) writeConfig(filename string, force bool) error {
|
func (v *Viper) writeConfig(filename string, force bool) error {
|
||||||
jww.INFO.Println("Attempting to write configuration to file.")
|
jww.INFO.Println("Attempting to write configuration to file.")
|
||||||
ext := filepath.Ext(filename)
|
ext := filepath.Ext(filename)
|
||||||
if len(ext) <= 1 {
|
if len(ext) <= 1 {
|
||||||
return fmt.Errorf("Filename: %s requires valid extension.", filename)
|
return fmt.Errorf("filename: %s requires valid extension", filename)
|
||||||
}
|
}
|
||||||
configType := ext[1:]
|
configType := ext[1:]
|
||||||
if !stringInSlice(configType, SupportedExts) {
|
if !stringInSlice(configType, SupportedExts) {
|
||||||
@ -1344,21 +1429,21 @@ func (v *Viper) writeConfig(filename string, force bool) error {
|
|||||||
if v.config == nil {
|
if v.config == nil {
|
||||||
v.config = make(map[string]interface{})
|
v.config = make(map[string]interface{})
|
||||||
}
|
}
|
||||||
var flags int
|
flags := os.O_CREATE | os.O_TRUNC | os.O_WRONLY
|
||||||
if force == true {
|
if !force {
|
||||||
flags = os.O_CREATE | os.O_TRUNC | os.O_WRONLY
|
flags |= os.O_EXCL
|
||||||
} else {
|
|
||||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
|
||||||
flags = os.O_WRONLY
|
|
||||||
} else {
|
|
||||||
return fmt.Errorf("File: %s exists. Use WriteConfig to overwrite.", filename)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
f, err := v.fs.OpenFile(filename, flags, v.configPermissions)
|
f, err := v.fs.OpenFile(filename, flags, v.configPermissions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return v.marshalWriter(f, configType)
|
defer f.Close()
|
||||||
|
|
||||||
|
if err := v.marshalWriter(f, configType); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return f.Sync()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshal a Reader into a map.
|
// Unmarshal a Reader into a map.
|
||||||
@ -1382,7 +1467,7 @@ func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case "hcl":
|
case "hcl":
|
||||||
obj, err := hcl.Parse(string(buf.Bytes()))
|
obj, err := hcl.Parse(buf.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ConfigParseError{err}
|
return ConfigParseError{err}
|
||||||
}
|
}
|
||||||
@ -1400,6 +1485,15 @@ func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error {
|
|||||||
c[k] = v
|
c[k] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "dotenv", "env":
|
||||||
|
env, err := gotenv.StrictParse(buf)
|
||||||
|
if err != nil {
|
||||||
|
return ConfigParseError{err}
|
||||||
|
}
|
||||||
|
for k, v := range env {
|
||||||
|
c[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
case "properties", "props", "prop":
|
case "properties", "props", "prop":
|
||||||
v.properties = properties.NewProperties()
|
v.properties = properties.NewProperties()
|
||||||
var err error
|
var err error
|
||||||
@ -1415,6 +1509,23 @@ func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error {
|
|||||||
// set innermost value
|
// set innermost value
|
||||||
deepestMap[lastKey] = value
|
deepestMap[lastKey] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "ini":
|
||||||
|
cfg := ini.Empty()
|
||||||
|
err := cfg.Append(buf.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return ConfigParseError{err}
|
||||||
|
}
|
||||||
|
sections := cfg.Sections()
|
||||||
|
for i := 0; i < len(sections); i++ {
|
||||||
|
section := sections[i]
|
||||||
|
keys := section.Keys()
|
||||||
|
for j := 0; j < len(keys); j++ {
|
||||||
|
key := keys[j]
|
||||||
|
value := cfg.Section(section.Name()).Key(key.Name()).String()
|
||||||
|
c[section.Name()+"."+key.Name()] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
insensitiviseMap(c)
|
insensitiviseMap(c)
|
||||||
@ -1422,9 +1533,6 @@ func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Marshal a map into Writer.
|
// Marshal a map into Writer.
|
||||||
func marshalWriter(f afero.File, configType string) error {
|
|
||||||
return v.marshalWriter(f, configType)
|
|
||||||
}
|
|
||||||
func (v *Viper) marshalWriter(f afero.File, configType string) error {
|
func (v *Viper) marshalWriter(f afero.File, configType string) error {
|
||||||
c := v.AllSettings()
|
c := v.AllSettings()
|
||||||
switch configType {
|
switch configType {
|
||||||
@ -1440,6 +1548,9 @@ func (v *Viper) marshalWriter(f afero.File, configType string) error {
|
|||||||
|
|
||||||
case "hcl":
|
case "hcl":
|
||||||
b, err := json.Marshal(c)
|
b, err := json.Marshal(c)
|
||||||
|
if err != nil {
|
||||||
|
return ConfigMarshalError{err}
|
||||||
|
}
|
||||||
ast, err := hcl.Parse(string(b))
|
ast, err := hcl.Parse(string(b))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ConfigMarshalError{err}
|
return ConfigMarshalError{err}
|
||||||
@ -1465,6 +1576,18 @@ func (v *Viper) marshalWriter(f afero.File, configType string) error {
|
|||||||
return ConfigMarshalError{err}
|
return ConfigMarshalError{err}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "dotenv", "env":
|
||||||
|
lines := []string{}
|
||||||
|
for _, key := range v.AllKeys() {
|
||||||
|
envName := strings.ToUpper(strings.Replace(key, ".", "_", -1))
|
||||||
|
val := v.Get(key)
|
||||||
|
lines = append(lines, fmt.Sprintf("%v=%v", envName, val))
|
||||||
|
}
|
||||||
|
s := strings.Join(lines, "\n")
|
||||||
|
if _, err := f.WriteString(s); err != nil {
|
||||||
|
return ConfigMarshalError{err}
|
||||||
|
}
|
||||||
|
|
||||||
case "toml":
|
case "toml":
|
||||||
t, err := toml.TreeFromMap(c)
|
t, err := toml.TreeFromMap(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1483,6 +1606,22 @@ func (v *Viper) marshalWriter(f afero.File, configType string) error {
|
|||||||
if _, err = f.WriteString(string(b)); err != nil {
|
if _, err = f.WriteString(string(b)); err != nil {
|
||||||
return ConfigMarshalError{err}
|
return ConfigMarshalError{err}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "ini":
|
||||||
|
keys := v.AllKeys()
|
||||||
|
cfg := ini.Empty()
|
||||||
|
ini.PrettyFormat = false
|
||||||
|
for i := 0; i < len(keys); i++ {
|
||||||
|
key := keys[i]
|
||||||
|
lastSep := strings.LastIndex(key, ".")
|
||||||
|
sectionName := key[:(lastSep)]
|
||||||
|
keyName := key[(lastSep + 1):]
|
||||||
|
if sectionName == "default" {
|
||||||
|
sectionName = ""
|
||||||
|
}
|
||||||
|
cfg.Section(sectionName).Key(keyName).SetValue(Get(key).(string))
|
||||||
|
}
|
||||||
|
cfg.WriteTo(f)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -1629,7 +1768,7 @@ func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]interface{}
|
|||||||
func (v *Viper) watchKeyValueConfigOnChannel() error {
|
func (v *Viper) watchKeyValueConfigOnChannel() error {
|
||||||
for _, rp := range v.remoteProviders {
|
for _, rp := range v.remoteProviders {
|
||||||
respc, _ := RemoteConfig.WatchChannel(rp)
|
respc, _ := RemoteConfig.WatchChannel(rp)
|
||||||
//Todo: Add quit channel
|
// Todo: Add quit channel
|
||||||
go func(rc <-chan *RemoteResponse) {
|
go func(rc <-chan *RemoteResponse) {
|
||||||
for {
|
for {
|
||||||
b := <-rc
|
b := <-rc
|
||||||
@ -1665,7 +1804,7 @@ func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]interface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AllKeys returns all keys holding a value, regardless of where they are set.
|
// AllKeys returns all keys holding a value, regardless of where they are set.
|
||||||
// Nested keys are returned with a v.keyDelim (= ".") separator
|
// Nested keys are returned with a v.keyDelim separator
|
||||||
func AllKeys() []string { return v.AllKeys() }
|
func AllKeys() []string { return v.AllKeys() }
|
||||||
func (v *Viper) AllKeys() []string {
|
func (v *Viper) AllKeys() []string {
|
||||||
m := map[string]bool{}
|
m := map[string]bool{}
|
||||||
@ -1679,7 +1818,7 @@ func (v *Viper) AllKeys() []string {
|
|||||||
m = v.flattenAndMergeMap(m, v.defaults, "")
|
m = v.flattenAndMergeMap(m, v.defaults, "")
|
||||||
|
|
||||||
// convert set of paths to list
|
// convert set of paths to list
|
||||||
a := []string{}
|
a := make([]string, 0, len(m))
|
||||||
for x := range m {
|
for x := range m {
|
||||||
a = append(a, x)
|
a = append(a, x)
|
||||||
}
|
}
|
||||||
@ -1688,7 +1827,7 @@ func (v *Viper) AllKeys() []string {
|
|||||||
|
|
||||||
// flattenAndMergeMap recursively flattens the given map into a map[string]bool
|
// flattenAndMergeMap recursively flattens the given map into a map[string]bool
|
||||||
// of key paths (used as a set, easier to manipulate than a []string):
|
// of key paths (used as a set, easier to manipulate than a []string):
|
||||||
// - each path is merged into a single key string, delimited with v.keyDelim (= ".")
|
// - each path is merged into a single key string, delimited with v.keyDelim
|
||||||
// - if a path is shadowed by an earlier value in the initial shadow map,
|
// - if a path is shadowed by an earlier value in the initial shadow map,
|
||||||
// it is skipped.
|
// it is skipped.
|
||||||
// The resulting set of paths is merged to the given shadow set at the same time.
|
// The resulting set of paths is merged to the given shadow set at the same time.
|
||||||
@ -1728,7 +1867,7 @@ func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]interfac
|
|||||||
func (v *Viper) mergeFlatMap(shadow map[string]bool, m map[string]interface{}) map[string]bool {
|
func (v *Viper) mergeFlatMap(shadow map[string]bool, m map[string]interface{}) map[string]bool {
|
||||||
// scan keys
|
// scan keys
|
||||||
outer:
|
outer:
|
||||||
for k, _ := range m {
|
for k := range m {
|
||||||
path := strings.Split(k, v.keyDelim)
|
path := strings.Split(k, v.keyDelim)
|
||||||
// scan intermediate paths
|
// scan intermediate paths
|
||||||
var parentKey string
|
var parentKey string
|
||||||
@ -1837,6 +1976,10 @@ func (v *Viper) searchInPath(in string) (filename string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if b, _ := exists(v.fs, filepath.Join(in, v.configName)); b {
|
||||||
|
return filepath.Join(in, v.configName)
|
||||||
|
}
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
vendor/github.com/subosito/gotenv/.env
generated
vendored
Normal file
1
vendor/github.com/subosito/gotenv/.env
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
HELLO=world
|
1
vendor/github.com/subosito/gotenv/.env.invalid
generated
vendored
Normal file
1
vendor/github.com/subosito/gotenv/.env.invalid
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
lol$wut
|
3
vendor/github.com/subosito/gotenv/.gitignore
generated
vendored
Normal file
3
vendor/github.com/subosito/gotenv/.gitignore
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
*.test
|
||||||
|
*.out
|
||||||
|
annotate.json
|
10
vendor/github.com/subosito/gotenv/.travis.yml
generated
vendored
Normal file
10
vendor/github.com/subosito/gotenv/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
language: go
|
||||||
|
go:
|
||||||
|
- 1.x
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
- osx
|
||||||
|
script:
|
||||||
|
- go test -test.v -coverprofile=coverage.out -covermode=count
|
||||||
|
after_success:
|
||||||
|
- bash <(curl -s https://codecov.io/bash)
|
47
vendor/github.com/subosito/gotenv/CHANGELOG.md
generated
vendored
Normal file
47
vendor/github.com/subosito/gotenv/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## [1.2.0] - 2019-08-03
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Add `Must` helper to raise an error as panic. It can be used with `Load` and `OverLoad`.
|
||||||
|
- Add more tests to be 100% coverage.
|
||||||
|
- Add CHANGELOG
|
||||||
|
- Add more OS for the test: OSX and Windows
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Reduce complexity and improve source code for having `A+` score in [goreportcard](https://goreportcard.com/report/github.com/subosito/gotenv).
|
||||||
|
- Updated README with mentions to all available functions
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- Remove `ErrFormat`
|
||||||
|
- Remove `MustLoad` and `MustOverload`, replaced with `Must` helper.
|
||||||
|
|
||||||
|
## [1.1.1] - 2018-06-05
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Replace `os.Getenv` with `os.LookupEnv` to ensure that the environment variable is not set, by [radding](https://github.com/radding)
|
||||||
|
|
||||||
|
## [1.1.0] - 2017-03-20
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Supports carriage return in env
|
||||||
|
- Handle files with UTF-8 BOM
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Whitespace handling
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Incorrect variable expansion
|
||||||
|
- Handling escaped '$' characters
|
||||||
|
|
||||||
|
## [1.0.0] - 2014-10-05
|
||||||
|
|
||||||
|
First stable release.
|
||||||
|
|
21
vendor/github.com/subosito/gotenv/LICENSE
generated
vendored
Normal file
21
vendor/github.com/subosito/gotenv/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2013 Alif Rachmawadi
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
131
vendor/github.com/subosito/gotenv/README.md
generated
vendored
Normal file
131
vendor/github.com/subosito/gotenv/README.md
generated
vendored
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
# gotenv
|
||||||
|
|
||||||
|
[![Build Status](https://travis-ci.org/subosito/gotenv.svg?branch=master)](https://travis-ci.org/subosito/gotenv)
|
||||||
|
[![Build status](https://ci.appveyor.com/api/projects/status/wb2e075xkfl0m0v2/branch/master?svg=true)](https://ci.appveyor.com/project/subosito/gotenv/branch/master)
|
||||||
|
[![Coverage Status](https://badgen.net/codecov/c/github/subosito/gotenv)](https://codecov.io/gh/subosito/gotenv)
|
||||||
|
[![Go Report Card](https://goreportcard.com/badge/github.com/subosito/gotenv)](https://goreportcard.com/report/github.com/subosito/gotenv)
|
||||||
|
[![GoDoc](https://godoc.org/github.com/subosito/gotenv?status.svg)](https://godoc.org/github.com/subosito/gotenv)
|
||||||
|
|
||||||
|
Load environment variables dynamically in Go.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Put the gotenv package on your `import` statement:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import "github.com/subosito/gotenv"
|
||||||
|
```
|
||||||
|
|
||||||
|
To modify your app environment variables, `gotenv` expose 2 main functions:
|
||||||
|
|
||||||
|
- `gotenv.Load`
|
||||||
|
- `gotenv.Apply`
|
||||||
|
|
||||||
|
By default, `gotenv.Load` will look for a file called `.env` in the current working directory.
|
||||||
|
|
||||||
|
Behind the scene, it will then load `.env` file and export the valid variables to the environment variables. Make sure you call the method as soon as possible to ensure it loads all variables, say, put it on `init()` function.
|
||||||
|
|
||||||
|
Once loaded you can use `os.Getenv()` to get the value of the variable.
|
||||||
|
|
||||||
|
Let's say you have `.env` file:
|
||||||
|
|
||||||
|
```
|
||||||
|
APP_ID=1234567
|
||||||
|
APP_SECRET=abcdef
|
||||||
|
```
|
||||||
|
|
||||||
|
Here's the example of your app:
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/subosito/gotenv"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
gotenv.Load()
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
log.Println(os.Getenv("APP_ID")) // "1234567"
|
||||||
|
log.Println(os.Getenv("APP_SECRET")) // "abcdef"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also load other than `.env` file if you wish. Just supply filenames when calling `Load()`. It will load them in order and the first value set for a variable will win.:
|
||||||
|
|
||||||
|
```go
|
||||||
|
gotenv.Load(".env.production", "credentials")
|
||||||
|
```
|
||||||
|
|
||||||
|
While `gotenv.Load` loads entries from `.env` file, `gotenv.Apply` allows you to use any `io.Reader`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
gotenv.Apply(strings.NewReader("APP_ID=1234567"))
|
||||||
|
|
||||||
|
log.Println(os.Getenv("APP_ID"))
|
||||||
|
// Output: "1234567"
|
||||||
|
```
|
||||||
|
|
||||||
|
Both `gotenv.Load` and `gotenv.Apply` **DO NOT** overrides existing environment variables. If you want to override existing ones, you can see section below.
|
||||||
|
|
||||||
|
### Environment Overrides
|
||||||
|
|
||||||
|
Besides above functions, `gotenv` also provides another functions that overrides existing:
|
||||||
|
|
||||||
|
- `gotenv.OverLoad`
|
||||||
|
- `gotenv.OverApply`
|
||||||
|
|
||||||
|
|
||||||
|
Here's the example of this overrides behavior:
|
||||||
|
|
||||||
|
```go
|
||||||
|
os.Setenv("HELLO", "world")
|
||||||
|
|
||||||
|
// NOTE: using Apply existing value will be reserved
|
||||||
|
gotenv.Apply(strings.NewReader("HELLO=universe"))
|
||||||
|
fmt.Println(os.Getenv("HELLO"))
|
||||||
|
// Output: "world"
|
||||||
|
|
||||||
|
// NOTE: using OverApply existing value will be overridden
|
||||||
|
gotenv.OverApply(strings.NewReader("HELLO=universe"))
|
||||||
|
fmt.Println(os.Getenv("HELLO"))
|
||||||
|
// Output: "universe"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Throw a Panic
|
||||||
|
|
||||||
|
Both `gotenv.Load` and `gotenv.OverLoad` returns an error on something wrong occurred, like your env file is not exist, and so on. To make it easier to use, `gotenv` also provides `gotenv.Must` helper, to let it panic when an error returned.
|
||||||
|
|
||||||
|
```go
|
||||||
|
err := gotenv.Load(".env-is-not-exist")
|
||||||
|
fmt.Println("error", err)
|
||||||
|
// error: open .env-is-not-exist: no such file or directory
|
||||||
|
|
||||||
|
gotenv.Must(gotenv.Load, ".env-is-not-exist")
|
||||||
|
// it will throw a panic
|
||||||
|
// panic: open .env-is-not-exist: no such file or directory
|
||||||
|
```
|
||||||
|
|
||||||
|
### Another Scenario
|
||||||
|
|
||||||
|
Just in case you want to parse environment variables from any `io.Reader`, gotenv keeps its `Parse` and `StrictParse` function as public API so you can use that.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// import "strings"
|
||||||
|
|
||||||
|
pairs := gotenv.Parse(strings.NewReader("FOO=test\nBAR=$FOO"))
|
||||||
|
// gotenv.Env{"FOO": "test", "BAR": "test"}
|
||||||
|
|
||||||
|
err, pairs = gotenv.StrictParse(strings.NewReader(`FOO="bar"`))
|
||||||
|
// gotenv.Env{"FOO": "bar"}
|
||||||
|
```
|
||||||
|
|
||||||
|
`Parse` ignores invalid lines and returns `Env` of valid environment variables, while `StrictParse` returns an error for invalid lines.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
The gotenv package is a Go port of [`dotenv`](https://github.com/bkeepers/dotenv) project with some additions made for Go. For general features, it aims to be compatible as close as possible.
|
9
vendor/github.com/subosito/gotenv/appveyor.yml
generated
vendored
Normal file
9
vendor/github.com/subosito/gotenv/appveyor.yml
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
build: off
|
||||||
|
clone_folder: c:\gopath\src\github.com\subosito\gotenv
|
||||||
|
environment:
|
||||||
|
GOPATH: c:\gopath
|
||||||
|
stack: go 1.10
|
||||||
|
before_test:
|
||||||
|
- go get -t
|
||||||
|
test_script:
|
||||||
|
- go test -v -cover -race
|
265
vendor/github.com/subosito/gotenv/gotenv.go
generated
vendored
Normal file
265
vendor/github.com/subosito/gotenv/gotenv.go
generated
vendored
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
// Package gotenv provides functionality to dynamically load the environment variables
|
||||||
|
package gotenv
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Pattern for detecting valid line format
|
||||||
|
linePattern = `\A\s*(?:export\s+)?([\w\.]+)(?:\s*=\s*|:\s+?)('(?:\'|[^'])*'|"(?:\"|[^"])*"|[^#\n]+)?\s*(?:\s*\#.*)?\z`
|
||||||
|
|
||||||
|
// Pattern for detecting valid variable within a value
|
||||||
|
variablePattern = `(\\)?(\$)(\{?([A-Z0-9_]+)?\}?)`
|
||||||
|
)
|
||||||
|
|
||||||
|
// Env holds key/value pair of valid environment variable
|
||||||
|
type Env map[string]string
|
||||||
|
|
||||||
|
/*
|
||||||
|
Load is a function to load a file or multiple files and then export the valid variables into environment variables if they do not exist.
|
||||||
|
When it's called with no argument, it will load `.env` file on the current path and set the environment variables.
|
||||||
|
Otherwise, it will loop over the filenames parameter and set the proper environment variables.
|
||||||
|
*/
|
||||||
|
func Load(filenames ...string) error {
|
||||||
|
return loadenv(false, filenames...)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
OverLoad is a function to load a file or multiple files and then export and override the valid variables into environment variables.
|
||||||
|
*/
|
||||||
|
func OverLoad(filenames ...string) error {
|
||||||
|
return loadenv(true, filenames...)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Must is wrapper function that will panic when supplied function returns an error.
|
||||||
|
*/
|
||||||
|
func Must(fn func(filenames ...string) error, filenames ...string) {
|
||||||
|
if err := fn(filenames...); err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Apply is a function to load an io Reader then export the valid variables into environment variables if they do not exist.
|
||||||
|
*/
|
||||||
|
func Apply(r io.Reader) error {
|
||||||
|
return parset(r, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
OverApply is a function to load an io Reader then export and override the valid variables into environment variables.
|
||||||
|
*/
|
||||||
|
func OverApply(r io.Reader) error {
|
||||||
|
return parset(r, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadenv(override bool, filenames ...string) error {
|
||||||
|
if len(filenames) == 0 {
|
||||||
|
filenames = []string{".env"}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, filename := range filenames {
|
||||||
|
f, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = parset(f, override)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse and set :)
|
||||||
|
func parset(r io.Reader, override bool) error {
|
||||||
|
env, err := StrictParse(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for key, val := range env {
|
||||||
|
setenv(key, val, override)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setenv(key, val string, override bool) {
|
||||||
|
if override {
|
||||||
|
os.Setenv(key, val)
|
||||||
|
} else {
|
||||||
|
if _, present := os.LookupEnv(key); !present {
|
||||||
|
os.Setenv(key, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse is a function to parse line by line any io.Reader supplied and returns the valid Env key/value pair of valid variables.
|
||||||
|
// It expands the value of a variable from the environment variable but does not set the value to the environment itself.
|
||||||
|
// This function is skipping any invalid lines and only processing the valid one.
|
||||||
|
func Parse(r io.Reader) Env {
|
||||||
|
env, _ := StrictParse(r)
|
||||||
|
return env
|
||||||
|
}
|
||||||
|
|
||||||
|
// StrictParse is a function to parse line by line any io.Reader supplied and returns the valid Env key/value pair of valid variables.
|
||||||
|
// It expands the value of a variable from the environment variable but does not set the value to the environment itself.
|
||||||
|
// This function is returning an error if there are any invalid lines.
|
||||||
|
func StrictParse(r io.Reader) (Env, error) {
|
||||||
|
env := make(Env)
|
||||||
|
scanner := bufio.NewScanner(r)
|
||||||
|
|
||||||
|
i := 1
|
||||||
|
bom := string([]byte{239, 187, 191})
|
||||||
|
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
|
||||||
|
if i == 1 {
|
||||||
|
line = strings.TrimPrefix(line, bom)
|
||||||
|
}
|
||||||
|
|
||||||
|
i++
|
||||||
|
|
||||||
|
err := parseLine(line, env)
|
||||||
|
if err != nil {
|
||||||
|
return env, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return env, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseLine(s string, env Env) error {
|
||||||
|
rl := regexp.MustCompile(linePattern)
|
||||||
|
rm := rl.FindStringSubmatch(s)
|
||||||
|
|
||||||
|
if len(rm) == 0 {
|
||||||
|
return checkFormat(s, env)
|
||||||
|
}
|
||||||
|
|
||||||
|
key := rm[1]
|
||||||
|
val := rm[2]
|
||||||
|
|
||||||
|
// determine if string has quote prefix
|
||||||
|
hdq := strings.HasPrefix(val, `"`)
|
||||||
|
|
||||||
|
// determine if string has single quote prefix
|
||||||
|
hsq := strings.HasPrefix(val, `'`)
|
||||||
|
|
||||||
|
// trim whitespace
|
||||||
|
val = strings.Trim(val, " ")
|
||||||
|
|
||||||
|
// remove quotes '' or ""
|
||||||
|
rq := regexp.MustCompile(`\A(['"])(.*)(['"])\z`)
|
||||||
|
val = rq.ReplaceAllString(val, "$2")
|
||||||
|
|
||||||
|
if hdq {
|
||||||
|
val = strings.Replace(val, `\n`, "\n", -1)
|
||||||
|
val = strings.Replace(val, `\r`, "\r", -1)
|
||||||
|
|
||||||
|
// Unescape all characters except $ so variables can be escaped properly
|
||||||
|
re := regexp.MustCompile(`\\([^$])`)
|
||||||
|
val = re.ReplaceAllString(val, "$1")
|
||||||
|
}
|
||||||
|
|
||||||
|
rv := regexp.MustCompile(variablePattern)
|
||||||
|
fv := func(s string) string {
|
||||||
|
return varReplacement(s, hsq, env)
|
||||||
|
}
|
||||||
|
|
||||||
|
val = rv.ReplaceAllStringFunc(val, fv)
|
||||||
|
val = parseVal(val, env)
|
||||||
|
|
||||||
|
env[key] = val
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseExport(st string, env Env) error {
|
||||||
|
if strings.HasPrefix(st, "export") {
|
||||||
|
vs := strings.SplitN(st, " ", 2)
|
||||||
|
|
||||||
|
if len(vs) > 1 {
|
||||||
|
if _, ok := env[vs[1]]; !ok {
|
||||||
|
return fmt.Errorf("line `%s` has an unset variable", st)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func varReplacement(s string, hsq bool, env Env) string {
|
||||||
|
if strings.HasPrefix(s, "\\") {
|
||||||
|
return strings.TrimPrefix(s, "\\")
|
||||||
|
}
|
||||||
|
|
||||||
|
if hsq {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
sn := `(\$)(\{?([A-Z0-9_]+)\}?)`
|
||||||
|
rn := regexp.MustCompile(sn)
|
||||||
|
mn := rn.FindStringSubmatch(s)
|
||||||
|
|
||||||
|
if len(mn) == 0 {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
v := mn[3]
|
||||||
|
|
||||||
|
replace, ok := env[v]
|
||||||
|
if !ok {
|
||||||
|
replace = os.Getenv(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return replace
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkFormat(s string, env Env) error {
|
||||||
|
st := strings.TrimSpace(s)
|
||||||
|
|
||||||
|
if (st == "") || strings.HasPrefix(st, "#") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := parseExport(st, env); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("line `%s` doesn't match format", s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseVal(val string, env Env) string {
|
||||||
|
if strings.Contains(val, "=") {
|
||||||
|
if !(val == "\n" || val == "\r") {
|
||||||
|
kv := strings.Split(val, "\n")
|
||||||
|
|
||||||
|
if len(kv) == 1 {
|
||||||
|
kv = strings.Split(val, "\r")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(kv) > 1 {
|
||||||
|
val = kv[0]
|
||||||
|
|
||||||
|
for i := 1; i < len(kv); i++ {
|
||||||
|
parseLine(kv[i], env)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return val
|
||||||
|
}
|
2
vendor/github.com/valyala/fasttemplate/README.md
generated
vendored
2
vendor/github.com/valyala/fasttemplate/README.md
generated
vendored
@ -3,7 +3,7 @@ fasttemplate
|
|||||||
|
|
||||||
Simple and fast template engine for Go.
|
Simple and fast template engine for Go.
|
||||||
|
|
||||||
Fasttemplate peforms only a single task - it substitutes template placeholders
|
Fasttemplate performs only a single task - it substitutes template placeholders
|
||||||
with user-defined values. At high speed :)
|
with user-defined values. At high speed :)
|
||||||
|
|
||||||
Take a look at [quicktemplate](https://github.com/valyala/quicktemplate) if you need fast yet powerful html template engine.
|
Take a look at [quicktemplate](https://github.com/valyala/quicktemplate) if you need fast yet powerful html template engine.
|
||||||
|
317
vendor/golang.org/x/crypto/acme/acme.go
generated
vendored
317
vendor/golang.org/x/crypto/acme/acme.go
generated
vendored
@ -4,7 +4,10 @@
|
|||||||
|
|
||||||
// Package acme provides an implementation of the
|
// Package acme provides an implementation of the
|
||||||
// Automatic Certificate Management Environment (ACME) spec.
|
// Automatic Certificate Management Environment (ACME) spec.
|
||||||
// See https://tools.ietf.org/html/draft-ietf-acme-acme-02 for details.
|
// The intial implementation was based on ACME draft-02 and
|
||||||
|
// is now being extended to comply with RFC 8555.
|
||||||
|
// See https://tools.ietf.org/html/draft-ietf-acme-acme-02
|
||||||
|
// and https://tools.ietf.org/html/rfc8555 for details.
|
||||||
//
|
//
|
||||||
// Most common scenarios will want to use autocert subdirectory instead,
|
// Most common scenarios will want to use autocert subdirectory instead,
|
||||||
// which provides automatic access to certificates from Let's Encrypt
|
// which provides automatic access to certificates from Let's Encrypt
|
||||||
@ -41,7 +44,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// LetsEncryptURL is the Directory endpoint of Let's Encrypt CA.
|
// LetsEncryptURL is the Directory endpoint of Let's Encrypt CA.
|
||||||
LetsEncryptURL = "https://acme-v01.api.letsencrypt.org/directory"
|
LetsEncryptURL = "https://acme-v02.api.letsencrypt.org/directory"
|
||||||
|
|
||||||
// ALPNProto is the ALPN protocol name used by a CA server when validating
|
// ALPNProto is the ALPN protocol name used by a CA server when validating
|
||||||
// tls-alpn-01 challenges.
|
// tls-alpn-01 challenges.
|
||||||
@ -57,7 +60,10 @@ var idPeACMEIdentifierV1 = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 30, 1}
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
maxChainLen = 5 // max depth and breadth of a certificate chain
|
maxChainLen = 5 // max depth and breadth of a certificate chain
|
||||||
maxCertSize = 1 << 20 // max size of a certificate, in bytes
|
maxCertSize = 1 << 20 // max size of a certificate, in DER bytes
|
||||||
|
// Used for decoding certs from application/pem-certificate-chain response,
|
||||||
|
// the default when in RFC mode.
|
||||||
|
maxCertChainSize = maxCertSize * maxChainLen
|
||||||
|
|
||||||
// Max number of collected nonces kept in memory.
|
// Max number of collected nonces kept in memory.
|
||||||
// Expect usual peak of 1 or 2.
|
// Expect usual peak of 1 or 2.
|
||||||
@ -116,21 +122,48 @@ type Client struct {
|
|||||||
// identifiable by the server, in case they are causing issues.
|
// identifiable by the server, in case they are causing issues.
|
||||||
UserAgent string
|
UserAgent string
|
||||||
|
|
||||||
dirMu sync.Mutex // guards writes to dir
|
cacheMu sync.Mutex
|
||||||
dir *Directory // cached result of Client's Discover method
|
dir *Directory // cached result of Client's Discover method
|
||||||
|
kid keyID // cached Account.URI obtained from registerRFC or getAccountRFC
|
||||||
|
|
||||||
noncesMu sync.Mutex
|
noncesMu sync.Mutex
|
||||||
nonces map[string]struct{} // nonces collected from previous responses
|
nonces map[string]struct{} // nonces collected from previous responses
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// accountKID returns a key ID associated with c.Key, the account identity
|
||||||
|
// provided by the CA during RFC based registration.
|
||||||
|
// It assumes c.Discover has already been called.
|
||||||
|
//
|
||||||
|
// accountKID requires at most one network roundtrip.
|
||||||
|
// It caches only successful result.
|
||||||
|
//
|
||||||
|
// When in pre-RFC mode or when c.getRegRFC responds with an error, accountKID
|
||||||
|
// returns noKeyID.
|
||||||
|
func (c *Client) accountKID(ctx context.Context) keyID {
|
||||||
|
c.cacheMu.Lock()
|
||||||
|
defer c.cacheMu.Unlock()
|
||||||
|
if !c.dir.rfcCompliant() {
|
||||||
|
return noKeyID
|
||||||
|
}
|
||||||
|
if c.kid != noKeyID {
|
||||||
|
return c.kid
|
||||||
|
}
|
||||||
|
a, err := c.getRegRFC(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return noKeyID
|
||||||
|
}
|
||||||
|
c.kid = keyID(a.URI)
|
||||||
|
return c.kid
|
||||||
|
}
|
||||||
|
|
||||||
// Discover performs ACME server discovery using c.DirectoryURL.
|
// Discover performs ACME server discovery using c.DirectoryURL.
|
||||||
//
|
//
|
||||||
// It caches successful result. So, subsequent calls will not result in
|
// It caches successful result. So, subsequent calls will not result in
|
||||||
// a network round-trip. This also means mutating c.DirectoryURL after successful call
|
// a network round-trip. This also means mutating c.DirectoryURL after successful call
|
||||||
// of this method will have no effect.
|
// of this method will have no effect.
|
||||||
func (c *Client) Discover(ctx context.Context) (Directory, error) {
|
func (c *Client) Discover(ctx context.Context) (Directory, error) {
|
||||||
c.dirMu.Lock()
|
c.cacheMu.Lock()
|
||||||
defer c.dirMu.Unlock()
|
defer c.cacheMu.Unlock()
|
||||||
if c.dir != nil {
|
if c.dir != nil {
|
||||||
return *c.dir, nil
|
return *c.dir, nil
|
||||||
}
|
}
|
||||||
@ -143,27 +176,53 @@ func (c *Client) Discover(ctx context.Context) (Directory, error) {
|
|||||||
c.addNonce(res.Header)
|
c.addNonce(res.Header)
|
||||||
|
|
||||||
var v struct {
|
var v struct {
|
||||||
Reg string `json:"new-reg"`
|
Reg string `json:"new-reg"`
|
||||||
Authz string `json:"new-authz"`
|
RegRFC string `json:"newAccount"`
|
||||||
Cert string `json:"new-cert"`
|
Authz string `json:"new-authz"`
|
||||||
Revoke string `json:"revoke-cert"`
|
AuthzRFC string `json:"newAuthz"`
|
||||||
Meta struct {
|
OrderRFC string `json:"newOrder"`
|
||||||
Terms string `json:"terms-of-service"`
|
Cert string `json:"new-cert"`
|
||||||
Website string `json:"website"`
|
Revoke string `json:"revoke-cert"`
|
||||||
CAA []string `json:"caa-identities"`
|
RevokeRFC string `json:"revokeCert"`
|
||||||
|
NonceRFC string `json:"newNonce"`
|
||||||
|
KeyChangeRFC string `json:"keyChange"`
|
||||||
|
Meta struct {
|
||||||
|
Terms string `json:"terms-of-service"`
|
||||||
|
TermsRFC string `json:"termsOfService"`
|
||||||
|
WebsiteRFC string `json:"website"`
|
||||||
|
CAA []string `json:"caa-identities"`
|
||||||
|
CAARFC []string `json:"caaIdentities"`
|
||||||
|
ExternalAcctRFC bool `json:"externalAccountRequired"`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
||||||
return Directory{}, err
|
return Directory{}, err
|
||||||
}
|
}
|
||||||
|
if v.OrderRFC == "" {
|
||||||
|
// Non-RFC compliant ACME CA.
|
||||||
|
c.dir = &Directory{
|
||||||
|
RegURL: v.Reg,
|
||||||
|
AuthzURL: v.Authz,
|
||||||
|
CertURL: v.Cert,
|
||||||
|
RevokeURL: v.Revoke,
|
||||||
|
Terms: v.Meta.Terms,
|
||||||
|
Website: v.Meta.WebsiteRFC,
|
||||||
|
CAA: v.Meta.CAA,
|
||||||
|
}
|
||||||
|
return *c.dir, nil
|
||||||
|
}
|
||||||
|
// RFC compliant ACME CA.
|
||||||
c.dir = &Directory{
|
c.dir = &Directory{
|
||||||
RegURL: v.Reg,
|
RegURL: v.RegRFC,
|
||||||
AuthzURL: v.Authz,
|
AuthzURL: v.AuthzRFC,
|
||||||
CertURL: v.Cert,
|
OrderURL: v.OrderRFC,
|
||||||
RevokeURL: v.Revoke,
|
RevokeURL: v.RevokeRFC,
|
||||||
Terms: v.Meta.Terms,
|
NonceURL: v.NonceRFC,
|
||||||
Website: v.Meta.Website,
|
KeyChangeURL: v.KeyChangeRFC,
|
||||||
CAA: v.Meta.CAA,
|
Terms: v.Meta.TermsRFC,
|
||||||
|
Website: v.Meta.WebsiteRFC,
|
||||||
|
CAA: v.Meta.CAARFC,
|
||||||
|
ExternalAccountRequired: v.Meta.ExternalAcctRFC,
|
||||||
}
|
}
|
||||||
return *c.dir, nil
|
return *c.dir, nil
|
||||||
}
|
}
|
||||||
@ -176,6 +235,9 @@ func (c *Client) directoryURL() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateCert requests a new certificate using the Certificate Signing Request csr encoded in DER format.
|
// CreateCert requests a new certificate using the Certificate Signing Request csr encoded in DER format.
|
||||||
|
// It is incompatible with RFC 8555. Callers should use CreateOrderCert when interfacing
|
||||||
|
// with an RFC-compliant CA.
|
||||||
|
//
|
||||||
// The exp argument indicates the desired certificate validity duration. CA may issue a certificate
|
// The exp argument indicates the desired certificate validity duration. CA may issue a certificate
|
||||||
// with a different duration.
|
// with a different duration.
|
||||||
// If the bundle argument is true, the returned value will also contain the CA (issuer) certificate chain.
|
// If the bundle argument is true, the returned value will also contain the CA (issuer) certificate chain.
|
||||||
@ -206,7 +268,7 @@ func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration,
|
|||||||
req.NotAfter = now.Add(exp).Format(time.RFC3339)
|
req.NotAfter = now.Add(exp).Format(time.RFC3339)
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := c.post(ctx, c.Key, c.dir.CertURL, req, wantStatus(http.StatusCreated))
|
res, err := c.post(ctx, nil, c.dir.CertURL, req, wantStatus(http.StatusCreated))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
@ -227,12 +289,22 @@ func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration,
|
|||||||
// It retries the request until the certificate is successfully retrieved,
|
// It retries the request until the certificate is successfully retrieved,
|
||||||
// context is cancelled by the caller or an error response is received.
|
// context is cancelled by the caller or an error response is received.
|
||||||
//
|
//
|
||||||
// The returned value will also contain the CA (issuer) certificate if the bundle argument is true.
|
// If the bundle argument is true, the returned value also contains the CA (issuer)
|
||||||
|
// certificate chain.
|
||||||
//
|
//
|
||||||
// FetchCert returns an error if the CA's response or chain was unreasonably large.
|
// FetchCert returns an error if the CA's response or chain was unreasonably large.
|
||||||
// Callers are encouraged to parse the returned value to ensure the certificate is valid
|
// Callers are encouraged to parse the returned value to ensure the certificate is valid
|
||||||
// and has expected features.
|
// and has expected features.
|
||||||
func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) {
|
func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) {
|
||||||
|
dir, err := c.Discover(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if dir.rfcCompliant() {
|
||||||
|
return c.fetchCertRFC(ctx, url, bundle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Legacy non-authenticated GET request.
|
||||||
res, err := c.get(ctx, url, wantStatus(http.StatusOK))
|
res, err := c.get(ctx, url, wantStatus(http.StatusOK))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -247,10 +319,15 @@ func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]by
|
|||||||
// For instance, the key pair of the certificate may be authorized.
|
// For instance, the key pair of the certificate may be authorized.
|
||||||
// If the key is nil, c.Key is used instead.
|
// If the key is nil, c.Key is used instead.
|
||||||
func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte, reason CRLReasonCode) error {
|
func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte, reason CRLReasonCode) error {
|
||||||
if _, err := c.Discover(ctx); err != nil {
|
dir, err := c.Discover(ctx)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if dir.rfcCompliant() {
|
||||||
|
return c.revokeCertRFC(ctx, key, cert, reason)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Legacy CA.
|
||||||
body := &struct {
|
body := &struct {
|
||||||
Resource string `json:"resource"`
|
Resource string `json:"resource"`
|
||||||
Cert string `json:"certificate"`
|
Cert string `json:"certificate"`
|
||||||
@ -260,10 +337,7 @@ func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte,
|
|||||||
Cert: base64.RawURLEncoding.EncodeToString(cert),
|
Cert: base64.RawURLEncoding.EncodeToString(cert),
|
||||||
Reason: int(reason),
|
Reason: int(reason),
|
||||||
}
|
}
|
||||||
if key == nil {
|
res, err := c.post(ctx, key, dir.RevokeURL, body, wantStatus(http.StatusOK))
|
||||||
key = c.Key
|
|
||||||
}
|
|
||||||
res, err := c.post(ctx, key, c.dir.RevokeURL, body, wantStatus(http.StatusOK))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -275,20 +349,30 @@ func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte,
|
|||||||
// during account registration. See Register method of Client for more details.
|
// during account registration. See Register method of Client for more details.
|
||||||
func AcceptTOS(tosURL string) bool { return true }
|
func AcceptTOS(tosURL string) bool { return true }
|
||||||
|
|
||||||
// Register creates a new account registration by following the "new-reg" flow.
|
// Register creates a new account with the CA using c.Key.
|
||||||
// It returns the registered account. The account is not modified.
|
// It returns the registered account. The account acct is not modified.
|
||||||
//
|
//
|
||||||
// The registration may require the caller to agree to the CA's Terms of Service (TOS).
|
// The registration may require the caller to agree to the CA's Terms of Service (TOS).
|
||||||
// If so, and the account has not indicated the acceptance of the terms (see Account for details),
|
// If so, and the account has not indicated the acceptance of the terms (see Account for details),
|
||||||
// Register calls prompt with a TOS URL provided by the CA. Prompt should report
|
// Register calls prompt with a TOS URL provided by the CA. Prompt should report
|
||||||
// whether the caller agrees to the terms. To always accept the terms, the caller can use AcceptTOS.
|
// whether the caller agrees to the terms. To always accept the terms, the caller can use AcceptTOS.
|
||||||
func (c *Client) Register(ctx context.Context, a *Account, prompt func(tosURL string) bool) (*Account, error) {
|
//
|
||||||
if _, err := c.Discover(ctx); err != nil {
|
// When interfacing with an RFC-compliant CA, non-RFC 8555 fields of acct are ignored
|
||||||
|
// and prompt is called if Directory's Terms field is non-zero.
|
||||||
|
// Also see Error's Instance field for when a CA requires already registered accounts to agree
|
||||||
|
// to an updated Terms of Service.
|
||||||
|
func (c *Client) Register(ctx context.Context, acct *Account, prompt func(tosURL string) bool) (*Account, error) {
|
||||||
|
dir, err := c.Discover(ctx)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if dir.rfcCompliant() {
|
||||||
|
return c.registerRFC(ctx, acct, prompt)
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
// Legacy ACME draft registration flow.
|
||||||
if a, err = c.doReg(ctx, c.dir.RegURL, "new-reg", a); err != nil {
|
a, err := c.doReg(ctx, dir.RegURL, "new-reg", acct)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var accept bool
|
var accept bool
|
||||||
@ -302,9 +386,20 @@ func (c *Client) Register(ctx context.Context, a *Account, prompt func(tosURL st
|
|||||||
return a, err
|
return a, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetReg retrieves an existing registration.
|
// GetReg retrieves an existing account associated with c.Key.
|
||||||
// The url argument is an Account URI.
|
//
|
||||||
|
// The url argument is an Account URI used with pre-RFC 8555 CAs.
|
||||||
|
// It is ignored when interfacing with an RFC-compliant CA.
|
||||||
func (c *Client) GetReg(ctx context.Context, url string) (*Account, error) {
|
func (c *Client) GetReg(ctx context.Context, url string) (*Account, error) {
|
||||||
|
dir, err := c.Discover(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if dir.rfcCompliant() {
|
||||||
|
return c.getRegRFC(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Legacy CA.
|
||||||
a, err := c.doReg(ctx, url, "reg", nil)
|
a, err := c.doReg(ctx, url, "reg", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -315,9 +410,21 @@ func (c *Client) GetReg(ctx context.Context, url string) (*Account, error) {
|
|||||||
|
|
||||||
// UpdateReg updates an existing registration.
|
// UpdateReg updates an existing registration.
|
||||||
// It returns an updated account copy. The provided account is not modified.
|
// It returns an updated account copy. The provided account is not modified.
|
||||||
func (c *Client) UpdateReg(ctx context.Context, a *Account) (*Account, error) {
|
//
|
||||||
uri := a.URI
|
// When interfacing with RFC-compliant CAs, a.URI is ignored and the account URL
|
||||||
a, err := c.doReg(ctx, uri, "reg", a)
|
// associated with c.Key is used instead.
|
||||||
|
func (c *Client) UpdateReg(ctx context.Context, acct *Account) (*Account, error) {
|
||||||
|
dir, err := c.Discover(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if dir.rfcCompliant() {
|
||||||
|
return c.updateRegRFC(ctx, acct)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Legacy CA.
|
||||||
|
uri := acct.URI
|
||||||
|
a, err := c.doReg(ctx, uri, "reg", acct)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -325,13 +432,21 @@ func (c *Client) UpdateReg(ctx context.Context, a *Account) (*Account, error) {
|
|||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Authorize performs the initial step in an authorization flow.
|
// Authorize performs the initial step in the pre-authorization flow,
|
||||||
|
// as opposed to order-based flow.
|
||||||
// The caller will then need to choose from and perform a set of returned
|
// The caller will then need to choose from and perform a set of returned
|
||||||
// challenges using c.Accept in order to successfully complete authorization.
|
// challenges using c.Accept in order to successfully complete authorization.
|
||||||
//
|
//
|
||||||
|
// Once complete, the caller can use AuthorizeOrder which the CA
|
||||||
|
// should provision with the already satisfied authorization.
|
||||||
|
// For pre-RFC CAs, the caller can proceed directly to requesting a certificate
|
||||||
|
// using CreateCert method.
|
||||||
|
//
|
||||||
// If an authorization has been previously granted, the CA may return
|
// If an authorization has been previously granted, the CA may return
|
||||||
// a valid authorization (Authorization.Status is StatusValid). If so, the caller
|
// a valid authorization which has its Status field set to StatusValid.
|
||||||
// need not fulfill any challenge and can proceed to requesting a certificate.
|
//
|
||||||
|
// More about pre-authorization can be found at
|
||||||
|
// https://tools.ietf.org/html/rfc8555#section-7.4.1.
|
||||||
func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, error) {
|
func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, error) {
|
||||||
return c.authorize(ctx, "dns", domain)
|
return c.authorize(ctx, "dns", domain)
|
||||||
}
|
}
|
||||||
@ -362,7 +477,7 @@ func (c *Client) authorize(ctx context.Context, typ, val string) (*Authorization
|
|||||||
Resource: "new-authz",
|
Resource: "new-authz",
|
||||||
Identifier: authzID{Type: typ, Value: val},
|
Identifier: authzID{Type: typ, Value: val},
|
||||||
}
|
}
|
||||||
res, err := c.post(ctx, c.Key, c.dir.AuthzURL, req, wantStatus(http.StatusCreated))
|
res, err := c.post(ctx, nil, c.dir.AuthzURL, req, wantStatus(http.StatusCreated))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -383,7 +498,17 @@ func (c *Client) authorize(ctx context.Context, typ, val string) (*Authorization
|
|||||||
// If a caller needs to poll an authorization until its status is final,
|
// If a caller needs to poll an authorization until its status is final,
|
||||||
// see the WaitAuthorization method.
|
// see the WaitAuthorization method.
|
||||||
func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error) {
|
func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error) {
|
||||||
res, err := c.get(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted))
|
dir, err := c.Discover(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var res *http.Response
|
||||||
|
if dir.rfcCompliant() {
|
||||||
|
res, err = c.postAsGet(ctx, url, wantStatus(http.StatusOK))
|
||||||
|
} else {
|
||||||
|
res, err = c.get(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted))
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -400,11 +525,16 @@ func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorizati
|
|||||||
// The url argument is an Authorization.URI value.
|
// The url argument is an Authorization.URI value.
|
||||||
//
|
//
|
||||||
// If successful, the caller will be required to obtain a new authorization
|
// If successful, the caller will be required to obtain a new authorization
|
||||||
// using the Authorize method before being able to request a new certificate
|
// using the Authorize or AuthorizeOrder methods before being able to request
|
||||||
// for the domain associated with the authorization.
|
// a new certificate for the domain associated with the authorization.
|
||||||
//
|
//
|
||||||
// It does not revoke existing certificates.
|
// It does not revoke existing certificates.
|
||||||
func (c *Client) RevokeAuthorization(ctx context.Context, url string) error {
|
func (c *Client) RevokeAuthorization(ctx context.Context, url string) error {
|
||||||
|
// Required for c.accountKID() when in RFC mode.
|
||||||
|
if _, err := c.Discover(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
req := struct {
|
req := struct {
|
||||||
Resource string `json:"resource"`
|
Resource string `json:"resource"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
@ -414,7 +544,7 @@ func (c *Client) RevokeAuthorization(ctx context.Context, url string) error {
|
|||||||
Status: "deactivated",
|
Status: "deactivated",
|
||||||
Delete: true,
|
Delete: true,
|
||||||
}
|
}
|
||||||
res, err := c.post(ctx, c.Key, url, req, wantStatus(http.StatusOK))
|
res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -430,8 +560,18 @@ func (c *Client) RevokeAuthorization(ctx context.Context, url string) error {
|
|||||||
// In all other cases WaitAuthorization returns an error.
|
// In all other cases WaitAuthorization returns an error.
|
||||||
// If the Status is StatusInvalid, the returned error is of type *AuthorizationError.
|
// If the Status is StatusInvalid, the returned error is of type *AuthorizationError.
|
||||||
func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error) {
|
func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error) {
|
||||||
|
// Required for c.accountKID() when in RFC mode.
|
||||||
|
dir, err := c.Discover(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
getfn := c.postAsGet
|
||||||
|
if !dir.rfcCompliant() {
|
||||||
|
getfn = c.get
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
res, err := c.get(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted))
|
res, err := getfn(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -474,10 +614,21 @@ func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorizat
|
|||||||
//
|
//
|
||||||
// A client typically polls a challenge status using this method.
|
// A client typically polls a challenge status using this method.
|
||||||
func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error) {
|
func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error) {
|
||||||
res, err := c.get(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted))
|
// Required for c.accountKID() when in RFC mode.
|
||||||
|
dir, err := c.Discover(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getfn := c.postAsGet
|
||||||
|
if !dir.rfcCompliant() {
|
||||||
|
getfn = c.get
|
||||||
|
}
|
||||||
|
res, err := getfn(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
v := wireChallenge{URI: url}
|
v := wireChallenge{URI: url}
|
||||||
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
||||||
@ -491,21 +642,29 @@ func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, erro
|
|||||||
//
|
//
|
||||||
// The server will then perform the validation asynchronously.
|
// The server will then perform the validation asynchronously.
|
||||||
func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error) {
|
func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error) {
|
||||||
auth, err := keyAuth(c.Key.Public(), chal.Token)
|
// Required for c.accountKID() when in RFC mode.
|
||||||
|
dir, err := c.Discover(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
req := struct {
|
var req interface{} = json.RawMessage("{}") // RFC-compliant CA
|
||||||
Resource string `json:"resource"`
|
if !dir.rfcCompliant() {
|
||||||
Type string `json:"type"`
|
auth, err := keyAuth(c.Key.Public(), chal.Token)
|
||||||
Auth string `json:"keyAuthorization"`
|
if err != nil {
|
||||||
}{
|
return nil, err
|
||||||
Resource: "challenge",
|
}
|
||||||
Type: chal.Type,
|
req = struct {
|
||||||
Auth: auth,
|
Resource string `json:"resource"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Auth string `json:"keyAuthorization"`
|
||||||
|
}{
|
||||||
|
Resource: "challenge",
|
||||||
|
Type: chal.Type,
|
||||||
|
Auth: auth,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
res, err := c.post(ctx, c.Key, chal.URI, req, wantStatus(
|
res, err := c.post(ctx, nil, chal.URI, req, wantStatus(
|
||||||
http.StatusOK, // according to the spec
|
http.StatusOK, // according to the spec
|
||||||
http.StatusAccepted, // Let's Encrypt: see https://goo.gl/WsJ7VT (acme-divergences.md)
|
http.StatusAccepted, // Let's Encrypt: see https://goo.gl/WsJ7VT (acme-divergences.md)
|
||||||
))
|
))
|
||||||
@ -555,21 +714,8 @@ func (c *Client) HTTP01ChallengePath(token string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TLSSNI01ChallengeCert creates a certificate for TLS-SNI-01 challenge response.
|
// TLSSNI01ChallengeCert creates a certificate for TLS-SNI-01 challenge response.
|
||||||
// Servers can present the certificate to validate the challenge and prove control
|
|
||||||
// over a domain name.
|
|
||||||
//
|
//
|
||||||
// The implementation is incomplete in that the returned value is a single certificate,
|
// Deprecated: This challenge type is unused in both draft-02 and RFC versions of ACME spec.
|
||||||
// computed only for Z0 of the key authorization. ACME CAs are expected to update
|
|
||||||
// their implementations to use the newer version, TLS-SNI-02.
|
|
||||||
// For more details on TLS-SNI-01 see https://tools.ietf.org/html/draft-ietf-acme-acme-01#section-7.3.
|
|
||||||
//
|
|
||||||
// The token argument is a Challenge.Token value.
|
|
||||||
// If a WithKey option is provided, its private part signs the returned cert,
|
|
||||||
// and the public part is used to specify the signee.
|
|
||||||
// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
|
|
||||||
//
|
|
||||||
// The returned certificate is valid for the next 24 hours and must be presented only when
|
|
||||||
// the server name of the TLS ClientHello matches exactly the returned name value.
|
|
||||||
func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
|
func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
|
||||||
ka, err := keyAuth(c.Key.Public(), token)
|
ka, err := keyAuth(c.Key.Public(), token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -586,17 +732,8 @@ func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tl
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TLSSNI02ChallengeCert creates a certificate for TLS-SNI-02 challenge response.
|
// TLSSNI02ChallengeCert creates a certificate for TLS-SNI-02 challenge response.
|
||||||
// Servers can present the certificate to validate the challenge and prove control
|
|
||||||
// over a domain name. For more details on TLS-SNI-02 see
|
|
||||||
// https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.3.
|
|
||||||
//
|
//
|
||||||
// The token argument is a Challenge.Token value.
|
// Deprecated: This challenge type is unused in both draft-02 and RFC versions of ACME spec.
|
||||||
// If a WithKey option is provided, its private part signs the returned cert,
|
|
||||||
// and the public part is used to specify the signee.
|
|
||||||
// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
|
|
||||||
//
|
|
||||||
// The returned certificate is valid for the next 24 hours and must be presented only when
|
|
||||||
// the server name in the TLS ClientHello matches exactly the returned name value.
|
|
||||||
func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
|
func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
|
||||||
b := sha256.Sum256([]byte(token))
|
b := sha256.Sum256([]byte(token))
|
||||||
h := hex.EncodeToString(b[:])
|
h := hex.EncodeToString(b[:])
|
||||||
@ -663,7 +800,7 @@ func (c *Client) TLSALPN01ChallengeCert(token, domain string, opt ...CertOption)
|
|||||||
return tlsChallengeCert([]string{domain}, newOpt)
|
return tlsChallengeCert([]string{domain}, newOpt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// doReg sends all types of registration requests.
|
// doReg sends all types of registration requests the old way (pre-RFC world).
|
||||||
// The type of request is identified by typ argument, which is a "resource"
|
// The type of request is identified by typ argument, which is a "resource"
|
||||||
// in the ACME spec terms.
|
// in the ACME spec terms.
|
||||||
//
|
//
|
||||||
@ -682,7 +819,7 @@ func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Accoun
|
|||||||
req.Contact = acct.Contact
|
req.Contact = acct.Contact
|
||||||
req.Agreement = acct.AgreedTerms
|
req.Agreement = acct.AgreedTerms
|
||||||
}
|
}
|
||||||
res, err := c.post(ctx, c.Key, url, req, wantStatus(
|
res, err := c.post(ctx, nil, url, req, wantStatus(
|
||||||
http.StatusOK, // updates and deletes
|
http.StatusOK, // updates and deletes
|
||||||
http.StatusCreated, // new account creation
|
http.StatusCreated, // new account creation
|
||||||
http.StatusAccepted, // Let's Encrypt divergent implementation
|
http.StatusAccepted, // Let's Encrypt divergent implementation
|
||||||
@ -721,12 +858,16 @@ func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Accoun
|
|||||||
}
|
}
|
||||||
|
|
||||||
// popNonce returns a nonce value previously stored with c.addNonce
|
// popNonce returns a nonce value previously stored with c.addNonce
|
||||||
// or fetches a fresh one from a URL by issuing a HEAD request.
|
// or fetches a fresh one from c.dir.NonceURL.
|
||||||
// It first tries c.directoryURL() and then the provided url if the former fails.
|
// If NonceURL is empty, it first tries c.directoryURL() and, failing that,
|
||||||
|
// the provided url.
|
||||||
func (c *Client) popNonce(ctx context.Context, url string) (string, error) {
|
func (c *Client) popNonce(ctx context.Context, url string) (string, error) {
|
||||||
c.noncesMu.Lock()
|
c.noncesMu.Lock()
|
||||||
defer c.noncesMu.Unlock()
|
defer c.noncesMu.Unlock()
|
||||||
if len(c.nonces) == 0 {
|
if len(c.nonces) == 0 {
|
||||||
|
if c.dir != nil && c.dir.NonceURL != "" {
|
||||||
|
return c.fetchNonce(ctx, c.dir.NonceURL)
|
||||||
|
}
|
||||||
dirURL := c.directoryURL()
|
dirURL := c.directoryURL()
|
||||||
v, err := c.fetchNonce(ctx, dirURL)
|
v, err := c.fetchNonce(ctx, dirURL)
|
||||||
if err != nil && url != dirURL {
|
if err != nil && url != dirURL {
|
||||||
|
314
vendor/golang.org/x/crypto/acme/autocert/autocert.go
generated
vendored
314
vendor/golang.org/x/crypto/acme/autocert/autocert.go
generated
vendored
@ -35,6 +35,9 @@ import (
|
|||||||
"golang.org/x/net/idna"
|
"golang.org/x/net/idna"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DefaultACMEDirectory is the default ACME Directory URL used when the Manager's Client is nil.
|
||||||
|
const DefaultACMEDirectory = "https://acme-v02.api.letsencrypt.org/directory"
|
||||||
|
|
||||||
// createCertRetryAfter is how much time to wait before removing a failed state
|
// createCertRetryAfter is how much time to wait before removing a failed state
|
||||||
// entry due to an unsuccessful createCert call.
|
// entry due to an unsuccessful createCert call.
|
||||||
// This is a variable instead of a const for testing.
|
// This is a variable instead of a const for testing.
|
||||||
@ -88,9 +91,9 @@ func defaultHostPolicy(context.Context, string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Manager is a stateful certificate manager built on top of acme.Client.
|
// Manager is a stateful certificate manager built on top of acme.Client.
|
||||||
// It obtains and refreshes certificates automatically using "tls-alpn-01",
|
// It obtains and refreshes certificates automatically using "tls-alpn-01"
|
||||||
// "tls-sni-01", "tls-sni-02" and "http-01" challenge types,
|
// or "http-01" challenge types, as well as providing them to a TLS server
|
||||||
// as well as providing them to a TLS server via tls.Config.
|
// via tls.Config.
|
||||||
//
|
//
|
||||||
// You must specify a cache implementation, such as DirCache,
|
// You must specify a cache implementation, such as DirCache,
|
||||||
// to reuse obtained certificates across program restarts.
|
// to reuse obtained certificates across program restarts.
|
||||||
@ -135,9 +138,10 @@ type Manager struct {
|
|||||||
// Client is used to perform low-level operations, such as account registration
|
// Client is used to perform low-level operations, such as account registration
|
||||||
// and requesting new certificates.
|
// and requesting new certificates.
|
||||||
//
|
//
|
||||||
// If Client is nil, a zero-value acme.Client is used with acme.LetsEncryptURL
|
// If Client is nil, a zero-value acme.Client is used with DefaultACMEDirectory
|
||||||
// as directory endpoint. If the Client.Key is nil, a new ECDSA P-256 key is
|
// as the directory endpoint.
|
||||||
// generated and, if Cache is not nil, stored in cache.
|
// If the Client.Key is nil, a new ECDSA P-256 key is generated and,
|
||||||
|
// if Cache is not nil, stored in cache.
|
||||||
//
|
//
|
||||||
// Mutating the field after the first call of GetCertificate method will have no effect.
|
// Mutating the field after the first call of GetCertificate method will have no effect.
|
||||||
Client *acme.Client
|
Client *acme.Client
|
||||||
@ -174,8 +178,8 @@ type Manager struct {
|
|||||||
renewalMu sync.Mutex
|
renewalMu sync.Mutex
|
||||||
renewal map[certKey]*domainRenewal
|
renewal map[certKey]*domainRenewal
|
||||||
|
|
||||||
// tokensMu guards the rest of the fields: tryHTTP01, certTokens and httpTokens.
|
// challengeMu guards tryHTTP01, certTokens and httpTokens.
|
||||||
tokensMu sync.RWMutex
|
challengeMu sync.RWMutex
|
||||||
// tryHTTP01 indicates whether the Manager should try "http-01" challenge type
|
// tryHTTP01 indicates whether the Manager should try "http-01" challenge type
|
||||||
// during the authorization flow.
|
// during the authorization flow.
|
||||||
tryHTTP01 bool
|
tryHTTP01 bool
|
||||||
@ -184,12 +188,11 @@ type Manager struct {
|
|||||||
// to be provisioned.
|
// to be provisioned.
|
||||||
// The entries are stored for the duration of the authorization flow.
|
// The entries are stored for the duration of the authorization flow.
|
||||||
httpTokens map[string][]byte
|
httpTokens map[string][]byte
|
||||||
// certTokens contains temporary certificates for tls-sni and tls-alpn challenges
|
// certTokens contains temporary certificates for tls-alpn-01 challenges
|
||||||
// and is keyed by token domain name, which matches server name of ClientHello.
|
// and is keyed by the domain name which matches the ClientHello server name.
|
||||||
// Keys always have ".acme.invalid" suffix for tls-sni. Otherwise, they are domain names
|
|
||||||
// for tls-alpn.
|
|
||||||
// The entries are stored for the duration of the authorization flow.
|
// The entries are stored for the duration of the authorization flow.
|
||||||
certTokens map[string]*tls.Certificate
|
certTokens map[string]*tls.Certificate
|
||||||
|
|
||||||
// nowFunc, if not nil, returns the current time. This may be set for
|
// nowFunc, if not nil, returns the current time. This may be set for
|
||||||
// testing purposes.
|
// testing purposes.
|
||||||
nowFunc func() time.Time
|
nowFunc func() time.Time
|
||||||
@ -226,7 +229,7 @@ func (m *Manager) TLSConfig() *tls.Config {
|
|||||||
|
|
||||||
// GetCertificate implements the tls.Config.GetCertificate hook.
|
// GetCertificate implements the tls.Config.GetCertificate hook.
|
||||||
// It provides a TLS certificate for hello.ServerName host, including answering
|
// It provides a TLS certificate for hello.ServerName host, including answering
|
||||||
// tls-alpn-01 and *.acme.invalid (tls-sni-01 and tls-sni-02) challenges.
|
// tls-alpn-01 challenges.
|
||||||
// All other fields of hello are ignored.
|
// All other fields of hello are ignored.
|
||||||
//
|
//
|
||||||
// If m.HostPolicy is non-nil, GetCertificate calls the policy before requesting
|
// If m.HostPolicy is non-nil, GetCertificate calls the policy before requesting
|
||||||
@ -235,9 +238,7 @@ func (m *Manager) TLSConfig() *tls.Config {
|
|||||||
// This does not affect cached certs. See HostPolicy field description for more details.
|
// This does not affect cached certs. See HostPolicy field description for more details.
|
||||||
//
|
//
|
||||||
// If GetCertificate is used directly, instead of via Manager.TLSConfig, package users will
|
// If GetCertificate is used directly, instead of via Manager.TLSConfig, package users will
|
||||||
// also have to add acme.ALPNProto to NextProtos for tls-alpn-01, or use HTTPHandler
|
// also have to add acme.ALPNProto to NextProtos for tls-alpn-01, or use HTTPHandler for http-01.
|
||||||
// for http-01. (The tls-sni-* challenges have been deprecated by popular ACME providers
|
|
||||||
// due to security issues in the ecosystem.)
|
|
||||||
func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||||
if m.Prompt == nil {
|
if m.Prompt == nil {
|
||||||
return nil, errors.New("acme/autocert: Manager.Prompt not set")
|
return nil, errors.New("acme/autocert: Manager.Prompt not set")
|
||||||
@ -269,13 +270,10 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate,
|
|||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// Check whether this is a token cert requested for TLS-SNI or TLS-ALPN challenge.
|
// Check whether this is a token cert requested for TLS-ALPN challenge.
|
||||||
if wantsTokenCert(hello) {
|
if wantsTokenCert(hello) {
|
||||||
m.tokensMu.RLock()
|
m.challengeMu.RLock()
|
||||||
defer m.tokensMu.RUnlock()
|
defer m.challengeMu.RUnlock()
|
||||||
// It's ok to use the same token cert key for both tls-sni and tls-alpn
|
|
||||||
// because there's always at most 1 token cert per on-going domain authorization.
|
|
||||||
// See m.verify for details.
|
|
||||||
if cert := m.certTokens[name]; cert != nil {
|
if cert := m.certTokens[name]; cert != nil {
|
||||||
return cert, nil
|
return cert, nil
|
||||||
}
|
}
|
||||||
@ -318,8 +316,7 @@ func wantsTokenCert(hello *tls.ClientHelloInfo) bool {
|
|||||||
if len(hello.SupportedProtos) == 1 && hello.SupportedProtos[0] == acme.ALPNProto {
|
if len(hello.SupportedProtos) == 1 && hello.SupportedProtos[0] == acme.ALPNProto {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// tls-sni-xx
|
return false
|
||||||
return strings.HasSuffix(hello.ServerName, ".acme.invalid")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func supportsECDSA(hello *tls.ClientHelloInfo) bool {
|
func supportsECDSA(hello *tls.ClientHelloInfo) bool {
|
||||||
@ -384,8 +381,8 @@ func supportsECDSA(hello *tls.ClientHelloInfo) bool {
|
|||||||
// If HTTPHandler is never called, the Manager will only use the "tls-alpn-01"
|
// If HTTPHandler is never called, the Manager will only use the "tls-alpn-01"
|
||||||
// challenge for domain verification.
|
// challenge for domain verification.
|
||||||
func (m *Manager) HTTPHandler(fallback http.Handler) http.Handler {
|
func (m *Manager) HTTPHandler(fallback http.Handler) http.Handler {
|
||||||
m.tokensMu.Lock()
|
m.challengeMu.Lock()
|
||||||
defer m.tokensMu.Unlock()
|
defer m.challengeMu.Unlock()
|
||||||
m.tryHTTP01 = true
|
m.tryHTTP01 = true
|
||||||
|
|
||||||
if fallback == nil {
|
if fallback == nil {
|
||||||
@ -648,71 +645,64 @@ func (m *Manager) certState(ck certKey) (*certState, error) {
|
|||||||
// authorizedCert starts the domain ownership verification process and requests a new cert upon success.
|
// authorizedCert starts the domain ownership verification process and requests a new cert upon success.
|
||||||
// The key argument is the certificate private key.
|
// The key argument is the certificate private key.
|
||||||
func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, ck certKey) (der [][]byte, leaf *x509.Certificate, err error) {
|
func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, ck certKey) (der [][]byte, leaf *x509.Certificate, err error) {
|
||||||
client, err := m.acmeClient(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := m.verify(ctx, client, ck.domain); err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
csr, err := certRequest(key, ck.domain, m.ExtraExtensions)
|
csr, err := certRequest(key, ck.domain, m.ExtraExtensions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
der, _, err = client.CreateCert(ctx, csr, 0, true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
leaf, err = validCert(ck, der, key, m.now())
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
return der, leaf, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// revokePendingAuthz revokes all authorizations idenfied by the elements of uri slice.
|
|
||||||
// It ignores revocation errors.
|
|
||||||
func (m *Manager) revokePendingAuthz(ctx context.Context, uri []string) {
|
|
||||||
client, err := m.acmeClient(ctx)
|
client, err := m.acmeClient(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
for _, u := range uri {
|
dir, err := client.Discover(ctx)
|
||||||
client.RevokeAuthorization(ctx, u)
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var chain [][]byte
|
||||||
|
switch {
|
||||||
|
// Pre-RFC legacy CA.
|
||||||
|
case dir.OrderURL == "":
|
||||||
|
if err := m.verify(ctx, client, ck.domain); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
der, _, err := client.CreateCert(ctx, csr, 0, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
chain = der
|
||||||
|
// RFC 8555 compliant CA.
|
||||||
|
default:
|
||||||
|
o, err := m.verifyRFC(ctx, client, ck.domain)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
der, _, err := client.CreateOrderCert(ctx, o.FinalizeURL, csr, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
chain = der
|
||||||
|
}
|
||||||
|
leaf, err = validCert(ck, chain, key, m.now())
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return chain, leaf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify runs the identifier (domain) authorization flow
|
// verify runs the identifier (domain) pre-authorization flow for legacy CAs
|
||||||
// using each applicable ACME challenge type.
|
// using each applicable ACME challenge type.
|
||||||
func (m *Manager) verify(ctx context.Context, client *acme.Client, domain string) error {
|
func (m *Manager) verify(ctx context.Context, client *acme.Client, domain string) error {
|
||||||
// The list of challenge types we'll try to fulfill
|
// Remove all hanging authorizations to reduce rate limit quotas
|
||||||
// in this specific order.
|
// after we're done.
|
||||||
challengeTypes := []string{"tls-alpn-01", "tls-sni-02", "tls-sni-01"}
|
var authzURLs []string
|
||||||
m.tokensMu.RLock()
|
|
||||||
if m.tryHTTP01 {
|
|
||||||
challengeTypes = append(challengeTypes, "http-01")
|
|
||||||
}
|
|
||||||
m.tokensMu.RUnlock()
|
|
||||||
|
|
||||||
// Keep track of pending authzs and revoke the ones that did not validate.
|
|
||||||
pendingAuthzs := make(map[string]bool)
|
|
||||||
defer func() {
|
defer func() {
|
||||||
var uri []string
|
go m.deactivatePendingAuthz(authzURLs)
|
||||||
for k, pending := range pendingAuthzs {
|
|
||||||
if pending {
|
|
||||||
uri = append(uri, k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(uri) > 0 {
|
|
||||||
// Use "detached" background context.
|
|
||||||
// The revocations need not happen in the current verification flow.
|
|
||||||
go m.revokePendingAuthz(context.Background(), uri)
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// errs accumulates challenge failure errors, printed if all fail
|
// errs accumulates challenge failure errors, printed if all fail
|
||||||
errs := make(map[*acme.Challenge]error)
|
errs := make(map[*acme.Challenge]error)
|
||||||
|
challengeTypes := m.supportedChallengeTypes()
|
||||||
var nextTyp int // challengeType index of the next challenge type to try
|
var nextTyp int // challengeType index of the next challenge type to try
|
||||||
for {
|
for {
|
||||||
// Start domain authorization and get the challenge.
|
// Start domain authorization and get the challenge.
|
||||||
@ -720,6 +710,7 @@ func (m *Manager) verify(ctx context.Context, client *acme.Client, domain string
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
authzURLs = append(authzURLs, authz.URI)
|
||||||
// No point in accepting challenges if the authorization status
|
// No point in accepting challenges if the authorization status
|
||||||
// is in a final state.
|
// is in a final state.
|
||||||
switch authz.Status {
|
switch authz.Status {
|
||||||
@ -729,8 +720,6 @@ func (m *Manager) verify(ctx context.Context, client *acme.Client, domain string
|
|||||||
return fmt.Errorf("acme/autocert: invalid authorization %q", authz.URI)
|
return fmt.Errorf("acme/autocert: invalid authorization %q", authz.URI)
|
||||||
}
|
}
|
||||||
|
|
||||||
pendingAuthzs[authz.URI] = true
|
|
||||||
|
|
||||||
// Pick the next preferred challenge.
|
// Pick the next preferred challenge.
|
||||||
var chal *acme.Challenge
|
var chal *acme.Challenge
|
||||||
for chal == nil && nextTyp < len(challengeTypes) {
|
for chal == nil && nextTyp < len(challengeTypes) {
|
||||||
@ -760,11 +749,126 @@ func (m *Manager) verify(ctx context.Context, client *acme.Client, domain string
|
|||||||
errs[chal] = err
|
errs[chal] = err
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
delete(pendingAuthzs, authz.URI)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// verifyRFC runs the identifier (domain) order-based authorization flow for RFC compliant CAs
|
||||||
|
// using each applicable ACME challenge type.
|
||||||
|
func (m *Manager) verifyRFC(ctx context.Context, client *acme.Client, domain string) (*acme.Order, error) {
|
||||||
|
// Try each supported challenge type starting with a new order each time.
|
||||||
|
// The nextTyp index of the next challenge type to try is shared across
|
||||||
|
// all order authorizations: if we've tried a challenge type once and it didn't work,
|
||||||
|
// it will most likely not work on another order's authorization either.
|
||||||
|
challengeTypes := m.supportedChallengeTypes()
|
||||||
|
nextTyp := 0 // challengeTypes index
|
||||||
|
AuthorizeOrderLoop:
|
||||||
|
for {
|
||||||
|
o, err := client.AuthorizeOrder(ctx, acme.DomainIDs(domain))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Remove all hanging authorizations to reduce rate limit quotas
|
||||||
|
// after we're done.
|
||||||
|
defer func(urls []string) {
|
||||||
|
go m.deactivatePendingAuthz(urls)
|
||||||
|
}(o.AuthzURLs)
|
||||||
|
|
||||||
|
// Check if there's actually anything we need to do.
|
||||||
|
switch o.Status {
|
||||||
|
case acme.StatusReady:
|
||||||
|
// Already authorized.
|
||||||
|
return o, nil
|
||||||
|
case acme.StatusPending:
|
||||||
|
// Continue normal Order-based flow.
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("acme/autocert: invalid new order status %q; order URL: %q", o.Status, o.URI)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Satisfy all pending authorizations.
|
||||||
|
for _, zurl := range o.AuthzURLs {
|
||||||
|
z, err := client.GetAuthorization(ctx, zurl)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if z.Status != acme.StatusPending {
|
||||||
|
// We are interested only in pending authorizations.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Pick the next preferred challenge.
|
||||||
|
var chal *acme.Challenge
|
||||||
|
for chal == nil && nextTyp < len(challengeTypes) {
|
||||||
|
chal = pickChallenge(challengeTypes[nextTyp], z.Challenges)
|
||||||
|
nextTyp++
|
||||||
|
}
|
||||||
|
if chal == nil {
|
||||||
|
return nil, fmt.Errorf("acme/autocert: unable to satisfy %q for domain %q: no viable challenge type found", z.URI, domain)
|
||||||
|
}
|
||||||
|
// Respond to the challenge and wait for validation result.
|
||||||
|
cleanup, err := m.fulfill(ctx, client, chal, domain)
|
||||||
|
if err != nil {
|
||||||
|
continue AuthorizeOrderLoop
|
||||||
|
}
|
||||||
|
defer cleanup()
|
||||||
|
if _, err := client.Accept(ctx, chal); err != nil {
|
||||||
|
continue AuthorizeOrderLoop
|
||||||
|
}
|
||||||
|
if _, err := client.WaitAuthorization(ctx, z.URI); err != nil {
|
||||||
|
continue AuthorizeOrderLoop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All authorizations are satisfied.
|
||||||
|
// Wait for the CA to update the order status.
|
||||||
|
o, err = client.WaitOrder(ctx, o.URI)
|
||||||
|
if err != nil {
|
||||||
|
continue AuthorizeOrderLoop
|
||||||
|
}
|
||||||
|
return o, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func pickChallenge(typ string, chal []*acme.Challenge) *acme.Challenge {
|
||||||
|
for _, c := range chal {
|
||||||
|
if c.Type == typ {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) supportedChallengeTypes() []string {
|
||||||
|
m.challengeMu.RLock()
|
||||||
|
defer m.challengeMu.RUnlock()
|
||||||
|
typ := []string{"tls-alpn-01"}
|
||||||
|
if m.tryHTTP01 {
|
||||||
|
typ = append(typ, "http-01")
|
||||||
|
}
|
||||||
|
return typ
|
||||||
|
}
|
||||||
|
|
||||||
|
// deactivatePendingAuthz relinquishes all authorizations identified by the elements
|
||||||
|
// of the provided uri slice which are in "pending" state.
|
||||||
|
// It ignores revocation errors.
|
||||||
|
//
|
||||||
|
// deactivatePendingAuthz takes no context argument and instead runs with its own
|
||||||
|
// "detached" context because deactivations are done in a goroutine separate from
|
||||||
|
// that of the main issuance or renewal flow.
|
||||||
|
func (m *Manager) deactivatePendingAuthz(uri []string) {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
||||||
|
defer cancel()
|
||||||
|
client, err := m.acmeClient(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, u := range uri {
|
||||||
|
z, err := client.GetAuthorization(ctx, u)
|
||||||
|
if err == nil && z.Status == acme.StatusPending {
|
||||||
|
client.RevokeAuthorization(ctx, u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// fulfill provisions a response to the challenge chal.
|
// fulfill provisions a response to the challenge chal.
|
||||||
// The cleanup is non-nil only if provisioning succeeded.
|
// The cleanup is non-nil only if provisioning succeeded.
|
||||||
func (m *Manager) fulfill(ctx context.Context, client *acme.Client, chal *acme.Challenge, domain string) (cleanup func(), err error) {
|
func (m *Manager) fulfill(ctx context.Context, client *acme.Client, chal *acme.Challenge, domain string) (cleanup func(), err error) {
|
||||||
@ -776,20 +880,6 @@ func (m *Manager) fulfill(ctx context.Context, client *acme.Client, chal *acme.C
|
|||||||
}
|
}
|
||||||
m.putCertToken(ctx, domain, &cert)
|
m.putCertToken(ctx, domain, &cert)
|
||||||
return func() { go m.deleteCertToken(domain) }, nil
|
return func() { go m.deleteCertToken(domain) }, nil
|
||||||
case "tls-sni-01":
|
|
||||||
cert, name, err := client.TLSSNI01ChallengeCert(chal.Token)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
m.putCertToken(ctx, name, &cert)
|
|
||||||
return func() { go m.deleteCertToken(name) }, nil
|
|
||||||
case "tls-sni-02":
|
|
||||||
cert, name, err := client.TLSSNI02ChallengeCert(chal.Token)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
m.putCertToken(ctx, name, &cert)
|
|
||||||
return func() { go m.deleteCertToken(name) }, nil
|
|
||||||
case "http-01":
|
case "http-01":
|
||||||
resp, err := client.HTTP01ChallengeResponse(chal.Token)
|
resp, err := client.HTTP01ChallengeResponse(chal.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -802,20 +892,11 @@ func (m *Manager) fulfill(ctx context.Context, client *acme.Client, chal *acme.C
|
|||||||
return nil, fmt.Errorf("acme/autocert: unknown challenge type %q", chal.Type)
|
return nil, fmt.Errorf("acme/autocert: unknown challenge type %q", chal.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
func pickChallenge(typ string, chal []*acme.Challenge) *acme.Challenge {
|
|
||||||
for _, c := range chal {
|
|
||||||
if c.Type == typ {
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// putCertToken stores the token certificate with the specified name
|
// putCertToken stores the token certificate with the specified name
|
||||||
// in both m.certTokens map and m.Cache.
|
// in both m.certTokens map and m.Cache.
|
||||||
func (m *Manager) putCertToken(ctx context.Context, name string, cert *tls.Certificate) {
|
func (m *Manager) putCertToken(ctx context.Context, name string, cert *tls.Certificate) {
|
||||||
m.tokensMu.Lock()
|
m.challengeMu.Lock()
|
||||||
defer m.tokensMu.Unlock()
|
defer m.challengeMu.Unlock()
|
||||||
if m.certTokens == nil {
|
if m.certTokens == nil {
|
||||||
m.certTokens = make(map[string]*tls.Certificate)
|
m.certTokens = make(map[string]*tls.Certificate)
|
||||||
}
|
}
|
||||||
@ -826,8 +907,8 @@ func (m *Manager) putCertToken(ctx context.Context, name string, cert *tls.Certi
|
|||||||
// deleteCertToken removes the token certificate with the specified name
|
// deleteCertToken removes the token certificate with the specified name
|
||||||
// from both m.certTokens map and m.Cache.
|
// from both m.certTokens map and m.Cache.
|
||||||
func (m *Manager) deleteCertToken(name string) {
|
func (m *Manager) deleteCertToken(name string) {
|
||||||
m.tokensMu.Lock()
|
m.challengeMu.Lock()
|
||||||
defer m.tokensMu.Unlock()
|
defer m.challengeMu.Unlock()
|
||||||
delete(m.certTokens, name)
|
delete(m.certTokens, name)
|
||||||
if m.Cache != nil {
|
if m.Cache != nil {
|
||||||
ck := certKey{domain: name, isToken: true}
|
ck := certKey{domain: name, isToken: true}
|
||||||
@ -838,8 +919,8 @@ func (m *Manager) deleteCertToken(name string) {
|
|||||||
// httpToken retrieves an existing http-01 token value from an in-memory map
|
// httpToken retrieves an existing http-01 token value from an in-memory map
|
||||||
// or the optional cache.
|
// or the optional cache.
|
||||||
func (m *Manager) httpToken(ctx context.Context, tokenPath string) ([]byte, error) {
|
func (m *Manager) httpToken(ctx context.Context, tokenPath string) ([]byte, error) {
|
||||||
m.tokensMu.RLock()
|
m.challengeMu.RLock()
|
||||||
defer m.tokensMu.RUnlock()
|
defer m.challengeMu.RUnlock()
|
||||||
if v, ok := m.httpTokens[tokenPath]; ok {
|
if v, ok := m.httpTokens[tokenPath]; ok {
|
||||||
return v, nil
|
return v, nil
|
||||||
}
|
}
|
||||||
@ -854,8 +935,8 @@ func (m *Manager) httpToken(ctx context.Context, tokenPath string) ([]byte, erro
|
|||||||
//
|
//
|
||||||
// It ignores any error returned from Cache.Put.
|
// It ignores any error returned from Cache.Put.
|
||||||
func (m *Manager) putHTTPToken(ctx context.Context, tokenPath, val string) {
|
func (m *Manager) putHTTPToken(ctx context.Context, tokenPath, val string) {
|
||||||
m.tokensMu.Lock()
|
m.challengeMu.Lock()
|
||||||
defer m.tokensMu.Unlock()
|
defer m.challengeMu.Unlock()
|
||||||
if m.httpTokens == nil {
|
if m.httpTokens == nil {
|
||||||
m.httpTokens = make(map[string][]byte)
|
m.httpTokens = make(map[string][]byte)
|
||||||
}
|
}
|
||||||
@ -871,8 +952,8 @@ func (m *Manager) putHTTPToken(ctx context.Context, tokenPath, val string) {
|
|||||||
//
|
//
|
||||||
// If m.Cache is non-nil, it blocks until Cache.Delete returns without a timeout.
|
// If m.Cache is non-nil, it blocks until Cache.Delete returns without a timeout.
|
||||||
func (m *Manager) deleteHTTPToken(tokenPath string) {
|
func (m *Manager) deleteHTTPToken(tokenPath string) {
|
||||||
m.tokensMu.Lock()
|
m.challengeMu.Lock()
|
||||||
defer m.tokensMu.Unlock()
|
defer m.challengeMu.Unlock()
|
||||||
delete(m.httpTokens, tokenPath)
|
delete(m.httpTokens, tokenPath)
|
||||||
if m.Cache != nil {
|
if m.Cache != nil {
|
||||||
m.Cache.Delete(context.Background(), httpTokenCacheKey(tokenPath))
|
m.Cache.Delete(context.Background(), httpTokenCacheKey(tokenPath))
|
||||||
@ -971,7 +1052,7 @@ func (m *Manager) acmeClient(ctx context.Context) (*acme.Client, error) {
|
|||||||
|
|
||||||
client := m.Client
|
client := m.Client
|
||||||
if client == nil {
|
if client == nil {
|
||||||
client = &acme.Client{DirectoryURL: acme.LetsEncryptURL}
|
client = &acme.Client{DirectoryURL: DefaultACMEDirectory}
|
||||||
}
|
}
|
||||||
if client.Key == nil {
|
if client.Key == nil {
|
||||||
var err error
|
var err error
|
||||||
@ -989,14 +1070,23 @@ func (m *Manager) acmeClient(ctx context.Context) (*acme.Client, error) {
|
|||||||
}
|
}
|
||||||
a := &acme.Account{Contact: contact}
|
a := &acme.Account{Contact: contact}
|
||||||
_, err := client.Register(ctx, a, m.Prompt)
|
_, err := client.Register(ctx, a, m.Prompt)
|
||||||
if ae, ok := err.(*acme.Error); err == nil || ok && ae.StatusCode == http.StatusConflict {
|
if err == nil || isAccountAlreadyExist(err) {
|
||||||
// conflict indicates the key is already registered
|
|
||||||
m.client = client
|
m.client = client
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
return m.client, err
|
return m.client, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isAccountAlreadyExist reports whether the err, as returned from acme.Client.Register,
|
||||||
|
// indicates the account has already been registered.
|
||||||
|
func isAccountAlreadyExist(err error) bool {
|
||||||
|
if err == acme.ErrAccountAlreadyExists {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
ae, ok := err.(*acme.Error)
|
||||||
|
return ok && ae.StatusCode == http.StatusConflict
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Manager) hostPolicy() HostPolicy {
|
func (m *Manager) hostPolicy() HostPolicy {
|
||||||
if m.HostPolicy != nil {
|
if m.HostPolicy != nil {
|
||||||
return m.HostPolicy
|
return m.HostPolicy
|
||||||
|
8
vendor/golang.org/x/crypto/acme/autocert/cache.go
generated
vendored
8
vendor/golang.org/x/crypto/acme/autocert/cache.go
generated
vendored
@ -77,6 +77,7 @@ func (d DirCache) Put(ctx context.Context, name string, data []byte) error {
|
|||||||
if tmp, err = d.writeTempFile(name, data); err != nil {
|
if tmp, err = d.writeTempFile(name, data); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer os.Remove(tmp)
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
// Don't overwrite the file if the context was canceled.
|
// Don't overwrite the file if the context was canceled.
|
||||||
@ -116,12 +117,17 @@ func (d DirCache) Delete(ctx context.Context, name string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// writeTempFile writes b to a temporary file, closes the file and returns its path.
|
// writeTempFile writes b to a temporary file, closes the file and returns its path.
|
||||||
func (d DirCache) writeTempFile(prefix string, b []byte) (string, error) {
|
func (d DirCache) writeTempFile(prefix string, b []byte) (name string, reterr error) {
|
||||||
// TempFile uses 0600 permissions
|
// TempFile uses 0600 permissions
|
||||||
f, err := ioutil.TempFile(string(d), prefix)
|
f, err := ioutil.TempFile(string(d), prefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
defer func() {
|
||||||
|
if reterr != nil {
|
||||||
|
os.Remove(f.Name())
|
||||||
|
}
|
||||||
|
}()
|
||||||
if _, err := f.Write(b); err != nil {
|
if _, err := f.Write(b); err != nil {
|
||||||
f.Close()
|
f.Close()
|
||||||
return "", err
|
return "", err
|
||||||
|
28
vendor/golang.org/x/crypto/acme/http.go
generated
vendored
28
vendor/golang.org/x/crypto/acme/http.go
generated
vendored
@ -155,8 +155,16 @@ func (c *Client) get(ctx context.Context, url string, ok resOkay) (*http.Respons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// postAsGet is POST-as-GET, a replacement for GET in RFC8555
|
||||||
|
// as described in https://tools.ietf.org/html/rfc8555#section-6.3.
|
||||||
|
// It makes a POST request in KID form with zero JWS payload.
|
||||||
|
// See nopayload doc comments in jws.go.
|
||||||
|
func (c *Client) postAsGet(ctx context.Context, url string, ok resOkay) (*http.Response, error) {
|
||||||
|
return c.post(ctx, nil, url, noPayload, ok)
|
||||||
|
}
|
||||||
|
|
||||||
// post issues a signed POST request in JWS format using the provided key
|
// post issues a signed POST request in JWS format using the provided key
|
||||||
// to the specified URL.
|
// to the specified URL. If key is nil, c.Key is used instead.
|
||||||
// It returns a non-error value only when ok reports true.
|
// It returns a non-error value only when ok reports true.
|
||||||
//
|
//
|
||||||
// post retries unsuccessful attempts according to c.RetryBackoff
|
// post retries unsuccessful attempts according to c.RetryBackoff
|
||||||
@ -193,14 +201,28 @@ func (c *Client) post(ctx context.Context, key crypto.Signer, url string, body i
|
|||||||
}
|
}
|
||||||
|
|
||||||
// postNoRetry signs the body with the given key and POSTs it to the provided url.
|
// postNoRetry signs the body with the given key and POSTs it to the provided url.
|
||||||
// The body argument must be JSON-serializable.
|
|
||||||
// It is used by c.post to retry unsuccessful attempts.
|
// It is used by c.post to retry unsuccessful attempts.
|
||||||
|
// The body argument must be JSON-serializable.
|
||||||
|
//
|
||||||
|
// If key argument is nil, c.Key is used to sign the request.
|
||||||
|
// If key argument is nil and c.accountKID returns a non-zero keyID,
|
||||||
|
// the request is sent in KID form. Otherwise, JWK form is used.
|
||||||
|
//
|
||||||
|
// In practice, when interfacing with RFC-compliant CAs most requests are sent in KID form
|
||||||
|
// and JWK is used only when KID is unavailable: new account endpoint and certificate
|
||||||
|
// revocation requests authenticated by a cert key.
|
||||||
|
// See jwsEncodeJSON for other details.
|
||||||
func (c *Client) postNoRetry(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, *http.Request, error) {
|
func (c *Client) postNoRetry(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, *http.Request, error) {
|
||||||
|
kid := noKeyID
|
||||||
|
if key == nil {
|
||||||
|
key = c.Key
|
||||||
|
kid = c.accountKID(ctx)
|
||||||
|
}
|
||||||
nonce, err := c.popNonce(ctx, url)
|
nonce, err := c.popNonce(ctx, url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
b, err := jwsEncodeJSON(body, key, nonce)
|
b, err := jwsEncodeJSON(body, key, kid, nonce, url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
79
vendor/golang.org/x/crypto/acme/jws.go
generated
vendored
79
vendor/golang.org/x/crypto/acme/jws.go
generated
vendored
@ -11,31 +11,60 @@ import (
|
|||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
_ "crypto/sha512" // need for EC keys
|
_ "crypto/sha512" // need for EC keys
|
||||||
|
"encoding/asn1"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// keyID is the account identity provided by a CA during registration.
|
||||||
|
type keyID string
|
||||||
|
|
||||||
|
// noKeyID indicates that jwsEncodeJSON should compute and use JWK instead of a KID.
|
||||||
|
// See jwsEncodeJSON for details.
|
||||||
|
const noKeyID = keyID("")
|
||||||
|
|
||||||
|
// noPayload indicates jwsEncodeJSON will encode zero-length octet string
|
||||||
|
// in a JWS request. This is called POST-as-GET in RFC 8555 and is used to make
|
||||||
|
// authenticated GET requests via POSTing with an empty payload.
|
||||||
|
// See https://tools.ietf.org/html/rfc8555#section-6.3 for more details.
|
||||||
|
const noPayload = ""
|
||||||
|
|
||||||
// jwsEncodeJSON signs claimset using provided key and a nonce.
|
// jwsEncodeJSON signs claimset using provided key and a nonce.
|
||||||
// The result is serialized in JSON format.
|
// The result is serialized in JSON format containing either kid or jwk
|
||||||
|
// fields based on the provided keyID value.
|
||||||
|
//
|
||||||
|
// If kid is non-empty, its quoted value is inserted in the protected head
|
||||||
|
// as "kid" field value. Otherwise, JWK is computed using jwkEncode and inserted
|
||||||
|
// as "jwk" field value. The "jwk" and "kid" fields are mutually exclusive.
|
||||||
|
//
|
||||||
// See https://tools.ietf.org/html/rfc7515#section-7.
|
// See https://tools.ietf.org/html/rfc7515#section-7.
|
||||||
func jwsEncodeJSON(claimset interface{}, key crypto.Signer, nonce string) ([]byte, error) {
|
func jwsEncodeJSON(claimset interface{}, key crypto.Signer, kid keyID, nonce, url string) ([]byte, error) {
|
||||||
jwk, err := jwkEncode(key.Public())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
alg, sha := jwsHasher(key.Public())
|
alg, sha := jwsHasher(key.Public())
|
||||||
if alg == "" || !sha.Available() {
|
if alg == "" || !sha.Available() {
|
||||||
return nil, ErrUnsupportedKey
|
return nil, ErrUnsupportedKey
|
||||||
}
|
}
|
||||||
phead := fmt.Sprintf(`{"alg":%q,"jwk":%s,"nonce":%q}`, alg, jwk, nonce)
|
var phead string
|
||||||
phead = base64.RawURLEncoding.EncodeToString([]byte(phead))
|
switch kid {
|
||||||
cs, err := json.Marshal(claimset)
|
case noKeyID:
|
||||||
if err != nil {
|
jwk, err := jwkEncode(key.Public())
|
||||||
return nil, err
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
phead = fmt.Sprintf(`{"alg":%q,"jwk":%s,"nonce":%q,"url":%q}`, alg, jwk, nonce, url)
|
||||||
|
default:
|
||||||
|
phead = fmt.Sprintf(`{"alg":%q,"kid":%q,"nonce":%q,"url":%q}`, alg, kid, nonce, url)
|
||||||
|
}
|
||||||
|
phead = base64.RawURLEncoding.EncodeToString([]byte(phead))
|
||||||
|
var payload string
|
||||||
|
if claimset != noPayload {
|
||||||
|
cs, err := json.Marshal(claimset)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
payload = base64.RawURLEncoding.EncodeToString(cs)
|
||||||
}
|
}
|
||||||
payload := base64.RawURLEncoding.EncodeToString(cs)
|
|
||||||
hash := sha.New()
|
hash := sha.New()
|
||||||
hash.Write([]byte(phead + "." + payload))
|
hash.Write([]byte(phead + "." + payload))
|
||||||
sig, err := jwsSign(key, sha, hash.Sum(nil))
|
sig, err := jwsSign(key, sha, hash.Sum(nil))
|
||||||
@ -98,21 +127,23 @@ func jwkEncode(pub crypto.PublicKey) (string, error) {
|
|||||||
|
|
||||||
// jwsSign signs the digest using the given key.
|
// jwsSign signs the digest using the given key.
|
||||||
// The hash is unused for ECDSA keys.
|
// The hash is unused for ECDSA keys.
|
||||||
//
|
|
||||||
// Note: non-stdlib crypto.Signer implementations are expected to return
|
|
||||||
// the signature in the format as specified in RFC7518.
|
|
||||||
// See https://tools.ietf.org/html/rfc7518 for more details.
|
|
||||||
func jwsSign(key crypto.Signer, hash crypto.Hash, digest []byte) ([]byte, error) {
|
func jwsSign(key crypto.Signer, hash crypto.Hash, digest []byte) ([]byte, error) {
|
||||||
if key, ok := key.(*ecdsa.PrivateKey); ok {
|
switch pub := key.Public().(type) {
|
||||||
// The key.Sign method of ecdsa returns ASN1-encoded signature.
|
case *rsa.PublicKey:
|
||||||
// So, we use the package Sign function instead
|
return key.Sign(rand.Reader, digest, hash)
|
||||||
// to get R and S values directly and format the result accordingly.
|
case *ecdsa.PublicKey:
|
||||||
r, s, err := ecdsa.Sign(rand.Reader, key, digest)
|
sigASN1, err := key.Sign(rand.Reader, digest, hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
rb, sb := r.Bytes(), s.Bytes()
|
|
||||||
size := key.Params().BitSize / 8
|
var rs struct{ R, S *big.Int }
|
||||||
|
if _, err := asn1.Unmarshal(sigASN1, &rs); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rb, sb := rs.R.Bytes(), rs.S.Bytes()
|
||||||
|
size := pub.Params().BitSize / 8
|
||||||
if size%8 > 0 {
|
if size%8 > 0 {
|
||||||
size++
|
size++
|
||||||
}
|
}
|
||||||
@ -121,7 +152,7 @@ func jwsSign(key crypto.Signer, hash crypto.Hash, digest []byte) ([]byte, error)
|
|||||||
copy(sig[size*2-len(sb):], sb)
|
copy(sig[size*2-len(sb):], sb)
|
||||||
return sig, nil
|
return sig, nil
|
||||||
}
|
}
|
||||||
return key.Sign(rand.Reader, digest, hash)
|
return nil, ErrUnsupportedKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// jwsHasher indicates suitable JWS algorithm name and a hash function
|
// jwsHasher indicates suitable JWS algorithm name and a hash function
|
||||||
|
392
vendor/golang.org/x/crypto/acme/rfc8555.go
generated
vendored
Normal file
392
vendor/golang.org/x/crypto/acme/rfc8555.go
generated
vendored
Normal file
@ -0,0 +1,392 @@
|
|||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package acme
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"encoding/pem"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeactivateReg permanently disables an existing account associated with c.Key.
|
||||||
|
// A deactivated account can no longer request certificate issuance or access
|
||||||
|
// resources related to the account, such as orders or authorizations.
|
||||||
|
//
|
||||||
|
// It only works with CAs implementing RFC 8555.
|
||||||
|
func (c *Client) DeactivateReg(ctx context.Context) error {
|
||||||
|
url := string(c.accountKID(ctx))
|
||||||
|
if url == "" {
|
||||||
|
return ErrNoAccount
|
||||||
|
}
|
||||||
|
req := json.RawMessage(`{"status": "deactivated"}`)
|
||||||
|
res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
res.Body.Close()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// registerRFC is quivalent to c.Register but for CAs implementing RFC 8555.
|
||||||
|
// It expects c.Discover to have already been called.
|
||||||
|
// TODO: Implement externalAccountBinding.
|
||||||
|
func (c *Client) registerRFC(ctx context.Context, acct *Account, prompt func(tosURL string) bool) (*Account, error) {
|
||||||
|
c.cacheMu.Lock() // guard c.kid access
|
||||||
|
defer c.cacheMu.Unlock()
|
||||||
|
|
||||||
|
req := struct {
|
||||||
|
TermsAgreed bool `json:"termsOfServiceAgreed,omitempty"`
|
||||||
|
Contact []string `json:"contact,omitempty"`
|
||||||
|
}{
|
||||||
|
Contact: acct.Contact,
|
||||||
|
}
|
||||||
|
if c.dir.Terms != "" {
|
||||||
|
req.TermsAgreed = prompt(c.dir.Terms)
|
||||||
|
}
|
||||||
|
res, err := c.post(ctx, c.Key, c.dir.RegURL, req, wantStatus(
|
||||||
|
http.StatusOK, // account with this key already registered
|
||||||
|
http.StatusCreated, // new account created
|
||||||
|
))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer res.Body.Close()
|
||||||
|
a, err := responseAccount(res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Cache Account URL even if we return an error to the caller.
|
||||||
|
// It is by all means a valid and usable "kid" value for future requests.
|
||||||
|
c.kid = keyID(a.URI)
|
||||||
|
if res.StatusCode == http.StatusOK {
|
||||||
|
return nil, ErrAccountAlreadyExists
|
||||||
|
}
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// updateGegRFC is equivalent to c.UpdateReg but for CAs implementing RFC 8555.
|
||||||
|
// It expects c.Discover to have already been called.
|
||||||
|
func (c *Client) updateRegRFC(ctx context.Context, a *Account) (*Account, error) {
|
||||||
|
url := string(c.accountKID(ctx))
|
||||||
|
if url == "" {
|
||||||
|
return nil, ErrNoAccount
|
||||||
|
}
|
||||||
|
req := struct {
|
||||||
|
Contact []string `json:"contact,omitempty"`
|
||||||
|
}{
|
||||||
|
Contact: a.Contact,
|
||||||
|
}
|
||||||
|
res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
return responseAccount(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getGegRFC is equivalent to c.GetReg but for CAs implementing RFC 8555.
|
||||||
|
// It expects c.Discover to have already been called.
|
||||||
|
func (c *Client) getRegRFC(ctx context.Context) (*Account, error) {
|
||||||
|
req := json.RawMessage(`{"onlyReturnExisting": true}`)
|
||||||
|
res, err := c.post(ctx, c.Key, c.dir.RegURL, req, wantStatus(http.StatusOK))
|
||||||
|
if e, ok := err.(*Error); ok && e.ProblemType == "urn:ietf:params:acme:error:accountDoesNotExist" {
|
||||||
|
return nil, ErrNoAccount
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer res.Body.Close()
|
||||||
|
return responseAccount(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func responseAccount(res *http.Response) (*Account, error) {
|
||||||
|
var v struct {
|
||||||
|
Status string
|
||||||
|
Contact []string
|
||||||
|
Orders string
|
||||||
|
}
|
||||||
|
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
||||||
|
return nil, fmt.Errorf("acme: invalid account response: %v", err)
|
||||||
|
}
|
||||||
|
return &Account{
|
||||||
|
URI: res.Header.Get("Location"),
|
||||||
|
Status: v.Status,
|
||||||
|
Contact: v.Contact,
|
||||||
|
OrdersURL: v.Orders,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuthorizeOrder initiates the order-based application for certificate issuance,
|
||||||
|
// as opposed to pre-authorization in Authorize.
|
||||||
|
// It is only supported by CAs implementing RFC 8555.
|
||||||
|
//
|
||||||
|
// The caller then needs to fetch each authorization with GetAuthorization,
|
||||||
|
// identify those with StatusPending status and fulfill a challenge using Accept.
|
||||||
|
// Once all authorizations are satisfied, the caller will typically want to poll
|
||||||
|
// order status using WaitOrder until it's in StatusReady state.
|
||||||
|
// To finalize the order and obtain a certificate, the caller submits a CSR with CreateOrderCert.
|
||||||
|
func (c *Client) AuthorizeOrder(ctx context.Context, id []AuthzID, opt ...OrderOption) (*Order, error) {
|
||||||
|
dir, err := c.Discover(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req := struct {
|
||||||
|
Identifiers []wireAuthzID `json:"identifiers"`
|
||||||
|
NotBefore string `json:"notBefore,omitempty"`
|
||||||
|
NotAfter string `json:"notAfter,omitempty"`
|
||||||
|
}{}
|
||||||
|
for _, v := range id {
|
||||||
|
req.Identifiers = append(req.Identifiers, wireAuthzID{
|
||||||
|
Type: v.Type,
|
||||||
|
Value: v.Value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
for _, o := range opt {
|
||||||
|
switch o := o.(type) {
|
||||||
|
case orderNotBeforeOpt:
|
||||||
|
req.NotBefore = time.Time(o).Format(time.RFC3339)
|
||||||
|
case orderNotAfterOpt:
|
||||||
|
req.NotAfter = time.Time(o).Format(time.RFC3339)
|
||||||
|
default:
|
||||||
|
// Package's fault if we let this happen.
|
||||||
|
panic(fmt.Sprintf("unsupported order option type %T", o))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := c.post(ctx, nil, dir.OrderURL, req, wantStatus(http.StatusCreated))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
return responseOrder(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOrder retrives an order identified by the given URL.
|
||||||
|
// For orders created with AuthorizeOrder, the url value is Order.URI.
|
||||||
|
//
|
||||||
|
// If a caller needs to poll an order until its status is final,
|
||||||
|
// see the WaitOrder method.
|
||||||
|
func (c *Client) GetOrder(ctx context.Context, url string) (*Order, error) {
|
||||||
|
if _, err := c.Discover(ctx); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
return responseOrder(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WaitOrder polls an order from the given URL until it is in one of the final states,
|
||||||
|
// StatusReady, StatusValid or StatusInvalid, the CA responded with a non-retryable error
|
||||||
|
// or the context is done.
|
||||||
|
//
|
||||||
|
// It returns a non-nil Order only if its Status is StatusReady or StatusValid.
|
||||||
|
// In all other cases WaitOrder returns an error.
|
||||||
|
// If the Status is StatusInvalid, the returned error is of type *OrderError.
|
||||||
|
func (c *Client) WaitOrder(ctx context.Context, url string) (*Order, error) {
|
||||||
|
if _, err := c.Discover(ctx); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
o, err := responseOrder(res)
|
||||||
|
res.Body.Close()
|
||||||
|
switch {
|
||||||
|
case err != nil:
|
||||||
|
// Skip and retry.
|
||||||
|
case o.Status == StatusInvalid:
|
||||||
|
return nil, &OrderError{OrderURL: o.URI, Status: o.Status}
|
||||||
|
case o.Status == StatusReady || o.Status == StatusValid:
|
||||||
|
return o, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
d := retryAfter(res.Header.Get("Retry-After"))
|
||||||
|
if d == 0 {
|
||||||
|
// Default retry-after.
|
||||||
|
// Same reasoning as in WaitAuthorization.
|
||||||
|
d = time.Second
|
||||||
|
}
|
||||||
|
t := time.NewTimer(d)
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
t.Stop()
|
||||||
|
return nil, ctx.Err()
|
||||||
|
case <-t.C:
|
||||||
|
// Retry.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func responseOrder(res *http.Response) (*Order, error) {
|
||||||
|
var v struct {
|
||||||
|
Status string
|
||||||
|
Expires time.Time
|
||||||
|
Identifiers []wireAuthzID
|
||||||
|
NotBefore time.Time
|
||||||
|
NotAfter time.Time
|
||||||
|
Error *wireError
|
||||||
|
Authorizations []string
|
||||||
|
Finalize string
|
||||||
|
Certificate string
|
||||||
|
}
|
||||||
|
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
||||||
|
return nil, fmt.Errorf("acme: error reading order: %v", err)
|
||||||
|
}
|
||||||
|
o := &Order{
|
||||||
|
URI: res.Header.Get("Location"),
|
||||||
|
Status: v.Status,
|
||||||
|
Expires: v.Expires,
|
||||||
|
NotBefore: v.NotBefore,
|
||||||
|
NotAfter: v.NotAfter,
|
||||||
|
AuthzURLs: v.Authorizations,
|
||||||
|
FinalizeURL: v.Finalize,
|
||||||
|
CertURL: v.Certificate,
|
||||||
|
}
|
||||||
|
for _, id := range v.Identifiers {
|
||||||
|
o.Identifiers = append(o.Identifiers, AuthzID{Type: id.Type, Value: id.Value})
|
||||||
|
}
|
||||||
|
if v.Error != nil {
|
||||||
|
o.Error = v.Error.error(nil /* headers */)
|
||||||
|
}
|
||||||
|
return o, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrderCert submits the CSR (Certificate Signing Request) to a CA at the specified URL.
|
||||||
|
// The URL is the FinalizeURL field of an Order created with AuthorizeOrder.
|
||||||
|
//
|
||||||
|
// If the bundle argument is true, the returned value also contain the CA (issuer)
|
||||||
|
// certificate chain. Otherwise, only a leaf certificate is returned.
|
||||||
|
// The returned URL can be used to re-fetch the certificate using FetchCert.
|
||||||
|
//
|
||||||
|
// This method is only supported by CAs implementing RFC 8555. See CreateCert for pre-RFC CAs.
|
||||||
|
//
|
||||||
|
// CreateOrderCert returns an error if the CA's response is unreasonably large.
|
||||||
|
// Callers are encouraged to parse the returned value to ensure the certificate is valid and has the expected features.
|
||||||
|
func (c *Client) CreateOrderCert(ctx context.Context, url string, csr []byte, bundle bool) (der [][]byte, certURL string, err error) {
|
||||||
|
if _, err := c.Discover(ctx); err != nil { // required by c.accountKID
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RFC describes this as "finalize order" request.
|
||||||
|
req := struct {
|
||||||
|
CSR string `json:"csr"`
|
||||||
|
}{
|
||||||
|
CSR: base64.RawURLEncoding.EncodeToString(csr),
|
||||||
|
}
|
||||||
|
res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK))
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
o, err := responseOrder(res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for CA to issue the cert if they haven't.
|
||||||
|
if o.Status != StatusValid {
|
||||||
|
o, err = c.WaitOrder(ctx, o.URI)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
// The only acceptable status post finalize and WaitOrder is "valid".
|
||||||
|
if o.Status != StatusValid {
|
||||||
|
return nil, "", &OrderError{OrderURL: o.URI, Status: o.Status}
|
||||||
|
}
|
||||||
|
crt, err := c.fetchCertRFC(ctx, o.CertURL, bundle)
|
||||||
|
return crt, o.CertURL, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetchCertRFC downloads issued certificate from the given URL.
|
||||||
|
// It expects the CA to respond with PEM-encoded certificate chain.
|
||||||
|
//
|
||||||
|
// The URL argument is the CertURL field of Order.
|
||||||
|
func (c *Client) fetchCertRFC(ctx context.Context, url string, bundle bool) ([][]byte, error) {
|
||||||
|
res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
// Get all the bytes up to a sane maximum.
|
||||||
|
// Account very roughly for base64 overhead.
|
||||||
|
const max = maxCertChainSize + maxCertChainSize/33
|
||||||
|
b, err := ioutil.ReadAll(io.LimitReader(res.Body, max+1))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("acme: fetch cert response stream: %v", err)
|
||||||
|
}
|
||||||
|
if len(b) > max {
|
||||||
|
return nil, errors.New("acme: certificate chain is too big")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode PEM chain.
|
||||||
|
var chain [][]byte
|
||||||
|
for {
|
||||||
|
var p *pem.Block
|
||||||
|
p, b = pem.Decode(b)
|
||||||
|
if p == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if p.Type != "CERTIFICATE" {
|
||||||
|
return nil, fmt.Errorf("acme: invalid PEM cert type %q", p.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
chain = append(chain, p.Bytes)
|
||||||
|
if !bundle {
|
||||||
|
return chain, nil
|
||||||
|
}
|
||||||
|
if len(chain) > maxChainLen {
|
||||||
|
return nil, errors.New("acme: certificate chain is too long")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(chain) == 0 {
|
||||||
|
return nil, errors.New("acme: certificate chain is empty")
|
||||||
|
}
|
||||||
|
return chain, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// sends a cert revocation request in either JWK form when key is non-nil or KID form otherwise.
|
||||||
|
func (c *Client) revokeCertRFC(ctx context.Context, key crypto.Signer, cert []byte, reason CRLReasonCode) error {
|
||||||
|
req := &struct {
|
||||||
|
Cert string `json:"certificate"`
|
||||||
|
Reason int `json:"reason"`
|
||||||
|
}{
|
||||||
|
Cert: base64.RawURLEncoding.EncodeToString(cert),
|
||||||
|
Reason: int(reason),
|
||||||
|
}
|
||||||
|
res, err := c.post(ctx, key, c.dir.RevokeURL, req, wantStatus(http.StatusOK))
|
||||||
|
if err != nil {
|
||||||
|
if isAlreadyRevoked(err) {
|
||||||
|
// Assume it is not an error to revoke an already revoked cert.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isAlreadyRevoked(err error) bool {
|
||||||
|
e, ok := err.(*Error)
|
||||||
|
return ok && e.ProblemType == "urn:ietf:params:acme:error:alreadyRevoked"
|
||||||
|
}
|
307
vendor/golang.org/x/crypto/acme/types.go
generated
vendored
307
vendor/golang.org/x/crypto/acme/types.go
generated
vendored
@ -14,14 +14,18 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ACME server response statuses used to describe Authorization and Challenge states.
|
// ACME status values of Account, Order, Authorization and Challenge objects.
|
||||||
|
// See https://tools.ietf.org/html/rfc8555#section-7.1.6 for details.
|
||||||
const (
|
const (
|
||||||
StatusUnknown = "unknown"
|
StatusDeactivated = "deactivated"
|
||||||
StatusPending = "pending"
|
StatusExpired = "expired"
|
||||||
StatusProcessing = "processing"
|
StatusInvalid = "invalid"
|
||||||
StatusValid = "valid"
|
StatusPending = "pending"
|
||||||
StatusInvalid = "invalid"
|
StatusProcessing = "processing"
|
||||||
StatusRevoked = "revoked"
|
StatusReady = "ready"
|
||||||
|
StatusRevoked = "revoked"
|
||||||
|
StatusUnknown = "unknown"
|
||||||
|
StatusValid = "valid"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CRLReasonCode identifies the reason for a certificate revocation.
|
// CRLReasonCode identifies the reason for a certificate revocation.
|
||||||
@ -41,8 +45,17 @@ const (
|
|||||||
CRLReasonAACompromise CRLReasonCode = 10
|
CRLReasonAACompromise CRLReasonCode = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrUnsupportedKey is returned when an unsupported key type is encountered.
|
var (
|
||||||
var ErrUnsupportedKey = errors.New("acme: unknown key type; only RSA and ECDSA are supported")
|
// ErrUnsupportedKey is returned when an unsupported key type is encountered.
|
||||||
|
ErrUnsupportedKey = errors.New("acme: unknown key type; only RSA and ECDSA are supported")
|
||||||
|
|
||||||
|
// ErrAccountAlreadyExists indicates that the Client's key has already been registered
|
||||||
|
// with the CA. It is returned by Register method.
|
||||||
|
ErrAccountAlreadyExists = errors.New("acme: account already exists")
|
||||||
|
|
||||||
|
// ErrNoAccount indicates that the Client's key has not been registered with the CA.
|
||||||
|
ErrNoAccount = errors.New("acme: account does not exist")
|
||||||
|
)
|
||||||
|
|
||||||
// Error is an ACME error, defined in Problem Details for HTTP APIs doc
|
// Error is an ACME error, defined in Problem Details for HTTP APIs doc
|
||||||
// http://tools.ietf.org/html/draft-ietf-appsawg-http-problem.
|
// http://tools.ietf.org/html/draft-ietf-appsawg-http-problem.
|
||||||
@ -54,6 +67,12 @@ type Error struct {
|
|||||||
ProblemType string
|
ProblemType string
|
||||||
// Detail is a human-readable explanation specific to this occurrence of the problem.
|
// Detail is a human-readable explanation specific to this occurrence of the problem.
|
||||||
Detail string
|
Detail string
|
||||||
|
// Instance indicates a URL that the client should direct a human user to visit
|
||||||
|
// in order for instructions on how to agree to the updated Terms of Service.
|
||||||
|
// In such an event CA sets StatusCode to 403, ProblemType to
|
||||||
|
// "urn:ietf:params:acme:error:userActionRequired" and a Link header with relation
|
||||||
|
// "terms-of-service" containing the latest TOS URL.
|
||||||
|
Instance string
|
||||||
// Header is the original server error response headers.
|
// Header is the original server error response headers.
|
||||||
// It may be nil.
|
// It may be nil.
|
||||||
Header http.Header
|
Header http.Header
|
||||||
@ -86,6 +105,21 @@ func (a *AuthorizationError) Error() string {
|
|||||||
return fmt.Sprintf("acme: authorization error for %s: %s", a.Identifier, strings.Join(e, "; "))
|
return fmt.Sprintf("acme: authorization error for %s: %s", a.Identifier, strings.Join(e, "; "))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OrderError is returned from Client's order related methods.
|
||||||
|
// It indicates the order is unusable and the clients should start over with
|
||||||
|
// AuthorizeOrder.
|
||||||
|
//
|
||||||
|
// The clients can still fetch the order object from CA using GetOrder
|
||||||
|
// to inspect its state.
|
||||||
|
type OrderError struct {
|
||||||
|
OrderURL string
|
||||||
|
Status string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (oe *OrderError) Error() string {
|
||||||
|
return fmt.Sprintf("acme: order %s status: %s", oe.OrderURL, oe.Status)
|
||||||
|
}
|
||||||
|
|
||||||
// RateLimit reports whether err represents a rate limit error and
|
// RateLimit reports whether err represents a rate limit error and
|
||||||
// any Retry-After duration returned by the server.
|
// any Retry-After duration returned by the server.
|
||||||
//
|
//
|
||||||
@ -108,49 +142,88 @@ func RateLimit(err error) (time.Duration, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Account is a user account. It is associated with a private key.
|
// Account is a user account. It is associated with a private key.
|
||||||
|
// Non-RFC 8555 fields are empty when interfacing with a compliant CA.
|
||||||
type Account struct {
|
type Account struct {
|
||||||
// URI is the account unique ID, which is also a URL used to retrieve
|
// URI is the account unique ID, which is also a URL used to retrieve
|
||||||
// account data from the CA.
|
// account data from the CA.
|
||||||
|
// When interfacing with RFC 8555-compliant CAs, URI is the "kid" field
|
||||||
|
// value in JWS signed requests.
|
||||||
URI string
|
URI string
|
||||||
|
|
||||||
// Contact is a slice of contact info used during registration.
|
// Contact is a slice of contact info used during registration.
|
||||||
|
// See https://tools.ietf.org/html/rfc8555#section-7.3 for supported
|
||||||
|
// formats.
|
||||||
Contact []string
|
Contact []string
|
||||||
|
|
||||||
|
// Status indicates current account status as returned by the CA.
|
||||||
|
// Possible values are StatusValid, StatusDeactivated, and StatusRevoked.
|
||||||
|
Status string
|
||||||
|
|
||||||
|
// OrdersURL is a URL from which a list of orders submitted by this account
|
||||||
|
// can be fetched.
|
||||||
|
OrdersURL string
|
||||||
|
|
||||||
// The terms user has agreed to.
|
// The terms user has agreed to.
|
||||||
// A value not matching CurrentTerms indicates that the user hasn't agreed
|
// A value not matching CurrentTerms indicates that the user hasn't agreed
|
||||||
// to the actual Terms of Service of the CA.
|
// to the actual Terms of Service of the CA.
|
||||||
|
//
|
||||||
|
// It is non-RFC 8555 compliant. Package users can store the ToS they agree to
|
||||||
|
// during Client's Register call in the prompt callback function.
|
||||||
AgreedTerms string
|
AgreedTerms string
|
||||||
|
|
||||||
// Actual terms of a CA.
|
// Actual terms of a CA.
|
||||||
|
//
|
||||||
|
// It is non-RFC 8555 compliant. Use Directory's Terms field.
|
||||||
|
// When a CA updates their terms and requires an account agreement,
|
||||||
|
// a URL at which instructions to do so is available in Error's Instance field.
|
||||||
CurrentTerms string
|
CurrentTerms string
|
||||||
|
|
||||||
// Authz is the authorization URL used to initiate a new authz flow.
|
// Authz is the authorization URL used to initiate a new authz flow.
|
||||||
|
//
|
||||||
|
// It is non-RFC 8555 compliant. Use Directory's AuthzURL or OrderURL.
|
||||||
Authz string
|
Authz string
|
||||||
|
|
||||||
// Authorizations is a URI from which a list of authorizations
|
// Authorizations is a URI from which a list of authorizations
|
||||||
// granted to this account can be fetched via a GET request.
|
// granted to this account can be fetched via a GET request.
|
||||||
|
//
|
||||||
|
// It is non-RFC 8555 compliant and is obsoleted by OrdersURL.
|
||||||
Authorizations string
|
Authorizations string
|
||||||
|
|
||||||
// Certificates is a URI from which a list of certificates
|
// Certificates is a URI from which a list of certificates
|
||||||
// issued for this account can be fetched via a GET request.
|
// issued for this account can be fetched via a GET request.
|
||||||
|
//
|
||||||
|
// It is non-RFC 8555 compliant and is obsoleted by OrdersURL.
|
||||||
Certificates string
|
Certificates string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Directory is ACME server discovery data.
|
// Directory is ACME server discovery data.
|
||||||
|
// See https://tools.ietf.org/html/rfc8555#section-7.1.1 for more details.
|
||||||
type Directory struct {
|
type Directory struct {
|
||||||
// RegURL is an account endpoint URL, allowing for creating new
|
// NonceURL indicates an endpoint where to fetch fresh nonce values from.
|
||||||
// and modifying existing accounts.
|
NonceURL string
|
||||||
|
|
||||||
|
// RegURL is an account endpoint URL, allowing for creating new accounts.
|
||||||
|
// Pre-RFC 8555 CAs also allow modifying existing accounts at this URL.
|
||||||
RegURL string
|
RegURL string
|
||||||
|
|
||||||
// AuthzURL is used to initiate Identifier Authorization flow.
|
// OrderURL is used to initiate the certificate issuance flow
|
||||||
|
// as described in RFC 8555.
|
||||||
|
OrderURL string
|
||||||
|
|
||||||
|
// AuthzURL is used to initiate identifier pre-authorization flow.
|
||||||
|
// Empty string indicates the flow is unsupported by the CA.
|
||||||
AuthzURL string
|
AuthzURL string
|
||||||
|
|
||||||
// CertURL is a new certificate issuance endpoint URL.
|
// CertURL is a new certificate issuance endpoint URL.
|
||||||
|
// It is non-RFC 8555 compliant and is obsoleted by OrderURL.
|
||||||
CertURL string
|
CertURL string
|
||||||
|
|
||||||
// RevokeURL is used to initiate a certificate revocation flow.
|
// RevokeURL is used to initiate a certificate revocation flow.
|
||||||
RevokeURL string
|
RevokeURL string
|
||||||
|
|
||||||
|
// KeyChangeURL allows to perform account key rollover flow.
|
||||||
|
KeyChangeURL string
|
||||||
|
|
||||||
// Term is a URI identifying the current terms of service.
|
// Term is a URI identifying the current terms of service.
|
||||||
Terms string
|
Terms string
|
||||||
|
|
||||||
@ -162,44 +235,126 @@ type Directory struct {
|
|||||||
// recognises as referring to itself for the purposes of CAA record validation
|
// recognises as referring to itself for the purposes of CAA record validation
|
||||||
// as defined in RFC6844.
|
// as defined in RFC6844.
|
||||||
CAA []string
|
CAA []string
|
||||||
|
|
||||||
|
// ExternalAccountRequired indicates that the CA requires for all account-related
|
||||||
|
// requests to include external account binding information.
|
||||||
|
ExternalAccountRequired bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Challenge encodes a returned CA challenge.
|
// rfcCompliant reports whether the ACME server implements RFC 8555.
|
||||||
// Its Error field may be non-nil if the challenge is part of an Authorization
|
// Note that some servers may have incomplete RFC implementation
|
||||||
// with StatusInvalid.
|
// even if the returned value is true.
|
||||||
type Challenge struct {
|
// If rfcCompliant reports false, the server most likely implements draft-02.
|
||||||
// Type is the challenge type, e.g. "http-01", "tls-sni-02", "dns-01".
|
func (d *Directory) rfcCompliant() bool {
|
||||||
Type string
|
return d.OrderURL != ""
|
||||||
|
}
|
||||||
|
|
||||||
// URI is where a challenge response can be posted to.
|
// Order represents a client's request for a certificate.
|
||||||
|
// It tracks the request flow progress through to issuance.
|
||||||
|
type Order struct {
|
||||||
|
// URI uniquely identifies an order.
|
||||||
URI string
|
URI string
|
||||||
|
|
||||||
// Token is a random value that uniquely identifies the challenge.
|
// Status represents the current status of the order.
|
||||||
Token string
|
// It indicates which action the client should take.
|
||||||
|
//
|
||||||
// Status identifies the status of this challenge.
|
// Possible values are StatusPending, StatusReady, StatusProcessing, StatusValid and StatusInvalid.
|
||||||
|
// Pending means the CA does not believe that the client has fulfilled the requirements.
|
||||||
|
// Ready indicates that the client has fulfilled all the requirements and can submit a CSR
|
||||||
|
// to obtain a certificate. This is done with Client's CreateOrderCert.
|
||||||
|
// Processing means the certificate is being issued.
|
||||||
|
// Valid indicates the CA has issued the certificate. It can be downloaded
|
||||||
|
// from the Order's CertURL. This is done with Client's FetchCert.
|
||||||
|
// Invalid means the certificate will not be issued. Users should consider this order
|
||||||
|
// abandoned.
|
||||||
Status string
|
Status string
|
||||||
|
|
||||||
// Error indicates the reason for an authorization failure
|
// Expires is the timestamp after which CA considers this order invalid.
|
||||||
// when this challenge was used.
|
Expires time.Time
|
||||||
// The type of a non-nil value is *Error.
|
|
||||||
Error error
|
// Identifiers contains all identifier objects which the order pertains to.
|
||||||
|
Identifiers []AuthzID
|
||||||
|
|
||||||
|
// NotBefore is the requested value of the notBefore field in the certificate.
|
||||||
|
NotBefore time.Time
|
||||||
|
|
||||||
|
// NotAfter is the requested value of the notAfter field in the certificate.
|
||||||
|
NotAfter time.Time
|
||||||
|
|
||||||
|
// AuthzURLs represents authorizations to complete before a certificate
|
||||||
|
// for identifiers specified in the order can be issued.
|
||||||
|
// It also contains unexpired authorizations that the client has completed
|
||||||
|
// in the past.
|
||||||
|
//
|
||||||
|
// Authorization objects can be fetched using Client's GetAuthorization method.
|
||||||
|
//
|
||||||
|
// The required authorizations are dictated by CA policies.
|
||||||
|
// There may not be a 1:1 relationship between the identifiers and required authorizations.
|
||||||
|
// Required authorizations can be identified by their StatusPending status.
|
||||||
|
//
|
||||||
|
// For orders in the StatusValid or StatusInvalid state these are the authorizations
|
||||||
|
// which were completed.
|
||||||
|
AuthzURLs []string
|
||||||
|
|
||||||
|
// FinalizeURL is the endpoint at which a CSR is submitted to obtain a certificate
|
||||||
|
// once all the authorizations are satisfied.
|
||||||
|
FinalizeURL string
|
||||||
|
|
||||||
|
// CertURL points to the certificate that has been issued in response to this order.
|
||||||
|
CertURL string
|
||||||
|
|
||||||
|
// The error that occurred while processing the order as received from a CA, if any.
|
||||||
|
Error *Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OrderOption allows customizing Client.AuthorizeOrder call.
|
||||||
|
type OrderOption interface {
|
||||||
|
privateOrderOpt()
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithOrderNotBefore sets order's NotBefore field.
|
||||||
|
func WithOrderNotBefore(t time.Time) OrderOption {
|
||||||
|
return orderNotBeforeOpt(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithOrderNotAfter sets order's NotAfter field.
|
||||||
|
func WithOrderNotAfter(t time.Time) OrderOption {
|
||||||
|
return orderNotAfterOpt(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
type orderNotBeforeOpt time.Time
|
||||||
|
|
||||||
|
func (orderNotBeforeOpt) privateOrderOpt() {}
|
||||||
|
|
||||||
|
type orderNotAfterOpt time.Time
|
||||||
|
|
||||||
|
func (orderNotAfterOpt) privateOrderOpt() {}
|
||||||
|
|
||||||
// Authorization encodes an authorization response.
|
// Authorization encodes an authorization response.
|
||||||
type Authorization struct {
|
type Authorization struct {
|
||||||
// URI uniquely identifies a authorization.
|
// URI uniquely identifies a authorization.
|
||||||
URI string
|
URI string
|
||||||
|
|
||||||
// Status identifies the status of an authorization.
|
// Status is the current status of an authorization.
|
||||||
|
// Possible values are StatusPending, StatusValid, StatusInvalid, StatusDeactivated,
|
||||||
|
// StatusExpired and StatusRevoked.
|
||||||
Status string
|
Status string
|
||||||
|
|
||||||
// Identifier is what the account is authorized to represent.
|
// Identifier is what the account is authorized to represent.
|
||||||
Identifier AuthzID
|
Identifier AuthzID
|
||||||
|
|
||||||
|
// The timestamp after which the CA considers the authorization invalid.
|
||||||
|
Expires time.Time
|
||||||
|
|
||||||
|
// Wildcard is true for authorizations of a wildcard domain name.
|
||||||
|
Wildcard bool
|
||||||
|
|
||||||
// Challenges that the client needs to fulfill in order to prove possession
|
// Challenges that the client needs to fulfill in order to prove possession
|
||||||
// of the identifier (for pending authorizations).
|
// of the identifier (for pending authorizations).
|
||||||
// For final authorizations, the challenges that were used.
|
// For valid authorizations, the challenge that was validated.
|
||||||
|
// For invalid authorizations, the challenge that was attempted and failed.
|
||||||
|
//
|
||||||
|
// RFC 8555 compatible CAs require users to fuflfill only one of the challenges.
|
||||||
Challenges []*Challenge
|
Challenges []*Challenge
|
||||||
|
|
||||||
// A collection of sets of challenges, each of which would be sufficient
|
// A collection of sets of challenges, each of which would be sufficient
|
||||||
@ -207,24 +362,51 @@ type Authorization struct {
|
|||||||
// Clients must complete a set of challenges that covers at least one set.
|
// Clients must complete a set of challenges that covers at least one set.
|
||||||
// Challenges are identified by their indices in the challenges array.
|
// Challenges are identified by their indices in the challenges array.
|
||||||
// If this field is empty, the client needs to complete all challenges.
|
// If this field is empty, the client needs to complete all challenges.
|
||||||
|
//
|
||||||
|
// This field is unused in RFC 8555.
|
||||||
Combinations [][]int
|
Combinations [][]int
|
||||||
}
|
}
|
||||||
|
|
||||||
// AuthzID is an identifier that an account is authorized to represent.
|
// AuthzID is an identifier that an account is authorized to represent.
|
||||||
type AuthzID struct {
|
type AuthzID struct {
|
||||||
Type string // The type of identifier, e.g. "dns".
|
Type string // The type of identifier, "dns" or "ip".
|
||||||
Value string // The identifier itself, e.g. "example.org".
|
Value string // The identifier itself, e.g. "example.org".
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DomainIDs creates a slice of AuthzID with "dns" identifier type.
|
||||||
|
func DomainIDs(names ...string) []AuthzID {
|
||||||
|
a := make([]AuthzID, len(names))
|
||||||
|
for i, v := range names {
|
||||||
|
a[i] = AuthzID{Type: "dns", Value: v}
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPIDs creates a slice of AuthzID with "ip" identifier type.
|
||||||
|
// Each element of addr is textual form of an address as defined
|
||||||
|
// in RFC1123 Section 2.1 for IPv4 and in RFC5952 Section 4 for IPv6.
|
||||||
|
func IPIDs(addr ...string) []AuthzID {
|
||||||
|
a := make([]AuthzID, len(addr))
|
||||||
|
for i, v := range addr {
|
||||||
|
a[i] = AuthzID{Type: "ip", Value: v}
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
// wireAuthzID is ACME JSON representation of authorization identifier objects.
|
||||||
|
type wireAuthzID struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
}
|
||||||
|
|
||||||
// wireAuthz is ACME JSON representation of Authorization objects.
|
// wireAuthz is ACME JSON representation of Authorization objects.
|
||||||
type wireAuthz struct {
|
type wireAuthz struct {
|
||||||
|
Identifier wireAuthzID
|
||||||
Status string
|
Status string
|
||||||
|
Expires time.Time
|
||||||
|
Wildcard bool
|
||||||
Challenges []wireChallenge
|
Challenges []wireChallenge
|
||||||
Combinations [][]int
|
Combinations [][]int
|
||||||
Identifier struct {
|
|
||||||
Type string
|
|
||||||
Value string
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (z *wireAuthz) authorization(uri string) *Authorization {
|
func (z *wireAuthz) authorization(uri string) *Authorization {
|
||||||
@ -232,8 +414,10 @@ func (z *wireAuthz) authorization(uri string) *Authorization {
|
|||||||
URI: uri,
|
URI: uri,
|
||||||
Status: z.Status,
|
Status: z.Status,
|
||||||
Identifier: AuthzID{Type: z.Identifier.Type, Value: z.Identifier.Value},
|
Identifier: AuthzID{Type: z.Identifier.Type, Value: z.Identifier.Value},
|
||||||
Combinations: z.Combinations, // shallow copy
|
Expires: z.Expires,
|
||||||
|
Wildcard: z.Wildcard,
|
||||||
Challenges: make([]*Challenge, len(z.Challenges)),
|
Challenges: make([]*Challenge, len(z.Challenges)),
|
||||||
|
Combinations: z.Combinations, // shallow copy
|
||||||
}
|
}
|
||||||
for i, v := range z.Challenges {
|
for i, v := range z.Challenges {
|
||||||
a.Challenges[i] = v.challenge()
|
a.Challenges[i] = v.challenge()
|
||||||
@ -254,22 +438,55 @@ func (z *wireAuthz) error(uri string) *AuthorizationError {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Challenge encodes a returned CA challenge.
|
||||||
|
// Its Error field may be non-nil if the challenge is part of an Authorization
|
||||||
|
// with StatusInvalid.
|
||||||
|
type Challenge struct {
|
||||||
|
// Type is the challenge type, e.g. "http-01", "tls-alpn-01", "dns-01".
|
||||||
|
Type string
|
||||||
|
|
||||||
|
// URI is where a challenge response can be posted to.
|
||||||
|
URI string
|
||||||
|
|
||||||
|
// Token is a random value that uniquely identifies the challenge.
|
||||||
|
Token string
|
||||||
|
|
||||||
|
// Status identifies the status of this challenge.
|
||||||
|
// In RFC 8555, possible values are StatusPending, StatusProcessing, StatusValid,
|
||||||
|
// and StatusInvalid.
|
||||||
|
Status string
|
||||||
|
|
||||||
|
// Validated is the time at which the CA validated this challenge.
|
||||||
|
// Always zero value in pre-RFC 8555.
|
||||||
|
Validated time.Time
|
||||||
|
|
||||||
|
// Error indicates the reason for an authorization failure
|
||||||
|
// when this challenge was used.
|
||||||
|
// The type of a non-nil value is *Error.
|
||||||
|
Error error
|
||||||
|
}
|
||||||
|
|
||||||
// wireChallenge is ACME JSON challenge representation.
|
// wireChallenge is ACME JSON challenge representation.
|
||||||
type wireChallenge struct {
|
type wireChallenge struct {
|
||||||
URI string `json:"uri"`
|
URL string `json:"url"` // RFC
|
||||||
Type string
|
URI string `json:"uri"` // pre-RFC
|
||||||
Token string
|
Type string
|
||||||
Status string
|
Token string
|
||||||
Error *wireError
|
Status string
|
||||||
|
Validated time.Time
|
||||||
|
Error *wireError
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *wireChallenge) challenge() *Challenge {
|
func (c *wireChallenge) challenge() *Challenge {
|
||||||
v := &Challenge{
|
v := &Challenge{
|
||||||
URI: c.URI,
|
URI: c.URL,
|
||||||
Type: c.Type,
|
Type: c.Type,
|
||||||
Token: c.Token,
|
Token: c.Token,
|
||||||
Status: c.Status,
|
Status: c.Status,
|
||||||
}
|
}
|
||||||
|
if v.URI == "" {
|
||||||
|
v.URI = c.URI // c.URL was empty; use legacy
|
||||||
|
}
|
||||||
if v.Status == "" {
|
if v.Status == "" {
|
||||||
v.Status = StatusPending
|
v.Status = StatusPending
|
||||||
}
|
}
|
||||||
@ -282,9 +499,10 @@ func (c *wireChallenge) challenge() *Challenge {
|
|||||||
// wireError is a subset of fields of the Problem Details object
|
// wireError is a subset of fields of the Problem Details object
|
||||||
// as described in https://tools.ietf.org/html/rfc7807#section-3.1.
|
// as described in https://tools.ietf.org/html/rfc7807#section-3.1.
|
||||||
type wireError struct {
|
type wireError struct {
|
||||||
Status int
|
Status int
|
||||||
Type string
|
Type string
|
||||||
Detail string
|
Detail string
|
||||||
|
Instance string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *wireError) error(h http.Header) *Error {
|
func (e *wireError) error(h http.Header) *Error {
|
||||||
@ -292,6 +510,7 @@ func (e *wireError) error(h http.Header) *Error {
|
|||||||
StatusCode: e.Status,
|
StatusCode: e.Status,
|
||||||
ProblemType: e.Type,
|
ProblemType: e.Type,
|
||||||
Detail: e.Detail,
|
Detail: e.Detail,
|
||||||
|
Instance: e.Instance,
|
||||||
Header: h,
|
Header: h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
17
vendor/golang.org/x/crypto/chacha20/chacha_arm64.go
generated
vendored
Normal file
17
vendor/golang.org/x/crypto/chacha20/chacha_arm64.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.11
|
||||||
|
// +build !gccgo,!appengine
|
||||||
|
|
||||||
|
package chacha20
|
||||||
|
|
||||||
|
const bufSize = 256
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
|
||||||
|
|
||||||
|
func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) {
|
||||||
|
xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter)
|
||||||
|
}
|
364
vendor/golang.org/x/crypto/chacha20/chacha_generic.go
generated
vendored
Normal file
364
vendor/golang.org/x/crypto/chacha20/chacha_generic.go
generated
vendored
Normal file
@ -0,0 +1,364 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package chacha20 implements the ChaCha20 and XChaCha20 encryption algorithms
|
||||||
|
// as specified in RFC 8439 and draft-irtf-cfrg-xchacha-01.
|
||||||
|
package chacha20
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/cipher"
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
"math/bits"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/internal/subtle"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// KeySize is the size of the key used by this cipher, in bytes.
|
||||||
|
KeySize = 32
|
||||||
|
|
||||||
|
// NonceSize is the size of the nonce used with the standard variant of this
|
||||||
|
// cipher, in bytes.
|
||||||
|
//
|
||||||
|
// Note that this is too short to be safely generated at random if the same
|
||||||
|
// key is reused more than 2³² times.
|
||||||
|
NonceSize = 12
|
||||||
|
|
||||||
|
// NonceSizeX is the size of the nonce used with the XChaCha20 variant of
|
||||||
|
// this cipher, in bytes.
|
||||||
|
NonceSizeX = 24
|
||||||
|
)
|
||||||
|
|
||||||
|
// Cipher is a stateful instance of ChaCha20 or XChaCha20 using a particular key
|
||||||
|
// and nonce. A *Cipher implements the cipher.Stream interface.
|
||||||
|
type Cipher struct {
|
||||||
|
// The ChaCha20 state is 16 words: 4 constant, 8 of key, 1 of counter
|
||||||
|
// (incremented after each block), and 3 of nonce.
|
||||||
|
key [8]uint32
|
||||||
|
counter uint32
|
||||||
|
nonce [3]uint32
|
||||||
|
|
||||||
|
// The last len bytes of buf are leftover key stream bytes from the previous
|
||||||
|
// XORKeyStream invocation. The size of buf depends on how many blocks are
|
||||||
|
// computed at a time.
|
||||||
|
buf [bufSize]byte
|
||||||
|
len int
|
||||||
|
|
||||||
|
// The counter-independent results of the first round are cached after they
|
||||||
|
// are computed the first time.
|
||||||
|
precompDone bool
|
||||||
|
p1, p5, p9, p13 uint32
|
||||||
|
p2, p6, p10, p14 uint32
|
||||||
|
p3, p7, p11, p15 uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ cipher.Stream = (*Cipher)(nil)
|
||||||
|
|
||||||
|
// NewUnauthenticatedCipher creates a new ChaCha20 stream cipher with the given
|
||||||
|
// 32 bytes key and a 12 or 24 bytes nonce. If a nonce of 24 bytes is provided,
|
||||||
|
// the XChaCha20 construction will be used. It returns an error if key or nonce
|
||||||
|
// have any other length.
|
||||||
|
//
|
||||||
|
// Note that ChaCha20, like all stream ciphers, is not authenticated and allows
|
||||||
|
// attackers to silently tamper with the plaintext. For this reason, it is more
|
||||||
|
// appropriate as a building block than as a standalone encryption mechanism.
|
||||||
|
// Instead, consider using package golang.org/x/crypto/chacha20poly1305.
|
||||||
|
func NewUnauthenticatedCipher(key, nonce []byte) (*Cipher, error) {
|
||||||
|
// This function is split into a wrapper so that the Cipher allocation will
|
||||||
|
// be inlined, and depending on how the caller uses the return value, won't
|
||||||
|
// escape to the heap.
|
||||||
|
c := &Cipher{}
|
||||||
|
return newUnauthenticatedCipher(c, key, nonce)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newUnauthenticatedCipher(c *Cipher, key, nonce []byte) (*Cipher, error) {
|
||||||
|
if len(key) != KeySize {
|
||||||
|
return nil, errors.New("chacha20: wrong key size")
|
||||||
|
}
|
||||||
|
if len(nonce) == NonceSizeX {
|
||||||
|
// XChaCha20 uses the ChaCha20 core to mix 16 bytes of the nonce into a
|
||||||
|
// derived key, allowing it to operate on a nonce of 24 bytes. See
|
||||||
|
// draft-irtf-cfrg-xchacha-01, Section 2.3.
|
||||||
|
key, _ = HChaCha20(key, nonce[0:16])
|
||||||
|
cNonce := make([]byte, NonceSize)
|
||||||
|
copy(cNonce[4:12], nonce[16:24])
|
||||||
|
nonce = cNonce
|
||||||
|
} else if len(nonce) != NonceSize {
|
||||||
|
return nil, errors.New("chacha20: wrong nonce size")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.key = [8]uint32{
|
||||||
|
binary.LittleEndian.Uint32(key[0:4]),
|
||||||
|
binary.LittleEndian.Uint32(key[4:8]),
|
||||||
|
binary.LittleEndian.Uint32(key[8:12]),
|
||||||
|
binary.LittleEndian.Uint32(key[12:16]),
|
||||||
|
binary.LittleEndian.Uint32(key[16:20]),
|
||||||
|
binary.LittleEndian.Uint32(key[20:24]),
|
||||||
|
binary.LittleEndian.Uint32(key[24:28]),
|
||||||
|
binary.LittleEndian.Uint32(key[28:32]),
|
||||||
|
}
|
||||||
|
c.nonce = [3]uint32{
|
||||||
|
binary.LittleEndian.Uint32(nonce[0:4]),
|
||||||
|
binary.LittleEndian.Uint32(nonce[4:8]),
|
||||||
|
binary.LittleEndian.Uint32(nonce[8:12]),
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// The constant first 4 words of the ChaCha20 state.
|
||||||
|
const (
|
||||||
|
j0 uint32 = 0x61707865 // expa
|
||||||
|
j1 uint32 = 0x3320646e // nd 3
|
||||||
|
j2 uint32 = 0x79622d32 // 2-by
|
||||||
|
j3 uint32 = 0x6b206574 // te k
|
||||||
|
)
|
||||||
|
|
||||||
|
const blockSize = 64
|
||||||
|
|
||||||
|
// quarterRound is the core of ChaCha20. It shuffles the bits of 4 state words.
|
||||||
|
// It's executed 4 times for each of the 20 ChaCha20 rounds, operating on all 16
|
||||||
|
// words each round, in columnar or diagonal groups of 4 at a time.
|
||||||
|
func quarterRound(a, b, c, d uint32) (uint32, uint32, uint32, uint32) {
|
||||||
|
a += b
|
||||||
|
d ^= a
|
||||||
|
d = bits.RotateLeft32(d, 16)
|
||||||
|
c += d
|
||||||
|
b ^= c
|
||||||
|
b = bits.RotateLeft32(b, 12)
|
||||||
|
a += b
|
||||||
|
d ^= a
|
||||||
|
d = bits.RotateLeft32(d, 8)
|
||||||
|
c += d
|
||||||
|
b ^= c
|
||||||
|
b = bits.RotateLeft32(b, 7)
|
||||||
|
return a, b, c, d
|
||||||
|
}
|
||||||
|
|
||||||
|
// XORKeyStream XORs each byte in the given slice with a byte from the
|
||||||
|
// cipher's key stream. Dst and src must overlap entirely or not at all.
|
||||||
|
//
|
||||||
|
// If len(dst) < len(src), XORKeyStream will panic. It is acceptable
|
||||||
|
// to pass a dst bigger than src, and in that case, XORKeyStream will
|
||||||
|
// only update dst[:len(src)] and will not touch the rest of dst.
|
||||||
|
//
|
||||||
|
// Multiple calls to XORKeyStream behave as if the concatenation of
|
||||||
|
// the src buffers was passed in a single run. That is, Cipher
|
||||||
|
// maintains state and does not reset at each XORKeyStream call.
|
||||||
|
func (s *Cipher) XORKeyStream(dst, src []byte) {
|
||||||
|
if len(src) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(dst) < len(src) {
|
||||||
|
panic("chacha20: output smaller than input")
|
||||||
|
}
|
||||||
|
dst = dst[:len(src)]
|
||||||
|
if subtle.InexactOverlap(dst, src) {
|
||||||
|
panic("chacha20: invalid buffer overlap")
|
||||||
|
}
|
||||||
|
|
||||||
|
// First, drain any remaining key stream from a previous XORKeyStream.
|
||||||
|
if s.len != 0 {
|
||||||
|
keyStream := s.buf[bufSize-s.len:]
|
||||||
|
if len(src) < len(keyStream) {
|
||||||
|
keyStream = keyStream[:len(src)]
|
||||||
|
}
|
||||||
|
_ = src[len(keyStream)-1] // bounds check elimination hint
|
||||||
|
for i, b := range keyStream {
|
||||||
|
dst[i] = src[i] ^ b
|
||||||
|
}
|
||||||
|
s.len -= len(keyStream)
|
||||||
|
src = src[len(keyStream):]
|
||||||
|
dst = dst[len(keyStream):]
|
||||||
|
}
|
||||||
|
|
||||||
|
const blocksPerBuf = bufSize / blockSize
|
||||||
|
numBufs := (uint64(len(src)) + bufSize - 1) / bufSize
|
||||||
|
if uint64(s.counter)+numBufs*blocksPerBuf >= 1<<32 {
|
||||||
|
panic("chacha20: counter overflow")
|
||||||
|
}
|
||||||
|
|
||||||
|
// xorKeyStreamBlocks implementations expect input lengths that are a
|
||||||
|
// multiple of bufSize. Platform-specific ones process multiple blocks at a
|
||||||
|
// time, so have bufSizes that are a multiple of blockSize.
|
||||||
|
|
||||||
|
rem := len(src) % bufSize
|
||||||
|
full := len(src) - rem
|
||||||
|
|
||||||
|
if full > 0 {
|
||||||
|
s.xorKeyStreamBlocks(dst[:full], src[:full])
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have a partial (multi-)block, pad it for xorKeyStreamBlocks, and
|
||||||
|
// keep the leftover keystream for the next XORKeyStream invocation.
|
||||||
|
if rem > 0 {
|
||||||
|
s.buf = [bufSize]byte{}
|
||||||
|
copy(s.buf[:], src[full:])
|
||||||
|
s.xorKeyStreamBlocks(s.buf[:], s.buf[:])
|
||||||
|
s.len = bufSize - copy(dst[full:], s.buf[:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Cipher) xorKeyStreamBlocksGeneric(dst, src []byte) {
|
||||||
|
if len(dst) != len(src) || len(dst)%blockSize != 0 {
|
||||||
|
panic("chacha20: internal error: wrong dst and/or src length")
|
||||||
|
}
|
||||||
|
|
||||||
|
// To generate each block of key stream, the initial cipher state
|
||||||
|
// (represented below) is passed through 20 rounds of shuffling,
|
||||||
|
// alternatively applying quarterRounds by columns (like 1, 5, 9, 13)
|
||||||
|
// or by diagonals (like 1, 6, 11, 12).
|
||||||
|
//
|
||||||
|
// 0:cccccccc 1:cccccccc 2:cccccccc 3:cccccccc
|
||||||
|
// 4:kkkkkkkk 5:kkkkkkkk 6:kkkkkkkk 7:kkkkkkkk
|
||||||
|
// 8:kkkkkkkk 9:kkkkkkkk 10:kkkkkkkk 11:kkkkkkkk
|
||||||
|
// 12:bbbbbbbb 13:nnnnnnnn 14:nnnnnnnn 15:nnnnnnnn
|
||||||
|
//
|
||||||
|
// c=constant k=key b=blockcount n=nonce
|
||||||
|
var (
|
||||||
|
c0, c1, c2, c3 = j0, j1, j2, j3
|
||||||
|
c4, c5, c6, c7 = s.key[0], s.key[1], s.key[2], s.key[3]
|
||||||
|
c8, c9, c10, c11 = s.key[4], s.key[5], s.key[6], s.key[7]
|
||||||
|
_, c13, c14, c15 = s.counter, s.nonce[0], s.nonce[1], s.nonce[2]
|
||||||
|
)
|
||||||
|
|
||||||
|
// Three quarters of the first round don't depend on the counter, so we can
|
||||||
|
// calculate them here, and reuse them for multiple blocks in the loop, and
|
||||||
|
// for future XORKeyStream invocations.
|
||||||
|
if !s.precompDone {
|
||||||
|
s.p1, s.p5, s.p9, s.p13 = quarterRound(c1, c5, c9, c13)
|
||||||
|
s.p2, s.p6, s.p10, s.p14 = quarterRound(c2, c6, c10, c14)
|
||||||
|
s.p3, s.p7, s.p11, s.p15 = quarterRound(c3, c7, c11, c15)
|
||||||
|
s.precompDone = true
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(src); i += blockSize {
|
||||||
|
// The remainder of the first column round.
|
||||||
|
fcr0, fcr4, fcr8, fcr12 := quarterRound(c0, c4, c8, s.counter)
|
||||||
|
|
||||||
|
// The second diagonal round.
|
||||||
|
x0, x5, x10, x15 := quarterRound(fcr0, s.p5, s.p10, s.p15)
|
||||||
|
x1, x6, x11, x12 := quarterRound(s.p1, s.p6, s.p11, fcr12)
|
||||||
|
x2, x7, x8, x13 := quarterRound(s.p2, s.p7, fcr8, s.p13)
|
||||||
|
x3, x4, x9, x14 := quarterRound(s.p3, fcr4, s.p9, s.p14)
|
||||||
|
|
||||||
|
// The remaining 18 rounds.
|
||||||
|
for i := 0; i < 9; i++ {
|
||||||
|
// Column round.
|
||||||
|
x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12)
|
||||||
|
x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13)
|
||||||
|
x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14)
|
||||||
|
x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15)
|
||||||
|
|
||||||
|
// Diagonal round.
|
||||||
|
x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15)
|
||||||
|
x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12)
|
||||||
|
x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13)
|
||||||
|
x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, add back the initial state to generate the key stream.
|
||||||
|
x0 += c0
|
||||||
|
x1 += c1
|
||||||
|
x2 += c2
|
||||||
|
x3 += c3
|
||||||
|
x4 += c4
|
||||||
|
x5 += c5
|
||||||
|
x6 += c6
|
||||||
|
x7 += c7
|
||||||
|
x8 += c8
|
||||||
|
x9 += c9
|
||||||
|
x10 += c10
|
||||||
|
x11 += c11
|
||||||
|
x12 += s.counter
|
||||||
|
x13 += c13
|
||||||
|
x14 += c14
|
||||||
|
x15 += c15
|
||||||
|
|
||||||
|
s.counter += 1
|
||||||
|
if s.counter == 0 {
|
||||||
|
panic("chacha20: internal error: counter overflow")
|
||||||
|
}
|
||||||
|
|
||||||
|
in, out := src[i:], dst[i:]
|
||||||
|
in, out = in[:blockSize], out[:blockSize] // bounds check elimination hint
|
||||||
|
|
||||||
|
// XOR the key stream with the source and write out the result.
|
||||||
|
xor(out[0:], in[0:], x0)
|
||||||
|
xor(out[4:], in[4:], x1)
|
||||||
|
xor(out[8:], in[8:], x2)
|
||||||
|
xor(out[12:], in[12:], x3)
|
||||||
|
xor(out[16:], in[16:], x4)
|
||||||
|
xor(out[20:], in[20:], x5)
|
||||||
|
xor(out[24:], in[24:], x6)
|
||||||
|
xor(out[28:], in[28:], x7)
|
||||||
|
xor(out[32:], in[32:], x8)
|
||||||
|
xor(out[36:], in[36:], x9)
|
||||||
|
xor(out[40:], in[40:], x10)
|
||||||
|
xor(out[44:], in[44:], x11)
|
||||||
|
xor(out[48:], in[48:], x12)
|
||||||
|
xor(out[52:], in[52:], x13)
|
||||||
|
xor(out[56:], in[56:], x14)
|
||||||
|
xor(out[60:], in[60:], x15)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HChaCha20 uses the ChaCha20 core to generate a derived key from a 32 bytes
|
||||||
|
// key and a 16 bytes nonce. It returns an error if key or nonce have any other
|
||||||
|
// length. It is used as part of the XChaCha20 construction.
|
||||||
|
func HChaCha20(key, nonce []byte) ([]byte, error) {
|
||||||
|
// This function is split into a wrapper so that the slice allocation will
|
||||||
|
// be inlined, and depending on how the caller uses the return value, won't
|
||||||
|
// escape to the heap.
|
||||||
|
out := make([]byte, 32)
|
||||||
|
return hChaCha20(out, key, nonce)
|
||||||
|
}
|
||||||
|
|
||||||
|
func hChaCha20(out, key, nonce []byte) ([]byte, error) {
|
||||||
|
if len(key) != KeySize {
|
||||||
|
return nil, errors.New("chacha20: wrong HChaCha20 key size")
|
||||||
|
}
|
||||||
|
if len(nonce) != 16 {
|
||||||
|
return nil, errors.New("chacha20: wrong HChaCha20 nonce size")
|
||||||
|
}
|
||||||
|
|
||||||
|
x0, x1, x2, x3 := j0, j1, j2, j3
|
||||||
|
x4 := binary.LittleEndian.Uint32(key[0:4])
|
||||||
|
x5 := binary.LittleEndian.Uint32(key[4:8])
|
||||||
|
x6 := binary.LittleEndian.Uint32(key[8:12])
|
||||||
|
x7 := binary.LittleEndian.Uint32(key[12:16])
|
||||||
|
x8 := binary.LittleEndian.Uint32(key[16:20])
|
||||||
|
x9 := binary.LittleEndian.Uint32(key[20:24])
|
||||||
|
x10 := binary.LittleEndian.Uint32(key[24:28])
|
||||||
|
x11 := binary.LittleEndian.Uint32(key[28:32])
|
||||||
|
x12 := binary.LittleEndian.Uint32(nonce[0:4])
|
||||||
|
x13 := binary.LittleEndian.Uint32(nonce[4:8])
|
||||||
|
x14 := binary.LittleEndian.Uint32(nonce[8:12])
|
||||||
|
x15 := binary.LittleEndian.Uint32(nonce[12:16])
|
||||||
|
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
// Diagonal round.
|
||||||
|
x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12)
|
||||||
|
x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13)
|
||||||
|
x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14)
|
||||||
|
x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15)
|
||||||
|
|
||||||
|
// Column round.
|
||||||
|
x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15)
|
||||||
|
x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12)
|
||||||
|
x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13)
|
||||||
|
x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14)
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = out[31] // bounds check elimination hint
|
||||||
|
binary.LittleEndian.PutUint32(out[0:4], x0)
|
||||||
|
binary.LittleEndian.PutUint32(out[4:8], x1)
|
||||||
|
binary.LittleEndian.PutUint32(out[8:12], x2)
|
||||||
|
binary.LittleEndian.PutUint32(out[12:16], x3)
|
||||||
|
binary.LittleEndian.PutUint32(out[16:20], x12)
|
||||||
|
binary.LittleEndian.PutUint32(out[20:24], x13)
|
||||||
|
binary.LittleEndian.PutUint32(out[24:28], x14)
|
||||||
|
binary.LittleEndian.PutUint32(out[28:32], x15)
|
||||||
|
return out, nil
|
||||||
|
}
|
13
vendor/golang.org/x/crypto/chacha20/chacha_noasm.go
generated
vendored
Normal file
13
vendor/golang.org/x/crypto/chacha20/chacha_noasm.go
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !arm64,!s390x,!ppc64le arm64,!go1.11 gccgo appengine
|
||||||
|
|
||||||
|
package chacha20
|
||||||
|
|
||||||
|
const bufSize = blockSize
|
||||||
|
|
||||||
|
func (s *Cipher) xorKeyStreamBlocks(dst, src []byte) {
|
||||||
|
s.xorKeyStreamBlocksGeneric(dst, src)
|
||||||
|
}
|
16
vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go
generated
vendored
Normal file
16
vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !gccgo,!appengine
|
||||||
|
|
||||||
|
package chacha20
|
||||||
|
|
||||||
|
const bufSize = 256
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32)
|
||||||
|
|
||||||
|
func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) {
|
||||||
|
chaCha20_ctr32_vsx(&dst[0], &src[0], len(src), &c.key, &c.counter)
|
||||||
|
}
|
449
vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s
generated
vendored
Normal file
449
vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s
generated
vendored
Normal file
@ -0,0 +1,449 @@
|
|||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Based on CRYPTOGAMS code with the following comment:
|
||||||
|
// # ====================================================================
|
||||||
|
// # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
|
||||||
|
// # project. The module is, however, dual licensed under OpenSSL and
|
||||||
|
// # CRYPTOGAMS licenses depending on where you obtain it. For further
|
||||||
|
// # details see http://www.openssl.org/~appro/cryptogams/.
|
||||||
|
// # ====================================================================
|
||||||
|
|
||||||
|
// Code for the perl script that generates the ppc64 assembler
|
||||||
|
// can be found in the cryptogams repository at the link below. It is based on
|
||||||
|
// the original from openssl.
|
||||||
|
|
||||||
|
// https://github.com/dot-asm/cryptogams/commit/a60f5b50ed908e91
|
||||||
|
|
||||||
|
// The differences in this and the original implementation are
|
||||||
|
// due to the calling conventions and initialization of constants.
|
||||||
|
|
||||||
|
// +build !gccgo,!appengine
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
#define OUT R3
|
||||||
|
#define INP R4
|
||||||
|
#define LEN R5
|
||||||
|
#define KEY R6
|
||||||
|
#define CNT R7
|
||||||
|
#define TMP R15
|
||||||
|
|
||||||
|
#define CONSTBASE R16
|
||||||
|
#define BLOCKS R17
|
||||||
|
|
||||||
|
DATA consts<>+0x00(SB)/8, $0x3320646e61707865
|
||||||
|
DATA consts<>+0x08(SB)/8, $0x6b20657479622d32
|
||||||
|
DATA consts<>+0x10(SB)/8, $0x0000000000000001
|
||||||
|
DATA consts<>+0x18(SB)/8, $0x0000000000000000
|
||||||
|
DATA consts<>+0x20(SB)/8, $0x0000000000000004
|
||||||
|
DATA consts<>+0x28(SB)/8, $0x0000000000000000
|
||||||
|
DATA consts<>+0x30(SB)/8, $0x0a0b08090e0f0c0d
|
||||||
|
DATA consts<>+0x38(SB)/8, $0x0203000106070405
|
||||||
|
DATA consts<>+0x40(SB)/8, $0x090a0b080d0e0f0c
|
||||||
|
DATA consts<>+0x48(SB)/8, $0x0102030005060704
|
||||||
|
DATA consts<>+0x50(SB)/8, $0x6170786561707865
|
||||||
|
DATA consts<>+0x58(SB)/8, $0x6170786561707865
|
||||||
|
DATA consts<>+0x60(SB)/8, $0x3320646e3320646e
|
||||||
|
DATA consts<>+0x68(SB)/8, $0x3320646e3320646e
|
||||||
|
DATA consts<>+0x70(SB)/8, $0x79622d3279622d32
|
||||||
|
DATA consts<>+0x78(SB)/8, $0x79622d3279622d32
|
||||||
|
DATA consts<>+0x80(SB)/8, $0x6b2065746b206574
|
||||||
|
DATA consts<>+0x88(SB)/8, $0x6b2065746b206574
|
||||||
|
DATA consts<>+0x90(SB)/8, $0x0000000100000000
|
||||||
|
DATA consts<>+0x98(SB)/8, $0x0000000300000002
|
||||||
|
GLOBL consts<>(SB), RODATA, $0xa0
|
||||||
|
|
||||||
|
//func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32)
|
||||||
|
TEXT ·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40
|
||||||
|
MOVD out+0(FP), OUT
|
||||||
|
MOVD inp+8(FP), INP
|
||||||
|
MOVD len+16(FP), LEN
|
||||||
|
MOVD key+24(FP), KEY
|
||||||
|
MOVD counter+32(FP), CNT
|
||||||
|
|
||||||
|
// Addressing for constants
|
||||||
|
MOVD $consts<>+0x00(SB), CONSTBASE
|
||||||
|
MOVD $16, R8
|
||||||
|
MOVD $32, R9
|
||||||
|
MOVD $48, R10
|
||||||
|
MOVD $64, R11
|
||||||
|
SRD $6, LEN, BLOCKS
|
||||||
|
// V16
|
||||||
|
LXVW4X (CONSTBASE)(R0), VS48
|
||||||
|
ADD $80,CONSTBASE
|
||||||
|
|
||||||
|
// Load key into V17,V18
|
||||||
|
LXVW4X (KEY)(R0), VS49
|
||||||
|
LXVW4X (KEY)(R8), VS50
|
||||||
|
|
||||||
|
// Load CNT, NONCE into V19
|
||||||
|
LXVW4X (CNT)(R0), VS51
|
||||||
|
|
||||||
|
// Clear V27
|
||||||
|
VXOR V27, V27, V27
|
||||||
|
|
||||||
|
// V28
|
||||||
|
LXVW4X (CONSTBASE)(R11), VS60
|
||||||
|
|
||||||
|
// splat slot from V19 -> V26
|
||||||
|
VSPLTW $0, V19, V26
|
||||||
|
|
||||||
|
VSLDOI $4, V19, V27, V19
|
||||||
|
VSLDOI $12, V27, V19, V19
|
||||||
|
|
||||||
|
VADDUWM V26, V28, V26
|
||||||
|
|
||||||
|
MOVD $10, R14
|
||||||
|
MOVD R14, CTR
|
||||||
|
|
||||||
|
loop_outer_vsx:
|
||||||
|
// V0, V1, V2, V3
|
||||||
|
LXVW4X (R0)(CONSTBASE), VS32
|
||||||
|
LXVW4X (R8)(CONSTBASE), VS33
|
||||||
|
LXVW4X (R9)(CONSTBASE), VS34
|
||||||
|
LXVW4X (R10)(CONSTBASE), VS35
|
||||||
|
|
||||||
|
// splat values from V17, V18 into V4-V11
|
||||||
|
VSPLTW $0, V17, V4
|
||||||
|
VSPLTW $1, V17, V5
|
||||||
|
VSPLTW $2, V17, V6
|
||||||
|
VSPLTW $3, V17, V7
|
||||||
|
VSPLTW $0, V18, V8
|
||||||
|
VSPLTW $1, V18, V9
|
||||||
|
VSPLTW $2, V18, V10
|
||||||
|
VSPLTW $3, V18, V11
|
||||||
|
|
||||||
|
// VOR
|
||||||
|
VOR V26, V26, V12
|
||||||
|
|
||||||
|
// splat values from V19 -> V13, V14, V15
|
||||||
|
VSPLTW $1, V19, V13
|
||||||
|
VSPLTW $2, V19, V14
|
||||||
|
VSPLTW $3, V19, V15
|
||||||
|
|
||||||
|
// splat const values
|
||||||
|
VSPLTISW $-16, V27
|
||||||
|
VSPLTISW $12, V28
|
||||||
|
VSPLTISW $8, V29
|
||||||
|
VSPLTISW $7, V30
|
||||||
|
|
||||||
|
loop_vsx:
|
||||||
|
VADDUWM V0, V4, V0
|
||||||
|
VADDUWM V1, V5, V1
|
||||||
|
VADDUWM V2, V6, V2
|
||||||
|
VADDUWM V3, V7, V3
|
||||||
|
|
||||||
|
VXOR V12, V0, V12
|
||||||
|
VXOR V13, V1, V13
|
||||||
|
VXOR V14, V2, V14
|
||||||
|
VXOR V15, V3, V15
|
||||||
|
|
||||||
|
VRLW V12, V27, V12
|
||||||
|
VRLW V13, V27, V13
|
||||||
|
VRLW V14, V27, V14
|
||||||
|
VRLW V15, V27, V15
|
||||||
|
|
||||||
|
VADDUWM V8, V12, V8
|
||||||
|
VADDUWM V9, V13, V9
|
||||||
|
VADDUWM V10, V14, V10
|
||||||
|
VADDUWM V11, V15, V11
|
||||||
|
|
||||||
|
VXOR V4, V8, V4
|
||||||
|
VXOR V5, V9, V5
|
||||||
|
VXOR V6, V10, V6
|
||||||
|
VXOR V7, V11, V7
|
||||||
|
|
||||||
|
VRLW V4, V28, V4
|
||||||
|
VRLW V5, V28, V5
|
||||||
|
VRLW V6, V28, V6
|
||||||
|
VRLW V7, V28, V7
|
||||||
|
|
||||||
|
VADDUWM V0, V4, V0
|
||||||
|
VADDUWM V1, V5, V1
|
||||||
|
VADDUWM V2, V6, V2
|
||||||
|
VADDUWM V3, V7, V3
|
||||||
|
|
||||||
|
VXOR V12, V0, V12
|
||||||
|
VXOR V13, V1, V13
|
||||||
|
VXOR V14, V2, V14
|
||||||
|
VXOR V15, V3, V15
|
||||||
|
|
||||||
|
VRLW V12, V29, V12
|
||||||
|
VRLW V13, V29, V13
|
||||||
|
VRLW V14, V29, V14
|
||||||
|
VRLW V15, V29, V15
|
||||||
|
|
||||||
|
VADDUWM V8, V12, V8
|
||||||
|
VADDUWM V9, V13, V9
|
||||||
|
VADDUWM V10, V14, V10
|
||||||
|
VADDUWM V11, V15, V11
|
||||||
|
|
||||||
|
VXOR V4, V8, V4
|
||||||
|
VXOR V5, V9, V5
|
||||||
|
VXOR V6, V10, V6
|
||||||
|
VXOR V7, V11, V7
|
||||||
|
|
||||||
|
VRLW V4, V30, V4
|
||||||
|
VRLW V5, V30, V5
|
||||||
|
VRLW V6, V30, V6
|
||||||
|
VRLW V7, V30, V7
|
||||||
|
|
||||||
|
VADDUWM V0, V5, V0
|
||||||
|
VADDUWM V1, V6, V1
|
||||||
|
VADDUWM V2, V7, V2
|
||||||
|
VADDUWM V3, V4, V3
|
||||||
|
|
||||||
|
VXOR V15, V0, V15
|
||||||
|
VXOR V12, V1, V12
|
||||||
|
VXOR V13, V2, V13
|
||||||
|
VXOR V14, V3, V14
|
||||||
|
|
||||||
|
VRLW V15, V27, V15
|
||||||
|
VRLW V12, V27, V12
|
||||||
|
VRLW V13, V27, V13
|
||||||
|
VRLW V14, V27, V14
|
||||||
|
|
||||||
|
VADDUWM V10, V15, V10
|
||||||
|
VADDUWM V11, V12, V11
|
||||||
|
VADDUWM V8, V13, V8
|
||||||
|
VADDUWM V9, V14, V9
|
||||||
|
|
||||||
|
VXOR V5, V10, V5
|
||||||
|
VXOR V6, V11, V6
|
||||||
|
VXOR V7, V8, V7
|
||||||
|
VXOR V4, V9, V4
|
||||||
|
|
||||||
|
VRLW V5, V28, V5
|
||||||
|
VRLW V6, V28, V6
|
||||||
|
VRLW V7, V28, V7
|
||||||
|
VRLW V4, V28, V4
|
||||||
|
|
||||||
|
VADDUWM V0, V5, V0
|
||||||
|
VADDUWM V1, V6, V1
|
||||||
|
VADDUWM V2, V7, V2
|
||||||
|
VADDUWM V3, V4, V3
|
||||||
|
|
||||||
|
VXOR V15, V0, V15
|
||||||
|
VXOR V12, V1, V12
|
||||||
|
VXOR V13, V2, V13
|
||||||
|
VXOR V14, V3, V14
|
||||||
|
|
||||||
|
VRLW V15, V29, V15
|
||||||
|
VRLW V12, V29, V12
|
||||||
|
VRLW V13, V29, V13
|
||||||
|
VRLW V14, V29, V14
|
||||||
|
|
||||||
|
VADDUWM V10, V15, V10
|
||||||
|
VADDUWM V11, V12, V11
|
||||||
|
VADDUWM V8, V13, V8
|
||||||
|
VADDUWM V9, V14, V9
|
||||||
|
|
||||||
|
VXOR V5, V10, V5
|
||||||
|
VXOR V6, V11, V6
|
||||||
|
VXOR V7, V8, V7
|
||||||
|
VXOR V4, V9, V4
|
||||||
|
|
||||||
|
VRLW V5, V30, V5
|
||||||
|
VRLW V6, V30, V6
|
||||||
|
VRLW V7, V30, V7
|
||||||
|
VRLW V4, V30, V4
|
||||||
|
BC 16, LT, loop_vsx
|
||||||
|
|
||||||
|
VADDUWM V12, V26, V12
|
||||||
|
|
||||||
|
WORD $0x13600F8C // VMRGEW V0, V1, V27
|
||||||
|
WORD $0x13821F8C // VMRGEW V2, V3, V28
|
||||||
|
|
||||||
|
WORD $0x10000E8C // VMRGOW V0, V1, V0
|
||||||
|
WORD $0x10421E8C // VMRGOW V2, V3, V2
|
||||||
|
|
||||||
|
WORD $0x13A42F8C // VMRGEW V4, V5, V29
|
||||||
|
WORD $0x13C63F8C // VMRGEW V6, V7, V30
|
||||||
|
|
||||||
|
XXPERMDI VS32, VS34, $0, VS33
|
||||||
|
XXPERMDI VS32, VS34, $3, VS35
|
||||||
|
XXPERMDI VS59, VS60, $0, VS32
|
||||||
|
XXPERMDI VS59, VS60, $3, VS34
|
||||||
|
|
||||||
|
WORD $0x10842E8C // VMRGOW V4, V5, V4
|
||||||
|
WORD $0x10C63E8C // VMRGOW V6, V7, V6
|
||||||
|
|
||||||
|
WORD $0x13684F8C // VMRGEW V8, V9, V27
|
||||||
|
WORD $0x138A5F8C // VMRGEW V10, V11, V28
|
||||||
|
|
||||||
|
XXPERMDI VS36, VS38, $0, VS37
|
||||||
|
XXPERMDI VS36, VS38, $3, VS39
|
||||||
|
XXPERMDI VS61, VS62, $0, VS36
|
||||||
|
XXPERMDI VS61, VS62, $3, VS38
|
||||||
|
|
||||||
|
WORD $0x11084E8C // VMRGOW V8, V9, V8
|
||||||
|
WORD $0x114A5E8C // VMRGOW V10, V11, V10
|
||||||
|
|
||||||
|
WORD $0x13AC6F8C // VMRGEW V12, V13, V29
|
||||||
|
WORD $0x13CE7F8C // VMRGEW V14, V15, V30
|
||||||
|
|
||||||
|
XXPERMDI VS40, VS42, $0, VS41
|
||||||
|
XXPERMDI VS40, VS42, $3, VS43
|
||||||
|
XXPERMDI VS59, VS60, $0, VS40
|
||||||
|
XXPERMDI VS59, VS60, $3, VS42
|
||||||
|
|
||||||
|
WORD $0x118C6E8C // VMRGOW V12, V13, V12
|
||||||
|
WORD $0x11CE7E8C // VMRGOW V14, V15, V14
|
||||||
|
|
||||||
|
VSPLTISW $4, V27
|
||||||
|
VADDUWM V26, V27, V26
|
||||||
|
|
||||||
|
XXPERMDI VS44, VS46, $0, VS45
|
||||||
|
XXPERMDI VS44, VS46, $3, VS47
|
||||||
|
XXPERMDI VS61, VS62, $0, VS44
|
||||||
|
XXPERMDI VS61, VS62, $3, VS46
|
||||||
|
|
||||||
|
VADDUWM V0, V16, V0
|
||||||
|
VADDUWM V4, V17, V4
|
||||||
|
VADDUWM V8, V18, V8
|
||||||
|
VADDUWM V12, V19, V12
|
||||||
|
|
||||||
|
CMPU LEN, $64
|
||||||
|
BLT tail_vsx
|
||||||
|
|
||||||
|
// Bottom of loop
|
||||||
|
LXVW4X (INP)(R0), VS59
|
||||||
|
LXVW4X (INP)(R8), VS60
|
||||||
|
LXVW4X (INP)(R9), VS61
|
||||||
|
LXVW4X (INP)(R10), VS62
|
||||||
|
|
||||||
|
VXOR V27, V0, V27
|
||||||
|
VXOR V28, V4, V28
|
||||||
|
VXOR V29, V8, V29
|
||||||
|
VXOR V30, V12, V30
|
||||||
|
|
||||||
|
STXVW4X VS59, (OUT)(R0)
|
||||||
|
STXVW4X VS60, (OUT)(R8)
|
||||||
|
ADD $64, INP
|
||||||
|
STXVW4X VS61, (OUT)(R9)
|
||||||
|
ADD $-64, LEN
|
||||||
|
STXVW4X VS62, (OUT)(R10)
|
||||||
|
ADD $64, OUT
|
||||||
|
BEQ done_vsx
|
||||||
|
|
||||||
|
VADDUWM V1, V16, V0
|
||||||
|
VADDUWM V5, V17, V4
|
||||||
|
VADDUWM V9, V18, V8
|
||||||
|
VADDUWM V13, V19, V12
|
||||||
|
|
||||||
|
CMPU LEN, $64
|
||||||
|
BLT tail_vsx
|
||||||
|
|
||||||
|
LXVW4X (INP)(R0), VS59
|
||||||
|
LXVW4X (INP)(R8), VS60
|
||||||
|
LXVW4X (INP)(R9), VS61
|
||||||
|
LXVW4X (INP)(R10), VS62
|
||||||
|
VXOR V27, V0, V27
|
||||||
|
|
||||||
|
VXOR V28, V4, V28
|
||||||
|
VXOR V29, V8, V29
|
||||||
|
VXOR V30, V12, V30
|
||||||
|
|
||||||
|
STXVW4X VS59, (OUT)(R0)
|
||||||
|
STXVW4X VS60, (OUT)(R8)
|
||||||
|
ADD $64, INP
|
||||||
|
STXVW4X VS61, (OUT)(R9)
|
||||||
|
ADD $-64, LEN
|
||||||
|
STXVW4X VS62, (OUT)(V10)
|
||||||
|
ADD $64, OUT
|
||||||
|
BEQ done_vsx
|
||||||
|
|
||||||
|
VADDUWM V2, V16, V0
|
||||||
|
VADDUWM V6, V17, V4
|
||||||
|
VADDUWM V10, V18, V8
|
||||||
|
VADDUWM V14, V19, V12
|
||||||
|
|
||||||
|
CMPU LEN, $64
|
||||||
|
BLT tail_vsx
|
||||||
|
|
||||||
|
LXVW4X (INP)(R0), VS59
|
||||||
|
LXVW4X (INP)(R8), VS60
|
||||||
|
LXVW4X (INP)(R9), VS61
|
||||||
|
LXVW4X (INP)(R10), VS62
|
||||||
|
|
||||||
|
VXOR V27, V0, V27
|
||||||
|
VXOR V28, V4, V28
|
||||||
|
VXOR V29, V8, V29
|
||||||
|
VXOR V30, V12, V30
|
||||||
|
|
||||||
|
STXVW4X VS59, (OUT)(R0)
|
||||||
|
STXVW4X VS60, (OUT)(R8)
|
||||||
|
ADD $64, INP
|
||||||
|
STXVW4X VS61, (OUT)(R9)
|
||||||
|
ADD $-64, LEN
|
||||||
|
STXVW4X VS62, (OUT)(R10)
|
||||||
|
ADD $64, OUT
|
||||||
|
BEQ done_vsx
|
||||||
|
|
||||||
|
VADDUWM V3, V16, V0
|
||||||
|
VADDUWM V7, V17, V4
|
||||||
|
VADDUWM V11, V18, V8
|
||||||
|
VADDUWM V15, V19, V12
|
||||||
|
|
||||||
|
CMPU LEN, $64
|
||||||
|
BLT tail_vsx
|
||||||
|
|
||||||
|
LXVW4X (INP)(R0), VS59
|
||||||
|
LXVW4X (INP)(R8), VS60
|
||||||
|
LXVW4X (INP)(R9), VS61
|
||||||
|
LXVW4X (INP)(R10), VS62
|
||||||
|
|
||||||
|
VXOR V27, V0, V27
|
||||||
|
VXOR V28, V4, V28
|
||||||
|
VXOR V29, V8, V29
|
||||||
|
VXOR V30, V12, V30
|
||||||
|
|
||||||
|
STXVW4X VS59, (OUT)(R0)
|
||||||
|
STXVW4X VS60, (OUT)(R8)
|
||||||
|
ADD $64, INP
|
||||||
|
STXVW4X VS61, (OUT)(R9)
|
||||||
|
ADD $-64, LEN
|
||||||
|
STXVW4X VS62, (OUT)(R10)
|
||||||
|
ADD $64, OUT
|
||||||
|
|
||||||
|
MOVD $10, R14
|
||||||
|
MOVD R14, CTR
|
||||||
|
BNE loop_outer_vsx
|
||||||
|
|
||||||
|
done_vsx:
|
||||||
|
// Increment counter by number of 64 byte blocks
|
||||||
|
MOVD (CNT), R14
|
||||||
|
ADD BLOCKS, R14
|
||||||
|
MOVD R14, (CNT)
|
||||||
|
RET
|
||||||
|
|
||||||
|
tail_vsx:
|
||||||
|
ADD $32, R1, R11
|
||||||
|
MOVD LEN, CTR
|
||||||
|
|
||||||
|
// Save values on stack to copy from
|
||||||
|
STXVW4X VS32, (R11)(R0)
|
||||||
|
STXVW4X VS36, (R11)(R8)
|
||||||
|
STXVW4X VS40, (R11)(R9)
|
||||||
|
STXVW4X VS44, (R11)(R10)
|
||||||
|
ADD $-1, R11, R12
|
||||||
|
ADD $-1, INP
|
||||||
|
ADD $-1, OUT
|
||||||
|
|
||||||
|
looptail_vsx:
|
||||||
|
// Copying the result to OUT
|
||||||
|
// in bytes.
|
||||||
|
MOVBZU 1(R12), KEY
|
||||||
|
MOVBZU 1(INP), TMP
|
||||||
|
XOR KEY, TMP, KEY
|
||||||
|
MOVBU KEY, 1(OUT)
|
||||||
|
BC 16, LT, looptail_vsx
|
||||||
|
|
||||||
|
// Clear the stack values
|
||||||
|
STXVW4X VS48, (R11)(R0)
|
||||||
|
STXVW4X VS48, (R11)(R8)
|
||||||
|
STXVW4X VS48, (R11)(R9)
|
||||||
|
STXVW4X VS48, (R11)(R10)
|
||||||
|
BR done_vsx
|
26
vendor/golang.org/x/crypto/chacha20/chacha_s390x.go
generated
vendored
Normal file
26
vendor/golang.org/x/crypto/chacha20/chacha_s390x.go
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !gccgo,!appengine
|
||||||
|
|
||||||
|
package chacha20
|
||||||
|
|
||||||
|
import "golang.org/x/sys/cpu"
|
||||||
|
|
||||||
|
var haveAsm = cpu.S390X.HasVX
|
||||||
|
|
||||||
|
const bufSize = 256
|
||||||
|
|
||||||
|
// xorKeyStreamVX is an assembly implementation of XORKeyStream. It must only
|
||||||
|
// be called when the vector facility is available. Implementation in asm_s390x.s.
|
||||||
|
//go:noescape
|
||||||
|
func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
|
||||||
|
|
||||||
|
func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) {
|
||||||
|
if cpu.S390X.HasVX {
|
||||||
|
xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter)
|
||||||
|
} else {
|
||||||
|
c.xorKeyStreamBlocksGeneric(dst, src)
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build s390x,!gccgo,!appengine
|
// +build !gccgo,!appengine
|
||||||
|
|
||||||
#include "go_asm.h"
|
#include "go_asm.h"
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
@ -24,15 +24,6 @@ DATA ·constants<>+0x14(SB)/4, $0x3320646e
|
|||||||
DATA ·constants<>+0x18(SB)/4, $0x79622d32
|
DATA ·constants<>+0x18(SB)/4, $0x79622d32
|
||||||
DATA ·constants<>+0x1c(SB)/4, $0x6b206574
|
DATA ·constants<>+0x1c(SB)/4, $0x6b206574
|
||||||
|
|
||||||
// EXRL targets:
|
|
||||||
TEXT ·mvcSrcToBuf(SB), NOFRAME|NOSPLIT, $0
|
|
||||||
MVC $1, (R1), (R8)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·mvcBufToDst(SB), NOFRAME|NOSPLIT, $0
|
|
||||||
MVC $1, (R8), (R9)
|
|
||||||
RET
|
|
||||||
|
|
||||||
#define BSWAP V5
|
#define BSWAP V5
|
||||||
#define J0 V6
|
#define J0 V6
|
||||||
#define KEY0 V7
|
#define KEY0 V7
|
||||||
@ -144,7 +135,7 @@ TEXT ·mvcBufToDst(SB), NOFRAME|NOSPLIT, $0
|
|||||||
VMRHF v, w, c \ // c = {a[2], b[2], c[2], d[2]}
|
VMRHF v, w, c \ // c = {a[2], b[2], c[2], d[2]}
|
||||||
VMRLF v, w, d // d = {a[3], b[3], c[3], d[3]}
|
VMRLF v, w, d // d = {a[3], b[3], c[3], d[3]}
|
||||||
|
|
||||||
// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32, buf *[256]byte, len *int)
|
// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
|
||||||
TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0
|
TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0
|
||||||
MOVD $·constants<>(SB), R1
|
MOVD $·constants<>(SB), R1
|
||||||
MOVD dst+0(FP), R2 // R2=&dst[0]
|
MOVD dst+0(FP), R2 // R2=&dst[0]
|
||||||
@ -152,25 +143,10 @@ TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0
|
|||||||
MOVD key+48(FP), R5 // R5=key
|
MOVD key+48(FP), R5 // R5=key
|
||||||
MOVD nonce+56(FP), R6 // R6=nonce
|
MOVD nonce+56(FP), R6 // R6=nonce
|
||||||
MOVD counter+64(FP), R7 // R7=counter
|
MOVD counter+64(FP), R7 // R7=counter
|
||||||
MOVD buf+72(FP), R8 // R8=buf
|
|
||||||
MOVD len+80(FP), R9 // R9=len
|
|
||||||
|
|
||||||
// load BSWAP and J0
|
// load BSWAP and J0
|
||||||
VLM (R1), BSWAP, J0
|
VLM (R1), BSWAP, J0
|
||||||
|
|
||||||
// set up tail buffer
|
|
||||||
ADD $-1, R4, R12
|
|
||||||
MOVBZ R12, R12
|
|
||||||
CMPUBEQ R12, $255, aligned
|
|
||||||
MOVD R4, R1
|
|
||||||
AND $~255, R1
|
|
||||||
MOVD $(R3)(R1*1), R1
|
|
||||||
EXRL $·mvcSrcToBuf(SB), R12
|
|
||||||
MOVD $255, R0
|
|
||||||
SUB R12, R0
|
|
||||||
MOVD R0, (R9) // update len
|
|
||||||
|
|
||||||
aligned:
|
|
||||||
// setup
|
// setup
|
||||||
MOVD $95, R0
|
MOVD $95, R0
|
||||||
VLM (R5), KEY0, KEY1
|
VLM (R5), KEY0, KEY1
|
||||||
@ -217,9 +193,7 @@ loop:
|
|||||||
|
|
||||||
// decrement length
|
// decrement length
|
||||||
ADD $-256, R4
|
ADD $-256, R4
|
||||||
BLT tail
|
|
||||||
|
|
||||||
continue:
|
|
||||||
// rearrange vectors
|
// rearrange vectors
|
||||||
SHUFFLE(X0, X1, X2, X3, M0, M1, M2, M3)
|
SHUFFLE(X0, X1, X2, X3, M0, M1, M2, M3)
|
||||||
ADDV(J0, X0, X1, X2, X3)
|
ADDV(J0, X0, X1, X2, X3)
|
||||||
@ -245,16 +219,6 @@ continue:
|
|||||||
MOVD $256(R3), R3
|
MOVD $256(R3), R3
|
||||||
|
|
||||||
CMPBNE R4, $0, chacha
|
CMPBNE R4, $0, chacha
|
||||||
CMPUBEQ R12, $255, return
|
|
||||||
EXRL $·mvcBufToDst(SB), R12 // len was updated during setup
|
|
||||||
|
|
||||||
return:
|
|
||||||
VSTEF $0, CTR, (R7)
|
VSTEF $0, CTR, (R7)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
tail:
|
|
||||||
MOVD R2, R9
|
|
||||||
MOVD R8, R2
|
|
||||||
MOVD R8, R3
|
|
||||||
MOVD $0, R4
|
|
||||||
JMP continue
|
|
@ -4,9 +4,7 @@
|
|||||||
|
|
||||||
package chacha20
|
package chacha20
|
||||||
|
|
||||||
import (
|
import "runtime"
|
||||||
"runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Platforms that have fast unaligned 32-bit little endian accesses.
|
// Platforms that have fast unaligned 32-bit little endian accesses.
|
||||||
const unaligned = runtime.GOARCH == "386" ||
|
const unaligned = runtime.GOARCH == "386" ||
|
8
vendor/golang.org/x/crypto/curve25519/const_amd64.h
generated
vendored
8
vendor/golang.org/x/crypto/curve25519/const_amd64.h
generated
vendored
@ -1,8 +0,0 @@
|
|||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// This code was translated into a form compatible with 6a from the public
|
|
||||||
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
|
|
||||||
|
|
||||||
#define REDMASK51 0x0007FFFFFFFFFFFF
|
|
20
vendor/golang.org/x/crypto/curve25519/const_amd64.s
generated
vendored
20
vendor/golang.org/x/crypto/curve25519/const_amd64.s
generated
vendored
@ -1,20 +0,0 @@
|
|||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// This code was translated into a form compatible with 6a from the public
|
|
||||||
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
|
|
||||||
|
|
||||||
// +build amd64,!gccgo,!appengine
|
|
||||||
|
|
||||||
// These constants cannot be encoded in non-MOVQ immediates.
|
|
||||||
// We access them directly from memory instead.
|
|
||||||
|
|
||||||
DATA ·_121666_213(SB)/8, $996687872
|
|
||||||
GLOBL ·_121666_213(SB), 8, $8
|
|
||||||
|
|
||||||
DATA ·_2P0(SB)/8, $0xFFFFFFFFFFFDA
|
|
||||||
GLOBL ·_2P0(SB), 8, $8
|
|
||||||
|
|
||||||
DATA ·_2P1234(SB)/8, $0xFFFFFFFFFFFFE
|
|
||||||
GLOBL ·_2P1234(SB), 8, $8
|
|
65
vendor/golang.org/x/crypto/curve25519/cswap_amd64.s
generated
vendored
65
vendor/golang.org/x/crypto/curve25519/cswap_amd64.s
generated
vendored
@ -1,65 +0,0 @@
|
|||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build amd64,!gccgo,!appengine
|
|
||||||
|
|
||||||
// func cswap(inout *[4][5]uint64, v uint64)
|
|
||||||
TEXT ·cswap(SB),7,$0
|
|
||||||
MOVQ inout+0(FP),DI
|
|
||||||
MOVQ v+8(FP),SI
|
|
||||||
|
|
||||||
SUBQ $1, SI
|
|
||||||
NOTQ SI
|
|
||||||
MOVQ SI, X15
|
|
||||||
PSHUFD $0x44, X15, X15
|
|
||||||
|
|
||||||
MOVOU 0(DI), X0
|
|
||||||
MOVOU 16(DI), X2
|
|
||||||
MOVOU 32(DI), X4
|
|
||||||
MOVOU 48(DI), X6
|
|
||||||
MOVOU 64(DI), X8
|
|
||||||
MOVOU 80(DI), X1
|
|
||||||
MOVOU 96(DI), X3
|
|
||||||
MOVOU 112(DI), X5
|
|
||||||
MOVOU 128(DI), X7
|
|
||||||
MOVOU 144(DI), X9
|
|
||||||
|
|
||||||
MOVO X1, X10
|
|
||||||
MOVO X3, X11
|
|
||||||
MOVO X5, X12
|
|
||||||
MOVO X7, X13
|
|
||||||
MOVO X9, X14
|
|
||||||
|
|
||||||
PXOR X0, X10
|
|
||||||
PXOR X2, X11
|
|
||||||
PXOR X4, X12
|
|
||||||
PXOR X6, X13
|
|
||||||
PXOR X8, X14
|
|
||||||
PAND X15, X10
|
|
||||||
PAND X15, X11
|
|
||||||
PAND X15, X12
|
|
||||||
PAND X15, X13
|
|
||||||
PAND X15, X14
|
|
||||||
PXOR X10, X0
|
|
||||||
PXOR X10, X1
|
|
||||||
PXOR X11, X2
|
|
||||||
PXOR X11, X3
|
|
||||||
PXOR X12, X4
|
|
||||||
PXOR X12, X5
|
|
||||||
PXOR X13, X6
|
|
||||||
PXOR X13, X7
|
|
||||||
PXOR X14, X8
|
|
||||||
PXOR X14, X9
|
|
||||||
|
|
||||||
MOVOU X0, 0(DI)
|
|
||||||
MOVOU X2, 16(DI)
|
|
||||||
MOVOU X4, 32(DI)
|
|
||||||
MOVOU X6, 48(DI)
|
|
||||||
MOVOU X8, 64(DI)
|
|
||||||
MOVOU X1, 80(DI)
|
|
||||||
MOVOU X3, 96(DI)
|
|
||||||
MOVOU X5, 112(DI)
|
|
||||||
MOVOU X7, 128(DI)
|
|
||||||
MOVOU X9, 144(DI)
|
|
||||||
RET
|
|
897
vendor/golang.org/x/crypto/curve25519/curve25519.go
generated
vendored
897
vendor/golang.org/x/crypto/curve25519/curve25519.go
generated
vendored
@ -1,834 +1,95 @@
|
|||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// We have an implementation in amd64 assembly so this code is only run on
|
// Package curve25519 provides an implementation of the X25519 function, which
|
||||||
// non-amd64 platforms. The amd64 assembly does not support gccgo.
|
// performs scalar multiplication on the elliptic curve known as Curve25519.
|
||||||
// +build !amd64 gccgo appengine
|
// See RFC 7748.
|
||||||
|
package curve25519 // import "golang.org/x/crypto/curve25519"
|
||||||
package curve25519
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"crypto/subtle"
|
||||||
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This code is a port of the public domain, "ref10" implementation of
|
// ScalarMult sets dst to the product scalar * point.
|
||||||
// curve25519 from SUPERCOP 20130419 by D. J. Bernstein.
|
//
|
||||||
|
// Deprecated: when provided a low-order point, ScalarMult will set dst to all
|
||||||
|
// zeroes, irrespective of the scalar. Instead, use the X25519 function, which
|
||||||
|
// will return an error.
|
||||||
|
func ScalarMult(dst, scalar, point *[32]byte) {
|
||||||
|
scalarMult(dst, scalar, point)
|
||||||
|
}
|
||||||
|
|
||||||
// fieldElement represents an element of the field GF(2^255 - 19). An element
|
// ScalarBaseMult sets dst to the product scalar * base where base is the
|
||||||
// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
|
// standard generator.
|
||||||
// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
|
//
|
||||||
// context.
|
// It is recommended to use the X25519 function with Basepoint instead, as
|
||||||
type fieldElement [10]int32
|
// copying into fixed size arrays can lead to unexpected bugs.
|
||||||
|
func ScalarBaseMult(dst, scalar *[32]byte) {
|
||||||
|
ScalarMult(dst, scalar, &basePoint)
|
||||||
|
}
|
||||||
|
|
||||||
func feZero(fe *fieldElement) {
|
const (
|
||||||
for i := range fe {
|
// ScalarSize is the size of the scalar input to X25519.
|
||||||
fe[i] = 0
|
ScalarSize = 32
|
||||||
|
// PointSize is the size of the point input to X25519.
|
||||||
|
PointSize = 32
|
||||||
|
)
|
||||||
|
|
||||||
|
// Basepoint is the canonical Curve25519 generator.
|
||||||
|
var Basepoint []byte
|
||||||
|
|
||||||
|
var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
|
|
||||||
|
func init() { Basepoint = basePoint[:] }
|
||||||
|
|
||||||
|
func checkBasepoint() {
|
||||||
|
if subtle.ConstantTimeCompare(Basepoint, []byte{
|
||||||
|
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
}) != 1 {
|
||||||
|
panic("curve25519: global Basepoint value was modified")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func feOne(fe *fieldElement) {
|
// X25519 returns the result of the scalar multiplication (scalar * point),
|
||||||
feZero(fe)
|
// according to RFC 7748, Section 5. scalar, point and the return value are
|
||||||
fe[0] = 1
|
// slices of 32 bytes.
|
||||||
|
//
|
||||||
|
// scalar can be generated at random, for example with crypto/rand. point should
|
||||||
|
// be either Basepoint or the output of another X25519 call.
|
||||||
|
//
|
||||||
|
// If point is Basepoint (but not if it's a different slice with the same
|
||||||
|
// contents) a precomputed implementation might be used for performance.
|
||||||
|
func X25519(scalar, point []byte) ([]byte, error) {
|
||||||
|
// Outline the body of function, to let the allocation be inlined in the
|
||||||
|
// caller, and possibly avoid escaping to the heap.
|
||||||
|
var dst [32]byte
|
||||||
|
return x25519(&dst, scalar, point)
|
||||||
}
|
}
|
||||||
|
|
||||||
func feAdd(dst, a, b *fieldElement) {
|
func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) {
|
||||||
for i := range dst {
|
var in [32]byte
|
||||||
dst[i] = a[i] + b[i]
|
if l := len(scalar); l != 32 {
|
||||||
|
return nil, fmt.Errorf("bad scalar length: %d, expected %d", l, 32)
|
||||||
}
|
}
|
||||||
}
|
if l := len(point); l != 32 {
|
||||||
|
return nil, fmt.Errorf("bad point length: %d, expected %d", l, 32)
|
||||||
func feSub(dst, a, b *fieldElement) {
|
}
|
||||||
for i := range dst {
|
copy(in[:], scalar)
|
||||||
dst[i] = a[i] - b[i]
|
if &point[0] == &Basepoint[0] {
|
||||||
}
|
checkBasepoint()
|
||||||
}
|
ScalarBaseMult(dst, &in)
|
||||||
|
} else {
|
||||||
func feCopy(dst, src *fieldElement) {
|
var base, zero [32]byte
|
||||||
for i := range dst {
|
copy(base[:], point)
|
||||||
dst[i] = src[i]
|
ScalarMult(dst, &in, &base)
|
||||||
}
|
if subtle.ConstantTimeCompare(dst[:], zero[:]) == 1 {
|
||||||
}
|
return nil, fmt.Errorf("bad input point: low order point")
|
||||||
|
}
|
||||||
// feCSwap replaces (f,g) with (g,f) if b == 1; replaces (f,g) with (f,g) if b == 0.
|
}
|
||||||
//
|
return dst[:], nil
|
||||||
// Preconditions: b in {0,1}.
|
|
||||||
func feCSwap(f, g *fieldElement, b int32) {
|
|
||||||
b = -b
|
|
||||||
for i := range f {
|
|
||||||
t := b & (f[i] ^ g[i])
|
|
||||||
f[i] ^= t
|
|
||||||
g[i] ^= t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// load3 reads a 24-bit, little-endian value from in.
|
|
||||||
func load3(in []byte) int64 {
|
|
||||||
var r int64
|
|
||||||
r = int64(in[0])
|
|
||||||
r |= int64(in[1]) << 8
|
|
||||||
r |= int64(in[2]) << 16
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// load4 reads a 32-bit, little-endian value from in.
|
|
||||||
func load4(in []byte) int64 {
|
|
||||||
return int64(binary.LittleEndian.Uint32(in))
|
|
||||||
}
|
|
||||||
|
|
||||||
func feFromBytes(dst *fieldElement, src *[32]byte) {
|
|
||||||
h0 := load4(src[:])
|
|
||||||
h1 := load3(src[4:]) << 6
|
|
||||||
h2 := load3(src[7:]) << 5
|
|
||||||
h3 := load3(src[10:]) << 3
|
|
||||||
h4 := load3(src[13:]) << 2
|
|
||||||
h5 := load4(src[16:])
|
|
||||||
h6 := load3(src[20:]) << 7
|
|
||||||
h7 := load3(src[23:]) << 5
|
|
||||||
h8 := load3(src[26:]) << 4
|
|
||||||
h9 := (load3(src[29:]) & 0x7fffff) << 2
|
|
||||||
|
|
||||||
var carry [10]int64
|
|
||||||
carry[9] = (h9 + 1<<24) >> 25
|
|
||||||
h0 += carry[9] * 19
|
|
||||||
h9 -= carry[9] << 25
|
|
||||||
carry[1] = (h1 + 1<<24) >> 25
|
|
||||||
h2 += carry[1]
|
|
||||||
h1 -= carry[1] << 25
|
|
||||||
carry[3] = (h3 + 1<<24) >> 25
|
|
||||||
h4 += carry[3]
|
|
||||||
h3 -= carry[3] << 25
|
|
||||||
carry[5] = (h5 + 1<<24) >> 25
|
|
||||||
h6 += carry[5]
|
|
||||||
h5 -= carry[5] << 25
|
|
||||||
carry[7] = (h7 + 1<<24) >> 25
|
|
||||||
h8 += carry[7]
|
|
||||||
h7 -= carry[7] << 25
|
|
||||||
|
|
||||||
carry[0] = (h0 + 1<<25) >> 26
|
|
||||||
h1 += carry[0]
|
|
||||||
h0 -= carry[0] << 26
|
|
||||||
carry[2] = (h2 + 1<<25) >> 26
|
|
||||||
h3 += carry[2]
|
|
||||||
h2 -= carry[2] << 26
|
|
||||||
carry[4] = (h4 + 1<<25) >> 26
|
|
||||||
h5 += carry[4]
|
|
||||||
h4 -= carry[4] << 26
|
|
||||||
carry[6] = (h6 + 1<<25) >> 26
|
|
||||||
h7 += carry[6]
|
|
||||||
h6 -= carry[6] << 26
|
|
||||||
carry[8] = (h8 + 1<<25) >> 26
|
|
||||||
h9 += carry[8]
|
|
||||||
h8 -= carry[8] << 26
|
|
||||||
|
|
||||||
dst[0] = int32(h0)
|
|
||||||
dst[1] = int32(h1)
|
|
||||||
dst[2] = int32(h2)
|
|
||||||
dst[3] = int32(h3)
|
|
||||||
dst[4] = int32(h4)
|
|
||||||
dst[5] = int32(h5)
|
|
||||||
dst[6] = int32(h6)
|
|
||||||
dst[7] = int32(h7)
|
|
||||||
dst[8] = int32(h8)
|
|
||||||
dst[9] = int32(h9)
|
|
||||||
}
|
|
||||||
|
|
||||||
// feToBytes marshals h to s.
|
|
||||||
// Preconditions:
|
|
||||||
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
|
|
||||||
//
|
|
||||||
// Write p=2^255-19; q=floor(h/p).
|
|
||||||
// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
|
|
||||||
//
|
|
||||||
// Proof:
|
|
||||||
// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
|
|
||||||
// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4.
|
|
||||||
//
|
|
||||||
// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
|
|
||||||
// Then 0<y<1.
|
|
||||||
//
|
|
||||||
// Write r=h-pq.
|
|
||||||
// Have 0<=r<=p-1=2^255-20.
|
|
||||||
// Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
|
|
||||||
//
|
|
||||||
// Write x=r+19(2^-255)r+y.
|
|
||||||
// Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
|
|
||||||
//
|
|
||||||
// Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
|
|
||||||
// so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q.
|
|
||||||
func feToBytes(s *[32]byte, h *fieldElement) {
|
|
||||||
var carry [10]int32
|
|
||||||
|
|
||||||
q := (19*h[9] + (1 << 24)) >> 25
|
|
||||||
q = (h[0] + q) >> 26
|
|
||||||
q = (h[1] + q) >> 25
|
|
||||||
q = (h[2] + q) >> 26
|
|
||||||
q = (h[3] + q) >> 25
|
|
||||||
q = (h[4] + q) >> 26
|
|
||||||
q = (h[5] + q) >> 25
|
|
||||||
q = (h[6] + q) >> 26
|
|
||||||
q = (h[7] + q) >> 25
|
|
||||||
q = (h[8] + q) >> 26
|
|
||||||
q = (h[9] + q) >> 25
|
|
||||||
|
|
||||||
// Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20.
|
|
||||||
h[0] += 19 * q
|
|
||||||
// Goal: Output h-2^255 q, which is between 0 and 2^255-20.
|
|
||||||
|
|
||||||
carry[0] = h[0] >> 26
|
|
||||||
h[1] += carry[0]
|
|
||||||
h[0] -= carry[0] << 26
|
|
||||||
carry[1] = h[1] >> 25
|
|
||||||
h[2] += carry[1]
|
|
||||||
h[1] -= carry[1] << 25
|
|
||||||
carry[2] = h[2] >> 26
|
|
||||||
h[3] += carry[2]
|
|
||||||
h[2] -= carry[2] << 26
|
|
||||||
carry[3] = h[3] >> 25
|
|
||||||
h[4] += carry[3]
|
|
||||||
h[3] -= carry[3] << 25
|
|
||||||
carry[4] = h[4] >> 26
|
|
||||||
h[5] += carry[4]
|
|
||||||
h[4] -= carry[4] << 26
|
|
||||||
carry[5] = h[5] >> 25
|
|
||||||
h[6] += carry[5]
|
|
||||||
h[5] -= carry[5] << 25
|
|
||||||
carry[6] = h[6] >> 26
|
|
||||||
h[7] += carry[6]
|
|
||||||
h[6] -= carry[6] << 26
|
|
||||||
carry[7] = h[7] >> 25
|
|
||||||
h[8] += carry[7]
|
|
||||||
h[7] -= carry[7] << 25
|
|
||||||
carry[8] = h[8] >> 26
|
|
||||||
h[9] += carry[8]
|
|
||||||
h[8] -= carry[8] << 26
|
|
||||||
carry[9] = h[9] >> 25
|
|
||||||
h[9] -= carry[9] << 25
|
|
||||||
// h10 = carry9
|
|
||||||
|
|
||||||
// Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
|
|
||||||
// Have h[0]+...+2^230 h[9] between 0 and 2^255-1;
|
|
||||||
// evidently 2^255 h10-2^255 q = 0.
|
|
||||||
// Goal: Output h[0]+...+2^230 h[9].
|
|
||||||
|
|
||||||
s[0] = byte(h[0] >> 0)
|
|
||||||
s[1] = byte(h[0] >> 8)
|
|
||||||
s[2] = byte(h[0] >> 16)
|
|
||||||
s[3] = byte((h[0] >> 24) | (h[1] << 2))
|
|
||||||
s[4] = byte(h[1] >> 6)
|
|
||||||
s[5] = byte(h[1] >> 14)
|
|
||||||
s[6] = byte((h[1] >> 22) | (h[2] << 3))
|
|
||||||
s[7] = byte(h[2] >> 5)
|
|
||||||
s[8] = byte(h[2] >> 13)
|
|
||||||
s[9] = byte((h[2] >> 21) | (h[3] << 5))
|
|
||||||
s[10] = byte(h[3] >> 3)
|
|
||||||
s[11] = byte(h[3] >> 11)
|
|
||||||
s[12] = byte((h[3] >> 19) | (h[4] << 6))
|
|
||||||
s[13] = byte(h[4] >> 2)
|
|
||||||
s[14] = byte(h[4] >> 10)
|
|
||||||
s[15] = byte(h[4] >> 18)
|
|
||||||
s[16] = byte(h[5] >> 0)
|
|
||||||
s[17] = byte(h[5] >> 8)
|
|
||||||
s[18] = byte(h[5] >> 16)
|
|
||||||
s[19] = byte((h[5] >> 24) | (h[6] << 1))
|
|
||||||
s[20] = byte(h[6] >> 7)
|
|
||||||
s[21] = byte(h[6] >> 15)
|
|
||||||
s[22] = byte((h[6] >> 23) | (h[7] << 3))
|
|
||||||
s[23] = byte(h[7] >> 5)
|
|
||||||
s[24] = byte(h[7] >> 13)
|
|
||||||
s[25] = byte((h[7] >> 21) | (h[8] << 4))
|
|
||||||
s[26] = byte(h[8] >> 4)
|
|
||||||
s[27] = byte(h[8] >> 12)
|
|
||||||
s[28] = byte((h[8] >> 20) | (h[9] << 6))
|
|
||||||
s[29] = byte(h[9] >> 2)
|
|
||||||
s[30] = byte(h[9] >> 10)
|
|
||||||
s[31] = byte(h[9] >> 18)
|
|
||||||
}
|
|
||||||
|
|
||||||
// feMul calculates h = f * g
|
|
||||||
// Can overlap h with f or g.
|
|
||||||
//
|
|
||||||
// Preconditions:
|
|
||||||
// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
|
|
||||||
// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
|
|
||||||
//
|
|
||||||
// Postconditions:
|
|
||||||
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
|
|
||||||
//
|
|
||||||
// Notes on implementation strategy:
|
|
||||||
//
|
|
||||||
// Using schoolbook multiplication.
|
|
||||||
// Karatsuba would save a little in some cost models.
|
|
||||||
//
|
|
||||||
// Most multiplications by 2 and 19 are 32-bit precomputations;
|
|
||||||
// cheaper than 64-bit postcomputations.
|
|
||||||
//
|
|
||||||
// There is one remaining multiplication by 19 in the carry chain;
|
|
||||||
// one *19 precomputation can be merged into this,
|
|
||||||
// but the resulting data flow is considerably less clean.
|
|
||||||
//
|
|
||||||
// There are 12 carries below.
|
|
||||||
// 10 of them are 2-way parallelizable and vectorizable.
|
|
||||||
// Can get away with 11 carries, but then data flow is much deeper.
|
|
||||||
//
|
|
||||||
// With tighter constraints on inputs can squeeze carries into int32.
|
|
||||||
func feMul(h, f, g *fieldElement) {
|
|
||||||
f0 := f[0]
|
|
||||||
f1 := f[1]
|
|
||||||
f2 := f[2]
|
|
||||||
f3 := f[3]
|
|
||||||
f4 := f[4]
|
|
||||||
f5 := f[5]
|
|
||||||
f6 := f[6]
|
|
||||||
f7 := f[7]
|
|
||||||
f8 := f[8]
|
|
||||||
f9 := f[9]
|
|
||||||
g0 := g[0]
|
|
||||||
g1 := g[1]
|
|
||||||
g2 := g[2]
|
|
||||||
g3 := g[3]
|
|
||||||
g4 := g[4]
|
|
||||||
g5 := g[5]
|
|
||||||
g6 := g[6]
|
|
||||||
g7 := g[7]
|
|
||||||
g8 := g[8]
|
|
||||||
g9 := g[9]
|
|
||||||
g1_19 := 19 * g1 // 1.4*2^29
|
|
||||||
g2_19 := 19 * g2 // 1.4*2^30; still ok
|
|
||||||
g3_19 := 19 * g3
|
|
||||||
g4_19 := 19 * g4
|
|
||||||
g5_19 := 19 * g5
|
|
||||||
g6_19 := 19 * g6
|
|
||||||
g7_19 := 19 * g7
|
|
||||||
g8_19 := 19 * g8
|
|
||||||
g9_19 := 19 * g9
|
|
||||||
f1_2 := 2 * f1
|
|
||||||
f3_2 := 2 * f3
|
|
||||||
f5_2 := 2 * f5
|
|
||||||
f7_2 := 2 * f7
|
|
||||||
f9_2 := 2 * f9
|
|
||||||
f0g0 := int64(f0) * int64(g0)
|
|
||||||
f0g1 := int64(f0) * int64(g1)
|
|
||||||
f0g2 := int64(f0) * int64(g2)
|
|
||||||
f0g3 := int64(f0) * int64(g3)
|
|
||||||
f0g4 := int64(f0) * int64(g4)
|
|
||||||
f0g5 := int64(f0) * int64(g5)
|
|
||||||
f0g6 := int64(f0) * int64(g6)
|
|
||||||
f0g7 := int64(f0) * int64(g7)
|
|
||||||
f0g8 := int64(f0) * int64(g8)
|
|
||||||
f0g9 := int64(f0) * int64(g9)
|
|
||||||
f1g0 := int64(f1) * int64(g0)
|
|
||||||
f1g1_2 := int64(f1_2) * int64(g1)
|
|
||||||
f1g2 := int64(f1) * int64(g2)
|
|
||||||
f1g3_2 := int64(f1_2) * int64(g3)
|
|
||||||
f1g4 := int64(f1) * int64(g4)
|
|
||||||
f1g5_2 := int64(f1_2) * int64(g5)
|
|
||||||
f1g6 := int64(f1) * int64(g6)
|
|
||||||
f1g7_2 := int64(f1_2) * int64(g7)
|
|
||||||
f1g8 := int64(f1) * int64(g8)
|
|
||||||
f1g9_38 := int64(f1_2) * int64(g9_19)
|
|
||||||
f2g0 := int64(f2) * int64(g0)
|
|
||||||
f2g1 := int64(f2) * int64(g1)
|
|
||||||
f2g2 := int64(f2) * int64(g2)
|
|
||||||
f2g3 := int64(f2) * int64(g3)
|
|
||||||
f2g4 := int64(f2) * int64(g4)
|
|
||||||
f2g5 := int64(f2) * int64(g5)
|
|
||||||
f2g6 := int64(f2) * int64(g6)
|
|
||||||
f2g7 := int64(f2) * int64(g7)
|
|
||||||
f2g8_19 := int64(f2) * int64(g8_19)
|
|
||||||
f2g9_19 := int64(f2) * int64(g9_19)
|
|
||||||
f3g0 := int64(f3) * int64(g0)
|
|
||||||
f3g1_2 := int64(f3_2) * int64(g1)
|
|
||||||
f3g2 := int64(f3) * int64(g2)
|
|
||||||
f3g3_2 := int64(f3_2) * int64(g3)
|
|
||||||
f3g4 := int64(f3) * int64(g4)
|
|
||||||
f3g5_2 := int64(f3_2) * int64(g5)
|
|
||||||
f3g6 := int64(f3) * int64(g6)
|
|
||||||
f3g7_38 := int64(f3_2) * int64(g7_19)
|
|
||||||
f3g8_19 := int64(f3) * int64(g8_19)
|
|
||||||
f3g9_38 := int64(f3_2) * int64(g9_19)
|
|
||||||
f4g0 := int64(f4) * int64(g0)
|
|
||||||
f4g1 := int64(f4) * int64(g1)
|
|
||||||
f4g2 := int64(f4) * int64(g2)
|
|
||||||
f4g3 := int64(f4) * int64(g3)
|
|
||||||
f4g4 := int64(f4) * int64(g4)
|
|
||||||
f4g5 := int64(f4) * int64(g5)
|
|
||||||
f4g6_19 := int64(f4) * int64(g6_19)
|
|
||||||
f4g7_19 := int64(f4) * int64(g7_19)
|
|
||||||
f4g8_19 := int64(f4) * int64(g8_19)
|
|
||||||
f4g9_19 := int64(f4) * int64(g9_19)
|
|
||||||
f5g0 := int64(f5) * int64(g0)
|
|
||||||
f5g1_2 := int64(f5_2) * int64(g1)
|
|
||||||
f5g2 := int64(f5) * int64(g2)
|
|
||||||
f5g3_2 := int64(f5_2) * int64(g3)
|
|
||||||
f5g4 := int64(f5) * int64(g4)
|
|
||||||
f5g5_38 := int64(f5_2) * int64(g5_19)
|
|
||||||
f5g6_19 := int64(f5) * int64(g6_19)
|
|
||||||
f5g7_38 := int64(f5_2) * int64(g7_19)
|
|
||||||
f5g8_19 := int64(f5) * int64(g8_19)
|
|
||||||
f5g9_38 := int64(f5_2) * int64(g9_19)
|
|
||||||
f6g0 := int64(f6) * int64(g0)
|
|
||||||
f6g1 := int64(f6) * int64(g1)
|
|
||||||
f6g2 := int64(f6) * int64(g2)
|
|
||||||
f6g3 := int64(f6) * int64(g3)
|
|
||||||
f6g4_19 := int64(f6) * int64(g4_19)
|
|
||||||
f6g5_19 := int64(f6) * int64(g5_19)
|
|
||||||
f6g6_19 := int64(f6) * int64(g6_19)
|
|
||||||
f6g7_19 := int64(f6) * int64(g7_19)
|
|
||||||
f6g8_19 := int64(f6) * int64(g8_19)
|
|
||||||
f6g9_19 := int64(f6) * int64(g9_19)
|
|
||||||
f7g0 := int64(f7) * int64(g0)
|
|
||||||
f7g1_2 := int64(f7_2) * int64(g1)
|
|
||||||
f7g2 := int64(f7) * int64(g2)
|
|
||||||
f7g3_38 := int64(f7_2) * int64(g3_19)
|
|
||||||
f7g4_19 := int64(f7) * int64(g4_19)
|
|
||||||
f7g5_38 := int64(f7_2) * int64(g5_19)
|
|
||||||
f7g6_19 := int64(f7) * int64(g6_19)
|
|
||||||
f7g7_38 := int64(f7_2) * int64(g7_19)
|
|
||||||
f7g8_19 := int64(f7) * int64(g8_19)
|
|
||||||
f7g9_38 := int64(f7_2) * int64(g9_19)
|
|
||||||
f8g0 := int64(f8) * int64(g0)
|
|
||||||
f8g1 := int64(f8) * int64(g1)
|
|
||||||
f8g2_19 := int64(f8) * int64(g2_19)
|
|
||||||
f8g3_19 := int64(f8) * int64(g3_19)
|
|
||||||
f8g4_19 := int64(f8) * int64(g4_19)
|
|
||||||
f8g5_19 := int64(f8) * int64(g5_19)
|
|
||||||
f8g6_19 := int64(f8) * int64(g6_19)
|
|
||||||
f8g7_19 := int64(f8) * int64(g7_19)
|
|
||||||
f8g8_19 := int64(f8) * int64(g8_19)
|
|
||||||
f8g9_19 := int64(f8) * int64(g9_19)
|
|
||||||
f9g0 := int64(f9) * int64(g0)
|
|
||||||
f9g1_38 := int64(f9_2) * int64(g1_19)
|
|
||||||
f9g2_19 := int64(f9) * int64(g2_19)
|
|
||||||
f9g3_38 := int64(f9_2) * int64(g3_19)
|
|
||||||
f9g4_19 := int64(f9) * int64(g4_19)
|
|
||||||
f9g5_38 := int64(f9_2) * int64(g5_19)
|
|
||||||
f9g6_19 := int64(f9) * int64(g6_19)
|
|
||||||
f9g7_38 := int64(f9_2) * int64(g7_19)
|
|
||||||
f9g8_19 := int64(f9) * int64(g8_19)
|
|
||||||
f9g9_38 := int64(f9_2) * int64(g9_19)
|
|
||||||
h0 := f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38
|
|
||||||
h1 := f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19
|
|
||||||
h2 := f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38
|
|
||||||
h3 := f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19
|
|
||||||
h4 := f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38
|
|
||||||
h5 := f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19
|
|
||||||
h6 := f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38
|
|
||||||
h7 := f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19
|
|
||||||
h8 := f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38
|
|
||||||
h9 := f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0
|
|
||||||
var carry [10]int64
|
|
||||||
|
|
||||||
// |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38))
|
|
||||||
// i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8
|
|
||||||
// |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19))
|
|
||||||
// i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9
|
|
||||||
|
|
||||||
carry[0] = (h0 + (1 << 25)) >> 26
|
|
||||||
h1 += carry[0]
|
|
||||||
h0 -= carry[0] << 26
|
|
||||||
carry[4] = (h4 + (1 << 25)) >> 26
|
|
||||||
h5 += carry[4]
|
|
||||||
h4 -= carry[4] << 26
|
|
||||||
// |h0| <= 2^25
|
|
||||||
// |h4| <= 2^25
|
|
||||||
// |h1| <= 1.51*2^58
|
|
||||||
// |h5| <= 1.51*2^58
|
|
||||||
|
|
||||||
carry[1] = (h1 + (1 << 24)) >> 25
|
|
||||||
h2 += carry[1]
|
|
||||||
h1 -= carry[1] << 25
|
|
||||||
carry[5] = (h5 + (1 << 24)) >> 25
|
|
||||||
h6 += carry[5]
|
|
||||||
h5 -= carry[5] << 25
|
|
||||||
// |h1| <= 2^24; from now on fits into int32
|
|
||||||
// |h5| <= 2^24; from now on fits into int32
|
|
||||||
// |h2| <= 1.21*2^59
|
|
||||||
// |h6| <= 1.21*2^59
|
|
||||||
|
|
||||||
carry[2] = (h2 + (1 << 25)) >> 26
|
|
||||||
h3 += carry[2]
|
|
||||||
h2 -= carry[2] << 26
|
|
||||||
carry[6] = (h6 + (1 << 25)) >> 26
|
|
||||||
h7 += carry[6]
|
|
||||||
h6 -= carry[6] << 26
|
|
||||||
// |h2| <= 2^25; from now on fits into int32 unchanged
|
|
||||||
// |h6| <= 2^25; from now on fits into int32 unchanged
|
|
||||||
// |h3| <= 1.51*2^58
|
|
||||||
// |h7| <= 1.51*2^58
|
|
||||||
|
|
||||||
carry[3] = (h3 + (1 << 24)) >> 25
|
|
||||||
h4 += carry[3]
|
|
||||||
h3 -= carry[3] << 25
|
|
||||||
carry[7] = (h7 + (1 << 24)) >> 25
|
|
||||||
h8 += carry[7]
|
|
||||||
h7 -= carry[7] << 25
|
|
||||||
// |h3| <= 2^24; from now on fits into int32 unchanged
|
|
||||||
// |h7| <= 2^24; from now on fits into int32 unchanged
|
|
||||||
// |h4| <= 1.52*2^33
|
|
||||||
// |h8| <= 1.52*2^33
|
|
||||||
|
|
||||||
carry[4] = (h4 + (1 << 25)) >> 26
|
|
||||||
h5 += carry[4]
|
|
||||||
h4 -= carry[4] << 26
|
|
||||||
carry[8] = (h8 + (1 << 25)) >> 26
|
|
||||||
h9 += carry[8]
|
|
||||||
h8 -= carry[8] << 26
|
|
||||||
// |h4| <= 2^25; from now on fits into int32 unchanged
|
|
||||||
// |h8| <= 2^25; from now on fits into int32 unchanged
|
|
||||||
// |h5| <= 1.01*2^24
|
|
||||||
// |h9| <= 1.51*2^58
|
|
||||||
|
|
||||||
carry[9] = (h9 + (1 << 24)) >> 25
|
|
||||||
h0 += carry[9] * 19
|
|
||||||
h9 -= carry[9] << 25
|
|
||||||
// |h9| <= 2^24; from now on fits into int32 unchanged
|
|
||||||
// |h0| <= 1.8*2^37
|
|
||||||
|
|
||||||
carry[0] = (h0 + (1 << 25)) >> 26
|
|
||||||
h1 += carry[0]
|
|
||||||
h0 -= carry[0] << 26
|
|
||||||
// |h0| <= 2^25; from now on fits into int32 unchanged
|
|
||||||
// |h1| <= 1.01*2^24
|
|
||||||
|
|
||||||
h[0] = int32(h0)
|
|
||||||
h[1] = int32(h1)
|
|
||||||
h[2] = int32(h2)
|
|
||||||
h[3] = int32(h3)
|
|
||||||
h[4] = int32(h4)
|
|
||||||
h[5] = int32(h5)
|
|
||||||
h[6] = int32(h6)
|
|
||||||
h[7] = int32(h7)
|
|
||||||
h[8] = int32(h8)
|
|
||||||
h[9] = int32(h9)
|
|
||||||
}
|
|
||||||
|
|
||||||
// feSquare calculates h = f*f. Can overlap h with f.
|
|
||||||
//
|
|
||||||
// Preconditions:
|
|
||||||
// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
|
|
||||||
//
|
|
||||||
// Postconditions:
|
|
||||||
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
|
|
||||||
func feSquare(h, f *fieldElement) {
|
|
||||||
f0 := f[0]
|
|
||||||
f1 := f[1]
|
|
||||||
f2 := f[2]
|
|
||||||
f3 := f[3]
|
|
||||||
f4 := f[4]
|
|
||||||
f5 := f[5]
|
|
||||||
f6 := f[6]
|
|
||||||
f7 := f[7]
|
|
||||||
f8 := f[8]
|
|
||||||
f9 := f[9]
|
|
||||||
f0_2 := 2 * f0
|
|
||||||
f1_2 := 2 * f1
|
|
||||||
f2_2 := 2 * f2
|
|
||||||
f3_2 := 2 * f3
|
|
||||||
f4_2 := 2 * f4
|
|
||||||
f5_2 := 2 * f5
|
|
||||||
f6_2 := 2 * f6
|
|
||||||
f7_2 := 2 * f7
|
|
||||||
f5_38 := 38 * f5 // 1.31*2^30
|
|
||||||
f6_19 := 19 * f6 // 1.31*2^30
|
|
||||||
f7_38 := 38 * f7 // 1.31*2^30
|
|
||||||
f8_19 := 19 * f8 // 1.31*2^30
|
|
||||||
f9_38 := 38 * f9 // 1.31*2^30
|
|
||||||
f0f0 := int64(f0) * int64(f0)
|
|
||||||
f0f1_2 := int64(f0_2) * int64(f1)
|
|
||||||
f0f2_2 := int64(f0_2) * int64(f2)
|
|
||||||
f0f3_2 := int64(f0_2) * int64(f3)
|
|
||||||
f0f4_2 := int64(f0_2) * int64(f4)
|
|
||||||
f0f5_2 := int64(f0_2) * int64(f5)
|
|
||||||
f0f6_2 := int64(f0_2) * int64(f6)
|
|
||||||
f0f7_2 := int64(f0_2) * int64(f7)
|
|
||||||
f0f8_2 := int64(f0_2) * int64(f8)
|
|
||||||
f0f9_2 := int64(f0_2) * int64(f9)
|
|
||||||
f1f1_2 := int64(f1_2) * int64(f1)
|
|
||||||
f1f2_2 := int64(f1_2) * int64(f2)
|
|
||||||
f1f3_4 := int64(f1_2) * int64(f3_2)
|
|
||||||
f1f4_2 := int64(f1_2) * int64(f4)
|
|
||||||
f1f5_4 := int64(f1_2) * int64(f5_2)
|
|
||||||
f1f6_2 := int64(f1_2) * int64(f6)
|
|
||||||
f1f7_4 := int64(f1_2) * int64(f7_2)
|
|
||||||
f1f8_2 := int64(f1_2) * int64(f8)
|
|
||||||
f1f9_76 := int64(f1_2) * int64(f9_38)
|
|
||||||
f2f2 := int64(f2) * int64(f2)
|
|
||||||
f2f3_2 := int64(f2_2) * int64(f3)
|
|
||||||
f2f4_2 := int64(f2_2) * int64(f4)
|
|
||||||
f2f5_2 := int64(f2_2) * int64(f5)
|
|
||||||
f2f6_2 := int64(f2_2) * int64(f6)
|
|
||||||
f2f7_2 := int64(f2_2) * int64(f7)
|
|
||||||
f2f8_38 := int64(f2_2) * int64(f8_19)
|
|
||||||
f2f9_38 := int64(f2) * int64(f9_38)
|
|
||||||
f3f3_2 := int64(f3_2) * int64(f3)
|
|
||||||
f3f4_2 := int64(f3_2) * int64(f4)
|
|
||||||
f3f5_4 := int64(f3_2) * int64(f5_2)
|
|
||||||
f3f6_2 := int64(f3_2) * int64(f6)
|
|
||||||
f3f7_76 := int64(f3_2) * int64(f7_38)
|
|
||||||
f3f8_38 := int64(f3_2) * int64(f8_19)
|
|
||||||
f3f9_76 := int64(f3_2) * int64(f9_38)
|
|
||||||
f4f4 := int64(f4) * int64(f4)
|
|
||||||
f4f5_2 := int64(f4_2) * int64(f5)
|
|
||||||
f4f6_38 := int64(f4_2) * int64(f6_19)
|
|
||||||
f4f7_38 := int64(f4) * int64(f7_38)
|
|
||||||
f4f8_38 := int64(f4_2) * int64(f8_19)
|
|
||||||
f4f9_38 := int64(f4) * int64(f9_38)
|
|
||||||
f5f5_38 := int64(f5) * int64(f5_38)
|
|
||||||
f5f6_38 := int64(f5_2) * int64(f6_19)
|
|
||||||
f5f7_76 := int64(f5_2) * int64(f7_38)
|
|
||||||
f5f8_38 := int64(f5_2) * int64(f8_19)
|
|
||||||
f5f9_76 := int64(f5_2) * int64(f9_38)
|
|
||||||
f6f6_19 := int64(f6) * int64(f6_19)
|
|
||||||
f6f7_38 := int64(f6) * int64(f7_38)
|
|
||||||
f6f8_38 := int64(f6_2) * int64(f8_19)
|
|
||||||
f6f9_38 := int64(f6) * int64(f9_38)
|
|
||||||
f7f7_38 := int64(f7) * int64(f7_38)
|
|
||||||
f7f8_38 := int64(f7_2) * int64(f8_19)
|
|
||||||
f7f9_76 := int64(f7_2) * int64(f9_38)
|
|
||||||
f8f8_19 := int64(f8) * int64(f8_19)
|
|
||||||
f8f9_38 := int64(f8) * int64(f9_38)
|
|
||||||
f9f9_38 := int64(f9) * int64(f9_38)
|
|
||||||
h0 := f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38
|
|
||||||
h1 := f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38
|
|
||||||
h2 := f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19
|
|
||||||
h3 := f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38
|
|
||||||
h4 := f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38
|
|
||||||
h5 := f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38
|
|
||||||
h6 := f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19
|
|
||||||
h7 := f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38
|
|
||||||
h8 := f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38
|
|
||||||
h9 := f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2
|
|
||||||
var carry [10]int64
|
|
||||||
|
|
||||||
carry[0] = (h0 + (1 << 25)) >> 26
|
|
||||||
h1 += carry[0]
|
|
||||||
h0 -= carry[0] << 26
|
|
||||||
carry[4] = (h4 + (1 << 25)) >> 26
|
|
||||||
h5 += carry[4]
|
|
||||||
h4 -= carry[4] << 26
|
|
||||||
|
|
||||||
carry[1] = (h1 + (1 << 24)) >> 25
|
|
||||||
h2 += carry[1]
|
|
||||||
h1 -= carry[1] << 25
|
|
||||||
carry[5] = (h5 + (1 << 24)) >> 25
|
|
||||||
h6 += carry[5]
|
|
||||||
h5 -= carry[5] << 25
|
|
||||||
|
|
||||||
carry[2] = (h2 + (1 << 25)) >> 26
|
|
||||||
h3 += carry[2]
|
|
||||||
h2 -= carry[2] << 26
|
|
||||||
carry[6] = (h6 + (1 << 25)) >> 26
|
|
||||||
h7 += carry[6]
|
|
||||||
h6 -= carry[6] << 26
|
|
||||||
|
|
||||||
carry[3] = (h3 + (1 << 24)) >> 25
|
|
||||||
h4 += carry[3]
|
|
||||||
h3 -= carry[3] << 25
|
|
||||||
carry[7] = (h7 + (1 << 24)) >> 25
|
|
||||||
h8 += carry[7]
|
|
||||||
h7 -= carry[7] << 25
|
|
||||||
|
|
||||||
carry[4] = (h4 + (1 << 25)) >> 26
|
|
||||||
h5 += carry[4]
|
|
||||||
h4 -= carry[4] << 26
|
|
||||||
carry[8] = (h8 + (1 << 25)) >> 26
|
|
||||||
h9 += carry[8]
|
|
||||||
h8 -= carry[8] << 26
|
|
||||||
|
|
||||||
carry[9] = (h9 + (1 << 24)) >> 25
|
|
||||||
h0 += carry[9] * 19
|
|
||||||
h9 -= carry[9] << 25
|
|
||||||
|
|
||||||
carry[0] = (h0 + (1 << 25)) >> 26
|
|
||||||
h1 += carry[0]
|
|
||||||
h0 -= carry[0] << 26
|
|
||||||
|
|
||||||
h[0] = int32(h0)
|
|
||||||
h[1] = int32(h1)
|
|
||||||
h[2] = int32(h2)
|
|
||||||
h[3] = int32(h3)
|
|
||||||
h[4] = int32(h4)
|
|
||||||
h[5] = int32(h5)
|
|
||||||
h[6] = int32(h6)
|
|
||||||
h[7] = int32(h7)
|
|
||||||
h[8] = int32(h8)
|
|
||||||
h[9] = int32(h9)
|
|
||||||
}
|
|
||||||
|
|
||||||
// feMul121666 calculates h = f * 121666. Can overlap h with f.
|
|
||||||
//
|
|
||||||
// Preconditions:
|
|
||||||
// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
|
|
||||||
//
|
|
||||||
// Postconditions:
|
|
||||||
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
|
|
||||||
func feMul121666(h, f *fieldElement) {
|
|
||||||
h0 := int64(f[0]) * 121666
|
|
||||||
h1 := int64(f[1]) * 121666
|
|
||||||
h2 := int64(f[2]) * 121666
|
|
||||||
h3 := int64(f[3]) * 121666
|
|
||||||
h4 := int64(f[4]) * 121666
|
|
||||||
h5 := int64(f[5]) * 121666
|
|
||||||
h6 := int64(f[6]) * 121666
|
|
||||||
h7 := int64(f[7]) * 121666
|
|
||||||
h8 := int64(f[8]) * 121666
|
|
||||||
h9 := int64(f[9]) * 121666
|
|
||||||
var carry [10]int64
|
|
||||||
|
|
||||||
carry[9] = (h9 + (1 << 24)) >> 25
|
|
||||||
h0 += carry[9] * 19
|
|
||||||
h9 -= carry[9] << 25
|
|
||||||
carry[1] = (h1 + (1 << 24)) >> 25
|
|
||||||
h2 += carry[1]
|
|
||||||
h1 -= carry[1] << 25
|
|
||||||
carry[3] = (h3 + (1 << 24)) >> 25
|
|
||||||
h4 += carry[3]
|
|
||||||
h3 -= carry[3] << 25
|
|
||||||
carry[5] = (h5 + (1 << 24)) >> 25
|
|
||||||
h6 += carry[5]
|
|
||||||
h5 -= carry[5] << 25
|
|
||||||
carry[7] = (h7 + (1 << 24)) >> 25
|
|
||||||
h8 += carry[7]
|
|
||||||
h7 -= carry[7] << 25
|
|
||||||
|
|
||||||
carry[0] = (h0 + (1 << 25)) >> 26
|
|
||||||
h1 += carry[0]
|
|
||||||
h0 -= carry[0] << 26
|
|
||||||
carry[2] = (h2 + (1 << 25)) >> 26
|
|
||||||
h3 += carry[2]
|
|
||||||
h2 -= carry[2] << 26
|
|
||||||
carry[4] = (h4 + (1 << 25)) >> 26
|
|
||||||
h5 += carry[4]
|
|
||||||
h4 -= carry[4] << 26
|
|
||||||
carry[6] = (h6 + (1 << 25)) >> 26
|
|
||||||
h7 += carry[6]
|
|
||||||
h6 -= carry[6] << 26
|
|
||||||
carry[8] = (h8 + (1 << 25)) >> 26
|
|
||||||
h9 += carry[8]
|
|
||||||
h8 -= carry[8] << 26
|
|
||||||
|
|
||||||
h[0] = int32(h0)
|
|
||||||
h[1] = int32(h1)
|
|
||||||
h[2] = int32(h2)
|
|
||||||
h[3] = int32(h3)
|
|
||||||
h[4] = int32(h4)
|
|
||||||
h[5] = int32(h5)
|
|
||||||
h[6] = int32(h6)
|
|
||||||
h[7] = int32(h7)
|
|
||||||
h[8] = int32(h8)
|
|
||||||
h[9] = int32(h9)
|
|
||||||
}
|
|
||||||
|
|
||||||
// feInvert sets out = z^-1.
|
|
||||||
func feInvert(out, z *fieldElement) {
|
|
||||||
var t0, t1, t2, t3 fieldElement
|
|
||||||
var i int
|
|
||||||
|
|
||||||
feSquare(&t0, z)
|
|
||||||
for i = 1; i < 1; i++ {
|
|
||||||
feSquare(&t0, &t0)
|
|
||||||
}
|
|
||||||
feSquare(&t1, &t0)
|
|
||||||
for i = 1; i < 2; i++ {
|
|
||||||
feSquare(&t1, &t1)
|
|
||||||
}
|
|
||||||
feMul(&t1, z, &t1)
|
|
||||||
feMul(&t0, &t0, &t1)
|
|
||||||
feSquare(&t2, &t0)
|
|
||||||
for i = 1; i < 1; i++ {
|
|
||||||
feSquare(&t2, &t2)
|
|
||||||
}
|
|
||||||
feMul(&t1, &t1, &t2)
|
|
||||||
feSquare(&t2, &t1)
|
|
||||||
for i = 1; i < 5; i++ {
|
|
||||||
feSquare(&t2, &t2)
|
|
||||||
}
|
|
||||||
feMul(&t1, &t2, &t1)
|
|
||||||
feSquare(&t2, &t1)
|
|
||||||
for i = 1; i < 10; i++ {
|
|
||||||
feSquare(&t2, &t2)
|
|
||||||
}
|
|
||||||
feMul(&t2, &t2, &t1)
|
|
||||||
feSquare(&t3, &t2)
|
|
||||||
for i = 1; i < 20; i++ {
|
|
||||||
feSquare(&t3, &t3)
|
|
||||||
}
|
|
||||||
feMul(&t2, &t3, &t2)
|
|
||||||
feSquare(&t2, &t2)
|
|
||||||
for i = 1; i < 10; i++ {
|
|
||||||
feSquare(&t2, &t2)
|
|
||||||
}
|
|
||||||
feMul(&t1, &t2, &t1)
|
|
||||||
feSquare(&t2, &t1)
|
|
||||||
for i = 1; i < 50; i++ {
|
|
||||||
feSquare(&t2, &t2)
|
|
||||||
}
|
|
||||||
feMul(&t2, &t2, &t1)
|
|
||||||
feSquare(&t3, &t2)
|
|
||||||
for i = 1; i < 100; i++ {
|
|
||||||
feSquare(&t3, &t3)
|
|
||||||
}
|
|
||||||
feMul(&t2, &t3, &t2)
|
|
||||||
feSquare(&t2, &t2)
|
|
||||||
for i = 1; i < 50; i++ {
|
|
||||||
feSquare(&t2, &t2)
|
|
||||||
}
|
|
||||||
feMul(&t1, &t2, &t1)
|
|
||||||
feSquare(&t1, &t1)
|
|
||||||
for i = 1; i < 5; i++ {
|
|
||||||
feSquare(&t1, &t1)
|
|
||||||
}
|
|
||||||
feMul(out, &t1, &t0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func scalarMult(out, in, base *[32]byte) {
|
|
||||||
var e [32]byte
|
|
||||||
|
|
||||||
copy(e[:], in[:])
|
|
||||||
e[0] &= 248
|
|
||||||
e[31] &= 127
|
|
||||||
e[31] |= 64
|
|
||||||
|
|
||||||
var x1, x2, z2, x3, z3, tmp0, tmp1 fieldElement
|
|
||||||
feFromBytes(&x1, base)
|
|
||||||
feOne(&x2)
|
|
||||||
feCopy(&x3, &x1)
|
|
||||||
feOne(&z3)
|
|
||||||
|
|
||||||
swap := int32(0)
|
|
||||||
for pos := 254; pos >= 0; pos-- {
|
|
||||||
b := e[pos/8] >> uint(pos&7)
|
|
||||||
b &= 1
|
|
||||||
swap ^= int32(b)
|
|
||||||
feCSwap(&x2, &x3, swap)
|
|
||||||
feCSwap(&z2, &z3, swap)
|
|
||||||
swap = int32(b)
|
|
||||||
|
|
||||||
feSub(&tmp0, &x3, &z3)
|
|
||||||
feSub(&tmp1, &x2, &z2)
|
|
||||||
feAdd(&x2, &x2, &z2)
|
|
||||||
feAdd(&z2, &x3, &z3)
|
|
||||||
feMul(&z3, &tmp0, &x2)
|
|
||||||
feMul(&z2, &z2, &tmp1)
|
|
||||||
feSquare(&tmp0, &tmp1)
|
|
||||||
feSquare(&tmp1, &x2)
|
|
||||||
feAdd(&x3, &z3, &z2)
|
|
||||||
feSub(&z2, &z3, &z2)
|
|
||||||
feMul(&x2, &tmp1, &tmp0)
|
|
||||||
feSub(&tmp1, &tmp1, &tmp0)
|
|
||||||
feSquare(&z2, &z2)
|
|
||||||
feMul121666(&z3, &tmp1)
|
|
||||||
feSquare(&x3, &x3)
|
|
||||||
feAdd(&tmp0, &tmp0, &z3)
|
|
||||||
feMul(&z3, &x1, &z2)
|
|
||||||
feMul(&z2, &tmp1, &tmp0)
|
|
||||||
}
|
|
||||||
|
|
||||||
feCSwap(&x2, &x3, swap)
|
|
||||||
feCSwap(&z2, &z3, swap)
|
|
||||||
|
|
||||||
feInvert(&z2, &z2)
|
|
||||||
feMul(&x2, &x2, &z2)
|
|
||||||
feToBytes(out, &x2)
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build amd64,!gccgo,!appengine
|
// +build amd64,!gccgo,!appengine,!purego
|
||||||
|
|
||||||
package curve25519
|
package curve25519
|
||||||
|
|
@ -5,9 +5,84 @@
|
|||||||
// This code was translated into a form compatible with 6a from the public
|
// This code was translated into a form compatible with 6a from the public
|
||||||
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
|
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
|
||||||
|
|
||||||
// +build amd64,!gccgo,!appengine
|
// +build amd64,!gccgo,!appengine,!purego
|
||||||
|
|
||||||
#include "const_amd64.h"
|
#define REDMASK51 0x0007FFFFFFFFFFFF
|
||||||
|
|
||||||
|
// These constants cannot be encoded in non-MOVQ immediates.
|
||||||
|
// We access them directly from memory instead.
|
||||||
|
|
||||||
|
DATA ·_121666_213(SB)/8, $996687872
|
||||||
|
GLOBL ·_121666_213(SB), 8, $8
|
||||||
|
|
||||||
|
DATA ·_2P0(SB)/8, $0xFFFFFFFFFFFDA
|
||||||
|
GLOBL ·_2P0(SB), 8, $8
|
||||||
|
|
||||||
|
DATA ·_2P1234(SB)/8, $0xFFFFFFFFFFFFE
|
||||||
|
GLOBL ·_2P1234(SB), 8, $8
|
||||||
|
|
||||||
|
// func freeze(inout *[5]uint64)
|
||||||
|
TEXT ·freeze(SB),7,$0-8
|
||||||
|
MOVQ inout+0(FP), DI
|
||||||
|
|
||||||
|
MOVQ 0(DI),SI
|
||||||
|
MOVQ 8(DI),DX
|
||||||
|
MOVQ 16(DI),CX
|
||||||
|
MOVQ 24(DI),R8
|
||||||
|
MOVQ 32(DI),R9
|
||||||
|
MOVQ $REDMASK51,AX
|
||||||
|
MOVQ AX,R10
|
||||||
|
SUBQ $18,R10
|
||||||
|
MOVQ $3,R11
|
||||||
|
REDUCELOOP:
|
||||||
|
MOVQ SI,R12
|
||||||
|
SHRQ $51,R12
|
||||||
|
ANDQ AX,SI
|
||||||
|
ADDQ R12,DX
|
||||||
|
MOVQ DX,R12
|
||||||
|
SHRQ $51,R12
|
||||||
|
ANDQ AX,DX
|
||||||
|
ADDQ R12,CX
|
||||||
|
MOVQ CX,R12
|
||||||
|
SHRQ $51,R12
|
||||||
|
ANDQ AX,CX
|
||||||
|
ADDQ R12,R8
|
||||||
|
MOVQ R8,R12
|
||||||
|
SHRQ $51,R12
|
||||||
|
ANDQ AX,R8
|
||||||
|
ADDQ R12,R9
|
||||||
|
MOVQ R9,R12
|
||||||
|
SHRQ $51,R12
|
||||||
|
ANDQ AX,R9
|
||||||
|
IMUL3Q $19,R12,R12
|
||||||
|
ADDQ R12,SI
|
||||||
|
SUBQ $1,R11
|
||||||
|
JA REDUCELOOP
|
||||||
|
MOVQ $1,R12
|
||||||
|
CMPQ R10,SI
|
||||||
|
CMOVQLT R11,R12
|
||||||
|
CMPQ AX,DX
|
||||||
|
CMOVQNE R11,R12
|
||||||
|
CMPQ AX,CX
|
||||||
|
CMOVQNE R11,R12
|
||||||
|
CMPQ AX,R8
|
||||||
|
CMOVQNE R11,R12
|
||||||
|
CMPQ AX,R9
|
||||||
|
CMOVQNE R11,R12
|
||||||
|
NEGQ R12
|
||||||
|
ANDQ R12,AX
|
||||||
|
ANDQ R12,R10
|
||||||
|
SUBQ R10,SI
|
||||||
|
SUBQ AX,DX
|
||||||
|
SUBQ AX,CX
|
||||||
|
SUBQ AX,R8
|
||||||
|
SUBQ AX,R9
|
||||||
|
MOVQ SI,0(DI)
|
||||||
|
MOVQ DX,8(DI)
|
||||||
|
MOVQ CX,16(DI)
|
||||||
|
MOVQ R8,24(DI)
|
||||||
|
MOVQ R9,32(DI)
|
||||||
|
RET
|
||||||
|
|
||||||
// func ladderstep(inout *[5][5]uint64)
|
// func ladderstep(inout *[5][5]uint64)
|
||||||
TEXT ·ladderstep(SB),0,$296-8
|
TEXT ·ladderstep(SB),0,$296-8
|
||||||
@ -1375,3 +1450,344 @@ TEXT ·ladderstep(SB),0,$296-8
|
|||||||
MOVQ AX,104(DI)
|
MOVQ AX,104(DI)
|
||||||
MOVQ R10,112(DI)
|
MOVQ R10,112(DI)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
// func cswap(inout *[4][5]uint64, v uint64)
|
||||||
|
TEXT ·cswap(SB),7,$0
|
||||||
|
MOVQ inout+0(FP),DI
|
||||||
|
MOVQ v+8(FP),SI
|
||||||
|
|
||||||
|
SUBQ $1, SI
|
||||||
|
NOTQ SI
|
||||||
|
MOVQ SI, X15
|
||||||
|
PSHUFD $0x44, X15, X15
|
||||||
|
|
||||||
|
MOVOU 0(DI), X0
|
||||||
|
MOVOU 16(DI), X2
|
||||||
|
MOVOU 32(DI), X4
|
||||||
|
MOVOU 48(DI), X6
|
||||||
|
MOVOU 64(DI), X8
|
||||||
|
MOVOU 80(DI), X1
|
||||||
|
MOVOU 96(DI), X3
|
||||||
|
MOVOU 112(DI), X5
|
||||||
|
MOVOU 128(DI), X7
|
||||||
|
MOVOU 144(DI), X9
|
||||||
|
|
||||||
|
MOVO X1, X10
|
||||||
|
MOVO X3, X11
|
||||||
|
MOVO X5, X12
|
||||||
|
MOVO X7, X13
|
||||||
|
MOVO X9, X14
|
||||||
|
|
||||||
|
PXOR X0, X10
|
||||||
|
PXOR X2, X11
|
||||||
|
PXOR X4, X12
|
||||||
|
PXOR X6, X13
|
||||||
|
PXOR X8, X14
|
||||||
|
PAND X15, X10
|
||||||
|
PAND X15, X11
|
||||||
|
PAND X15, X12
|
||||||
|
PAND X15, X13
|
||||||
|
PAND X15, X14
|
||||||
|
PXOR X10, X0
|
||||||
|
PXOR X10, X1
|
||||||
|
PXOR X11, X2
|
||||||
|
PXOR X11, X3
|
||||||
|
PXOR X12, X4
|
||||||
|
PXOR X12, X5
|
||||||
|
PXOR X13, X6
|
||||||
|
PXOR X13, X7
|
||||||
|
PXOR X14, X8
|
||||||
|
PXOR X14, X9
|
||||||
|
|
||||||
|
MOVOU X0, 0(DI)
|
||||||
|
MOVOU X2, 16(DI)
|
||||||
|
MOVOU X4, 32(DI)
|
||||||
|
MOVOU X6, 48(DI)
|
||||||
|
MOVOU X8, 64(DI)
|
||||||
|
MOVOU X1, 80(DI)
|
||||||
|
MOVOU X3, 96(DI)
|
||||||
|
MOVOU X5, 112(DI)
|
||||||
|
MOVOU X7, 128(DI)
|
||||||
|
MOVOU X9, 144(DI)
|
||||||
|
RET
|
||||||
|
|
||||||
|
// func mul(dest, a, b *[5]uint64)
|
||||||
|
TEXT ·mul(SB),0,$16-24
|
||||||
|
MOVQ dest+0(FP), DI
|
||||||
|
MOVQ a+8(FP), SI
|
||||||
|
MOVQ b+16(FP), DX
|
||||||
|
|
||||||
|
MOVQ DX,CX
|
||||||
|
MOVQ 24(SI),DX
|
||||||
|
IMUL3Q $19,DX,AX
|
||||||
|
MOVQ AX,0(SP)
|
||||||
|
MULQ 16(CX)
|
||||||
|
MOVQ AX,R8
|
||||||
|
MOVQ DX,R9
|
||||||
|
MOVQ 32(SI),DX
|
||||||
|
IMUL3Q $19,DX,AX
|
||||||
|
MOVQ AX,8(SP)
|
||||||
|
MULQ 8(CX)
|
||||||
|
ADDQ AX,R8
|
||||||
|
ADCQ DX,R9
|
||||||
|
MOVQ 0(SI),AX
|
||||||
|
MULQ 0(CX)
|
||||||
|
ADDQ AX,R8
|
||||||
|
ADCQ DX,R9
|
||||||
|
MOVQ 0(SI),AX
|
||||||
|
MULQ 8(CX)
|
||||||
|
MOVQ AX,R10
|
||||||
|
MOVQ DX,R11
|
||||||
|
MOVQ 0(SI),AX
|
||||||
|
MULQ 16(CX)
|
||||||
|
MOVQ AX,R12
|
||||||
|
MOVQ DX,R13
|
||||||
|
MOVQ 0(SI),AX
|
||||||
|
MULQ 24(CX)
|
||||||
|
MOVQ AX,R14
|
||||||
|
MOVQ DX,R15
|
||||||
|
MOVQ 0(SI),AX
|
||||||
|
MULQ 32(CX)
|
||||||
|
MOVQ AX,BX
|
||||||
|
MOVQ DX,BP
|
||||||
|
MOVQ 8(SI),AX
|
||||||
|
MULQ 0(CX)
|
||||||
|
ADDQ AX,R10
|
||||||
|
ADCQ DX,R11
|
||||||
|
MOVQ 8(SI),AX
|
||||||
|
MULQ 8(CX)
|
||||||
|
ADDQ AX,R12
|
||||||
|
ADCQ DX,R13
|
||||||
|
MOVQ 8(SI),AX
|
||||||
|
MULQ 16(CX)
|
||||||
|
ADDQ AX,R14
|
||||||
|
ADCQ DX,R15
|
||||||
|
MOVQ 8(SI),AX
|
||||||
|
MULQ 24(CX)
|
||||||
|
ADDQ AX,BX
|
||||||
|
ADCQ DX,BP
|
||||||
|
MOVQ 8(SI),DX
|
||||||
|
IMUL3Q $19,DX,AX
|
||||||
|
MULQ 32(CX)
|
||||||
|
ADDQ AX,R8
|
||||||
|
ADCQ DX,R9
|
||||||
|
MOVQ 16(SI),AX
|
||||||
|
MULQ 0(CX)
|
||||||
|
ADDQ AX,R12
|
||||||
|
ADCQ DX,R13
|
||||||
|
MOVQ 16(SI),AX
|
||||||
|
MULQ 8(CX)
|
||||||
|
ADDQ AX,R14
|
||||||
|
ADCQ DX,R15
|
||||||
|
MOVQ 16(SI),AX
|
||||||
|
MULQ 16(CX)
|
||||||
|
ADDQ AX,BX
|
||||||
|
ADCQ DX,BP
|
||||||
|
MOVQ 16(SI),DX
|
||||||
|
IMUL3Q $19,DX,AX
|
||||||
|
MULQ 24(CX)
|
||||||
|
ADDQ AX,R8
|
||||||
|
ADCQ DX,R9
|
||||||
|
MOVQ 16(SI),DX
|
||||||
|
IMUL3Q $19,DX,AX
|
||||||
|
MULQ 32(CX)
|
||||||
|
ADDQ AX,R10
|
||||||
|
ADCQ DX,R11
|
||||||
|
MOVQ 24(SI),AX
|
||||||
|
MULQ 0(CX)
|
||||||
|
ADDQ AX,R14
|
||||||
|
ADCQ DX,R15
|
||||||
|
MOVQ 24(SI),AX
|
||||||
|
MULQ 8(CX)
|
||||||
|
ADDQ AX,BX
|
||||||
|
ADCQ DX,BP
|
||||||
|
MOVQ 0(SP),AX
|
||||||
|
MULQ 24(CX)
|
||||||
|
ADDQ AX,R10
|
||||||
|
ADCQ DX,R11
|
||||||
|
MOVQ 0(SP),AX
|
||||||
|
MULQ 32(CX)
|
||||||
|
ADDQ AX,R12
|
||||||
|
ADCQ DX,R13
|
||||||
|
MOVQ 32(SI),AX
|
||||||
|
MULQ 0(CX)
|
||||||
|
ADDQ AX,BX
|
||||||
|
ADCQ DX,BP
|
||||||
|
MOVQ 8(SP),AX
|
||||||
|
MULQ 16(CX)
|
||||||
|
ADDQ AX,R10
|
||||||
|
ADCQ DX,R11
|
||||||
|
MOVQ 8(SP),AX
|
||||||
|
MULQ 24(CX)
|
||||||
|
ADDQ AX,R12
|
||||||
|
ADCQ DX,R13
|
||||||
|
MOVQ 8(SP),AX
|
||||||
|
MULQ 32(CX)
|
||||||
|
ADDQ AX,R14
|
||||||
|
ADCQ DX,R15
|
||||||
|
MOVQ $REDMASK51,SI
|
||||||
|
SHLQ $13,R8,R9
|
||||||
|
ANDQ SI,R8
|
||||||
|
SHLQ $13,R10,R11
|
||||||
|
ANDQ SI,R10
|
||||||
|
ADDQ R9,R10
|
||||||
|
SHLQ $13,R12,R13
|
||||||
|
ANDQ SI,R12
|
||||||
|
ADDQ R11,R12
|
||||||
|
SHLQ $13,R14,R15
|
||||||
|
ANDQ SI,R14
|
||||||
|
ADDQ R13,R14
|
||||||
|
SHLQ $13,BX,BP
|
||||||
|
ANDQ SI,BX
|
||||||
|
ADDQ R15,BX
|
||||||
|
IMUL3Q $19,BP,DX
|
||||||
|
ADDQ DX,R8
|
||||||
|
MOVQ R8,DX
|
||||||
|
SHRQ $51,DX
|
||||||
|
ADDQ R10,DX
|
||||||
|
MOVQ DX,CX
|
||||||
|
SHRQ $51,DX
|
||||||
|
ANDQ SI,R8
|
||||||
|
ADDQ R12,DX
|
||||||
|
MOVQ DX,R9
|
||||||
|
SHRQ $51,DX
|
||||||
|
ANDQ SI,CX
|
||||||
|
ADDQ R14,DX
|
||||||
|
MOVQ DX,AX
|
||||||
|
SHRQ $51,DX
|
||||||
|
ANDQ SI,R9
|
||||||
|
ADDQ BX,DX
|
||||||
|
MOVQ DX,R10
|
||||||
|
SHRQ $51,DX
|
||||||
|
ANDQ SI,AX
|
||||||
|
IMUL3Q $19,DX,DX
|
||||||
|
ADDQ DX,R8
|
||||||
|
ANDQ SI,R10
|
||||||
|
MOVQ R8,0(DI)
|
||||||
|
MOVQ CX,8(DI)
|
||||||
|
MOVQ R9,16(DI)
|
||||||
|
MOVQ AX,24(DI)
|
||||||
|
MOVQ R10,32(DI)
|
||||||
|
RET
|
||||||
|
|
||||||
|
// func square(out, in *[5]uint64)
|
||||||
|
TEXT ·square(SB),7,$0-16
|
||||||
|
MOVQ out+0(FP), DI
|
||||||
|
MOVQ in+8(FP), SI
|
||||||
|
|
||||||
|
MOVQ 0(SI),AX
|
||||||
|
MULQ 0(SI)
|
||||||
|
MOVQ AX,CX
|
||||||
|
MOVQ DX,R8
|
||||||
|
MOVQ 0(SI),AX
|
||||||
|
SHLQ $1,AX
|
||||||
|
MULQ 8(SI)
|
||||||
|
MOVQ AX,R9
|
||||||
|
MOVQ DX,R10
|
||||||
|
MOVQ 0(SI),AX
|
||||||
|
SHLQ $1,AX
|
||||||
|
MULQ 16(SI)
|
||||||
|
MOVQ AX,R11
|
||||||
|
MOVQ DX,R12
|
||||||
|
MOVQ 0(SI),AX
|
||||||
|
SHLQ $1,AX
|
||||||
|
MULQ 24(SI)
|
||||||
|
MOVQ AX,R13
|
||||||
|
MOVQ DX,R14
|
||||||
|
MOVQ 0(SI),AX
|
||||||
|
SHLQ $1,AX
|
||||||
|
MULQ 32(SI)
|
||||||
|
MOVQ AX,R15
|
||||||
|
MOVQ DX,BX
|
||||||
|
MOVQ 8(SI),AX
|
||||||
|
MULQ 8(SI)
|
||||||
|
ADDQ AX,R11
|
||||||
|
ADCQ DX,R12
|
||||||
|
MOVQ 8(SI),AX
|
||||||
|
SHLQ $1,AX
|
||||||
|
MULQ 16(SI)
|
||||||
|
ADDQ AX,R13
|
||||||
|
ADCQ DX,R14
|
||||||
|
MOVQ 8(SI),AX
|
||||||
|
SHLQ $1,AX
|
||||||
|
MULQ 24(SI)
|
||||||
|
ADDQ AX,R15
|
||||||
|
ADCQ DX,BX
|
||||||
|
MOVQ 8(SI),DX
|
||||||
|
IMUL3Q $38,DX,AX
|
||||||
|
MULQ 32(SI)
|
||||||
|
ADDQ AX,CX
|
||||||
|
ADCQ DX,R8
|
||||||
|
MOVQ 16(SI),AX
|
||||||
|
MULQ 16(SI)
|
||||||
|
ADDQ AX,R15
|
||||||
|
ADCQ DX,BX
|
||||||
|
MOVQ 16(SI),DX
|
||||||
|
IMUL3Q $38,DX,AX
|
||||||
|
MULQ 24(SI)
|
||||||
|
ADDQ AX,CX
|
||||||
|
ADCQ DX,R8
|
||||||
|
MOVQ 16(SI),DX
|
||||||
|
IMUL3Q $38,DX,AX
|
||||||
|
MULQ 32(SI)
|
||||||
|
ADDQ AX,R9
|
||||||
|
ADCQ DX,R10
|
||||||
|
MOVQ 24(SI),DX
|
||||||
|
IMUL3Q $19,DX,AX
|
||||||
|
MULQ 24(SI)
|
||||||
|
ADDQ AX,R9
|
||||||
|
ADCQ DX,R10
|
||||||
|
MOVQ 24(SI),DX
|
||||||
|
IMUL3Q $38,DX,AX
|
||||||
|
MULQ 32(SI)
|
||||||
|
ADDQ AX,R11
|
||||||
|
ADCQ DX,R12
|
||||||
|
MOVQ 32(SI),DX
|
||||||
|
IMUL3Q $19,DX,AX
|
||||||
|
MULQ 32(SI)
|
||||||
|
ADDQ AX,R13
|
||||||
|
ADCQ DX,R14
|
||||||
|
MOVQ $REDMASK51,SI
|
||||||
|
SHLQ $13,CX,R8
|
||||||
|
ANDQ SI,CX
|
||||||
|
SHLQ $13,R9,R10
|
||||||
|
ANDQ SI,R9
|
||||||
|
ADDQ R8,R9
|
||||||
|
SHLQ $13,R11,R12
|
||||||
|
ANDQ SI,R11
|
||||||
|
ADDQ R10,R11
|
||||||
|
SHLQ $13,R13,R14
|
||||||
|
ANDQ SI,R13
|
||||||
|
ADDQ R12,R13
|
||||||
|
SHLQ $13,R15,BX
|
||||||
|
ANDQ SI,R15
|
||||||
|
ADDQ R14,R15
|
||||||
|
IMUL3Q $19,BX,DX
|
||||||
|
ADDQ DX,CX
|
||||||
|
MOVQ CX,DX
|
||||||
|
SHRQ $51,DX
|
||||||
|
ADDQ R9,DX
|
||||||
|
ANDQ SI,CX
|
||||||
|
MOVQ DX,R8
|
||||||
|
SHRQ $51,DX
|
||||||
|
ADDQ R11,DX
|
||||||
|
ANDQ SI,R8
|
||||||
|
MOVQ DX,R9
|
||||||
|
SHRQ $51,DX
|
||||||
|
ADDQ R13,DX
|
||||||
|
ANDQ SI,R9
|
||||||
|
MOVQ DX,AX
|
||||||
|
SHRQ $51,DX
|
||||||
|
ADDQ R15,DX
|
||||||
|
ANDQ SI,AX
|
||||||
|
MOVQ DX,R10
|
||||||
|
SHRQ $51,DX
|
||||||
|
IMUL3Q $19,DX,DX
|
||||||
|
ADDQ DX,CX
|
||||||
|
ANDQ SI,R10
|
||||||
|
MOVQ CX,0(DI)
|
||||||
|
MOVQ R8,8(DI)
|
||||||
|
MOVQ R9,16(DI)
|
||||||
|
MOVQ AX,24(DI)
|
||||||
|
MOVQ R10,32(DI)
|
||||||
|
RET
|
828
vendor/golang.org/x/crypto/curve25519/curve25519_generic.go
generated
vendored
Normal file
828
vendor/golang.org/x/crypto/curve25519/curve25519_generic.go
generated
vendored
Normal file
@ -0,0 +1,828 @@
|
|||||||
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package curve25519
|
||||||
|
|
||||||
|
import "encoding/binary"
|
||||||
|
|
||||||
|
// This code is a port of the public domain, "ref10" implementation of
|
||||||
|
// curve25519 from SUPERCOP 20130419 by D. J. Bernstein.
|
||||||
|
|
||||||
|
// fieldElement represents an element of the field GF(2^255 - 19). An element
|
||||||
|
// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
|
||||||
|
// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
|
||||||
|
// context.
|
||||||
|
type fieldElement [10]int32
|
||||||
|
|
||||||
|
func feZero(fe *fieldElement) {
|
||||||
|
for i := range fe {
|
||||||
|
fe[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func feOne(fe *fieldElement) {
|
||||||
|
feZero(fe)
|
||||||
|
fe[0] = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func feAdd(dst, a, b *fieldElement) {
|
||||||
|
for i := range dst {
|
||||||
|
dst[i] = a[i] + b[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func feSub(dst, a, b *fieldElement) {
|
||||||
|
for i := range dst {
|
||||||
|
dst[i] = a[i] - b[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func feCopy(dst, src *fieldElement) {
|
||||||
|
for i := range dst {
|
||||||
|
dst[i] = src[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// feCSwap replaces (f,g) with (g,f) if b == 1; replaces (f,g) with (f,g) if b == 0.
|
||||||
|
//
|
||||||
|
// Preconditions: b in {0,1}.
|
||||||
|
func feCSwap(f, g *fieldElement, b int32) {
|
||||||
|
b = -b
|
||||||
|
for i := range f {
|
||||||
|
t := b & (f[i] ^ g[i])
|
||||||
|
f[i] ^= t
|
||||||
|
g[i] ^= t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// load3 reads a 24-bit, little-endian value from in.
|
||||||
|
func load3(in []byte) int64 {
|
||||||
|
var r int64
|
||||||
|
r = int64(in[0])
|
||||||
|
r |= int64(in[1]) << 8
|
||||||
|
r |= int64(in[2]) << 16
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// load4 reads a 32-bit, little-endian value from in.
|
||||||
|
func load4(in []byte) int64 {
|
||||||
|
return int64(binary.LittleEndian.Uint32(in))
|
||||||
|
}
|
||||||
|
|
||||||
|
func feFromBytes(dst *fieldElement, src *[32]byte) {
|
||||||
|
h0 := load4(src[:])
|
||||||
|
h1 := load3(src[4:]) << 6
|
||||||
|
h2 := load3(src[7:]) << 5
|
||||||
|
h3 := load3(src[10:]) << 3
|
||||||
|
h4 := load3(src[13:]) << 2
|
||||||
|
h5 := load4(src[16:])
|
||||||
|
h6 := load3(src[20:]) << 7
|
||||||
|
h7 := load3(src[23:]) << 5
|
||||||
|
h8 := load3(src[26:]) << 4
|
||||||
|
h9 := (load3(src[29:]) & 0x7fffff) << 2
|
||||||
|
|
||||||
|
var carry [10]int64
|
||||||
|
carry[9] = (h9 + 1<<24) >> 25
|
||||||
|
h0 += carry[9] * 19
|
||||||
|
h9 -= carry[9] << 25
|
||||||
|
carry[1] = (h1 + 1<<24) >> 25
|
||||||
|
h2 += carry[1]
|
||||||
|
h1 -= carry[1] << 25
|
||||||
|
carry[3] = (h3 + 1<<24) >> 25
|
||||||
|
h4 += carry[3]
|
||||||
|
h3 -= carry[3] << 25
|
||||||
|
carry[5] = (h5 + 1<<24) >> 25
|
||||||
|
h6 += carry[5]
|
||||||
|
h5 -= carry[5] << 25
|
||||||
|
carry[7] = (h7 + 1<<24) >> 25
|
||||||
|
h8 += carry[7]
|
||||||
|
h7 -= carry[7] << 25
|
||||||
|
|
||||||
|
carry[0] = (h0 + 1<<25) >> 26
|
||||||
|
h1 += carry[0]
|
||||||
|
h0 -= carry[0] << 26
|
||||||
|
carry[2] = (h2 + 1<<25) >> 26
|
||||||
|
h3 += carry[2]
|
||||||
|
h2 -= carry[2] << 26
|
||||||
|
carry[4] = (h4 + 1<<25) >> 26
|
||||||
|
h5 += carry[4]
|
||||||
|
h4 -= carry[4] << 26
|
||||||
|
carry[6] = (h6 + 1<<25) >> 26
|
||||||
|
h7 += carry[6]
|
||||||
|
h6 -= carry[6] << 26
|
||||||
|
carry[8] = (h8 + 1<<25) >> 26
|
||||||
|
h9 += carry[8]
|
||||||
|
h8 -= carry[8] << 26
|
||||||
|
|
||||||
|
dst[0] = int32(h0)
|
||||||
|
dst[1] = int32(h1)
|
||||||
|
dst[2] = int32(h2)
|
||||||
|
dst[3] = int32(h3)
|
||||||
|
dst[4] = int32(h4)
|
||||||
|
dst[5] = int32(h5)
|
||||||
|
dst[6] = int32(h6)
|
||||||
|
dst[7] = int32(h7)
|
||||||
|
dst[8] = int32(h8)
|
||||||
|
dst[9] = int32(h9)
|
||||||
|
}
|
||||||
|
|
||||||
|
// feToBytes marshals h to s.
|
||||||
|
// Preconditions:
|
||||||
|
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
|
||||||
|
//
|
||||||
|
// Write p=2^255-19; q=floor(h/p).
|
||||||
|
// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
|
||||||
|
//
|
||||||
|
// Proof:
|
||||||
|
// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
|
||||||
|
// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4.
|
||||||
|
//
|
||||||
|
// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
|
||||||
|
// Then 0<y<1.
|
||||||
|
//
|
||||||
|
// Write r=h-pq.
|
||||||
|
// Have 0<=r<=p-1=2^255-20.
|
||||||
|
// Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
|
||||||
|
//
|
||||||
|
// Write x=r+19(2^-255)r+y.
|
||||||
|
// Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
|
||||||
|
//
|
||||||
|
// Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
|
||||||
|
// so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q.
|
||||||
|
func feToBytes(s *[32]byte, h *fieldElement) {
|
||||||
|
var carry [10]int32
|
||||||
|
|
||||||
|
q := (19*h[9] + (1 << 24)) >> 25
|
||||||
|
q = (h[0] + q) >> 26
|
||||||
|
q = (h[1] + q) >> 25
|
||||||
|
q = (h[2] + q) >> 26
|
||||||
|
q = (h[3] + q) >> 25
|
||||||
|
q = (h[4] + q) >> 26
|
||||||
|
q = (h[5] + q) >> 25
|
||||||
|
q = (h[6] + q) >> 26
|
||||||
|
q = (h[7] + q) >> 25
|
||||||
|
q = (h[8] + q) >> 26
|
||||||
|
q = (h[9] + q) >> 25
|
||||||
|
|
||||||
|
// Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20.
|
||||||
|
h[0] += 19 * q
|
||||||
|
// Goal: Output h-2^255 q, which is between 0 and 2^255-20.
|
||||||
|
|
||||||
|
carry[0] = h[0] >> 26
|
||||||
|
h[1] += carry[0]
|
||||||
|
h[0] -= carry[0] << 26
|
||||||
|
carry[1] = h[1] >> 25
|
||||||
|
h[2] += carry[1]
|
||||||
|
h[1] -= carry[1] << 25
|
||||||
|
carry[2] = h[2] >> 26
|
||||||
|
h[3] += carry[2]
|
||||||
|
h[2] -= carry[2] << 26
|
||||||
|
carry[3] = h[3] >> 25
|
||||||
|
h[4] += carry[3]
|
||||||
|
h[3] -= carry[3] << 25
|
||||||
|
carry[4] = h[4] >> 26
|
||||||
|
h[5] += carry[4]
|
||||||
|
h[4] -= carry[4] << 26
|
||||||
|
carry[5] = h[5] >> 25
|
||||||
|
h[6] += carry[5]
|
||||||
|
h[5] -= carry[5] << 25
|
||||||
|
carry[6] = h[6] >> 26
|
||||||
|
h[7] += carry[6]
|
||||||
|
h[6] -= carry[6] << 26
|
||||||
|
carry[7] = h[7] >> 25
|
||||||
|
h[8] += carry[7]
|
||||||
|
h[7] -= carry[7] << 25
|
||||||
|
carry[8] = h[8] >> 26
|
||||||
|
h[9] += carry[8]
|
||||||
|
h[8] -= carry[8] << 26
|
||||||
|
carry[9] = h[9] >> 25
|
||||||
|
h[9] -= carry[9] << 25
|
||||||
|
// h10 = carry9
|
||||||
|
|
||||||
|
// Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
|
||||||
|
// Have h[0]+...+2^230 h[9] between 0 and 2^255-1;
|
||||||
|
// evidently 2^255 h10-2^255 q = 0.
|
||||||
|
// Goal: Output h[0]+...+2^230 h[9].
|
||||||
|
|
||||||
|
s[0] = byte(h[0] >> 0)
|
||||||
|
s[1] = byte(h[0] >> 8)
|
||||||
|
s[2] = byte(h[0] >> 16)
|
||||||
|
s[3] = byte((h[0] >> 24) | (h[1] << 2))
|
||||||
|
s[4] = byte(h[1] >> 6)
|
||||||
|
s[5] = byte(h[1] >> 14)
|
||||||
|
s[6] = byte((h[1] >> 22) | (h[2] << 3))
|
||||||
|
s[7] = byte(h[2] >> 5)
|
||||||
|
s[8] = byte(h[2] >> 13)
|
||||||
|
s[9] = byte((h[2] >> 21) | (h[3] << 5))
|
||||||
|
s[10] = byte(h[3] >> 3)
|
||||||
|
s[11] = byte(h[3] >> 11)
|
||||||
|
s[12] = byte((h[3] >> 19) | (h[4] << 6))
|
||||||
|
s[13] = byte(h[4] >> 2)
|
||||||
|
s[14] = byte(h[4] >> 10)
|
||||||
|
s[15] = byte(h[4] >> 18)
|
||||||
|
s[16] = byte(h[5] >> 0)
|
||||||
|
s[17] = byte(h[5] >> 8)
|
||||||
|
s[18] = byte(h[5] >> 16)
|
||||||
|
s[19] = byte((h[5] >> 24) | (h[6] << 1))
|
||||||
|
s[20] = byte(h[6] >> 7)
|
||||||
|
s[21] = byte(h[6] >> 15)
|
||||||
|
s[22] = byte((h[6] >> 23) | (h[7] << 3))
|
||||||
|
s[23] = byte(h[7] >> 5)
|
||||||
|
s[24] = byte(h[7] >> 13)
|
||||||
|
s[25] = byte((h[7] >> 21) | (h[8] << 4))
|
||||||
|
s[26] = byte(h[8] >> 4)
|
||||||
|
s[27] = byte(h[8] >> 12)
|
||||||
|
s[28] = byte((h[8] >> 20) | (h[9] << 6))
|
||||||
|
s[29] = byte(h[9] >> 2)
|
||||||
|
s[30] = byte(h[9] >> 10)
|
||||||
|
s[31] = byte(h[9] >> 18)
|
||||||
|
}
|
||||||
|
|
||||||
|
// feMul calculates h = f * g
|
||||||
|
// Can overlap h with f or g.
|
||||||
|
//
|
||||||
|
// Preconditions:
|
||||||
|
// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
|
||||||
|
// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
|
||||||
|
//
|
||||||
|
// Postconditions:
|
||||||
|
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
|
||||||
|
//
|
||||||
|
// Notes on implementation strategy:
|
||||||
|
//
|
||||||
|
// Using schoolbook multiplication.
|
||||||
|
// Karatsuba would save a little in some cost models.
|
||||||
|
//
|
||||||
|
// Most multiplications by 2 and 19 are 32-bit precomputations;
|
||||||
|
// cheaper than 64-bit postcomputations.
|
||||||
|
//
|
||||||
|
// There is one remaining multiplication by 19 in the carry chain;
|
||||||
|
// one *19 precomputation can be merged into this,
|
||||||
|
// but the resulting data flow is considerably less clean.
|
||||||
|
//
|
||||||
|
// There are 12 carries below.
|
||||||
|
// 10 of them are 2-way parallelizable and vectorizable.
|
||||||
|
// Can get away with 11 carries, but then data flow is much deeper.
|
||||||
|
//
|
||||||
|
// With tighter constraints on inputs can squeeze carries into int32.
|
||||||
|
func feMul(h, f, g *fieldElement) {
|
||||||
|
f0 := f[0]
|
||||||
|
f1 := f[1]
|
||||||
|
f2 := f[2]
|
||||||
|
f3 := f[3]
|
||||||
|
f4 := f[4]
|
||||||
|
f5 := f[5]
|
||||||
|
f6 := f[6]
|
||||||
|
f7 := f[7]
|
||||||
|
f8 := f[8]
|
||||||
|
f9 := f[9]
|
||||||
|
g0 := g[0]
|
||||||
|
g1 := g[1]
|
||||||
|
g2 := g[2]
|
||||||
|
g3 := g[3]
|
||||||
|
g4 := g[4]
|
||||||
|
g5 := g[5]
|
||||||
|
g6 := g[6]
|
||||||
|
g7 := g[7]
|
||||||
|
g8 := g[8]
|
||||||
|
g9 := g[9]
|
||||||
|
g1_19 := 19 * g1 // 1.4*2^29
|
||||||
|
g2_19 := 19 * g2 // 1.4*2^30; still ok
|
||||||
|
g3_19 := 19 * g3
|
||||||
|
g4_19 := 19 * g4
|
||||||
|
g5_19 := 19 * g5
|
||||||
|
g6_19 := 19 * g6
|
||||||
|
g7_19 := 19 * g7
|
||||||
|
g8_19 := 19 * g8
|
||||||
|
g9_19 := 19 * g9
|
||||||
|
f1_2 := 2 * f1
|
||||||
|
f3_2 := 2 * f3
|
||||||
|
f5_2 := 2 * f5
|
||||||
|
f7_2 := 2 * f7
|
||||||
|
f9_2 := 2 * f9
|
||||||
|
f0g0 := int64(f0) * int64(g0)
|
||||||
|
f0g1 := int64(f0) * int64(g1)
|
||||||
|
f0g2 := int64(f0) * int64(g2)
|
||||||
|
f0g3 := int64(f0) * int64(g3)
|
||||||
|
f0g4 := int64(f0) * int64(g4)
|
||||||
|
f0g5 := int64(f0) * int64(g5)
|
||||||
|
f0g6 := int64(f0) * int64(g6)
|
||||||
|
f0g7 := int64(f0) * int64(g7)
|
||||||
|
f0g8 := int64(f0) * int64(g8)
|
||||||
|
f0g9 := int64(f0) * int64(g9)
|
||||||
|
f1g0 := int64(f1) * int64(g0)
|
||||||
|
f1g1_2 := int64(f1_2) * int64(g1)
|
||||||
|
f1g2 := int64(f1) * int64(g2)
|
||||||
|
f1g3_2 := int64(f1_2) * int64(g3)
|
||||||
|
f1g4 := int64(f1) * int64(g4)
|
||||||
|
f1g5_2 := int64(f1_2) * int64(g5)
|
||||||
|
f1g6 := int64(f1) * int64(g6)
|
||||||
|
f1g7_2 := int64(f1_2) * int64(g7)
|
||||||
|
f1g8 := int64(f1) * int64(g8)
|
||||||
|
f1g9_38 := int64(f1_2) * int64(g9_19)
|
||||||
|
f2g0 := int64(f2) * int64(g0)
|
||||||
|
f2g1 := int64(f2) * int64(g1)
|
||||||
|
f2g2 := int64(f2) * int64(g2)
|
||||||
|
f2g3 := int64(f2) * int64(g3)
|
||||||
|
f2g4 := int64(f2) * int64(g4)
|
||||||
|
f2g5 := int64(f2) * int64(g5)
|
||||||
|
f2g6 := int64(f2) * int64(g6)
|
||||||
|
f2g7 := int64(f2) * int64(g7)
|
||||||
|
f2g8_19 := int64(f2) * int64(g8_19)
|
||||||
|
f2g9_19 := int64(f2) * int64(g9_19)
|
||||||
|
f3g0 := int64(f3) * int64(g0)
|
||||||
|
f3g1_2 := int64(f3_2) * int64(g1)
|
||||||
|
f3g2 := int64(f3) * int64(g2)
|
||||||
|
f3g3_2 := int64(f3_2) * int64(g3)
|
||||||
|
f3g4 := int64(f3) * int64(g4)
|
||||||
|
f3g5_2 := int64(f3_2) * int64(g5)
|
||||||
|
f3g6 := int64(f3) * int64(g6)
|
||||||
|
f3g7_38 := int64(f3_2) * int64(g7_19)
|
||||||
|
f3g8_19 := int64(f3) * int64(g8_19)
|
||||||
|
f3g9_38 := int64(f3_2) * int64(g9_19)
|
||||||
|
f4g0 := int64(f4) * int64(g0)
|
||||||
|
f4g1 := int64(f4) * int64(g1)
|
||||||
|
f4g2 := int64(f4) * int64(g2)
|
||||||
|
f4g3 := int64(f4) * int64(g3)
|
||||||
|
f4g4 := int64(f4) * int64(g4)
|
||||||
|
f4g5 := int64(f4) * int64(g5)
|
||||||
|
f4g6_19 := int64(f4) * int64(g6_19)
|
||||||
|
f4g7_19 := int64(f4) * int64(g7_19)
|
||||||
|
f4g8_19 := int64(f4) * int64(g8_19)
|
||||||
|
f4g9_19 := int64(f4) * int64(g9_19)
|
||||||
|
f5g0 := int64(f5) * int64(g0)
|
||||||
|
f5g1_2 := int64(f5_2) * int64(g1)
|
||||||
|
f5g2 := int64(f5) * int64(g2)
|
||||||
|
f5g3_2 := int64(f5_2) * int64(g3)
|
||||||
|
f5g4 := int64(f5) * int64(g4)
|
||||||
|
f5g5_38 := int64(f5_2) * int64(g5_19)
|
||||||
|
f5g6_19 := int64(f5) * int64(g6_19)
|
||||||
|
f5g7_38 := int64(f5_2) * int64(g7_19)
|
||||||
|
f5g8_19 := int64(f5) * int64(g8_19)
|
||||||
|
f5g9_38 := int64(f5_2) * int64(g9_19)
|
||||||
|
f6g0 := int64(f6) * int64(g0)
|
||||||
|
f6g1 := int64(f6) * int64(g1)
|
||||||
|
f6g2 := int64(f6) * int64(g2)
|
||||||
|
f6g3 := int64(f6) * int64(g3)
|
||||||
|
f6g4_19 := int64(f6) * int64(g4_19)
|
||||||
|
f6g5_19 := int64(f6) * int64(g5_19)
|
||||||
|
f6g6_19 := int64(f6) * int64(g6_19)
|
||||||
|
f6g7_19 := int64(f6) * int64(g7_19)
|
||||||
|
f6g8_19 := int64(f6) * int64(g8_19)
|
||||||
|
f6g9_19 := int64(f6) * int64(g9_19)
|
||||||
|
f7g0 := int64(f7) * int64(g0)
|
||||||
|
f7g1_2 := int64(f7_2) * int64(g1)
|
||||||
|
f7g2 := int64(f7) * int64(g2)
|
||||||
|
f7g3_38 := int64(f7_2) * int64(g3_19)
|
||||||
|
f7g4_19 := int64(f7) * int64(g4_19)
|
||||||
|
f7g5_38 := int64(f7_2) * int64(g5_19)
|
||||||
|
f7g6_19 := int64(f7) * int64(g6_19)
|
||||||
|
f7g7_38 := int64(f7_2) * int64(g7_19)
|
||||||
|
f7g8_19 := int64(f7) * int64(g8_19)
|
||||||
|
f7g9_38 := int64(f7_2) * int64(g9_19)
|
||||||
|
f8g0 := int64(f8) * int64(g0)
|
||||||
|
f8g1 := int64(f8) * int64(g1)
|
||||||
|
f8g2_19 := int64(f8) * int64(g2_19)
|
||||||
|
f8g3_19 := int64(f8) * int64(g3_19)
|
||||||
|
f8g4_19 := int64(f8) * int64(g4_19)
|
||||||
|
f8g5_19 := int64(f8) * int64(g5_19)
|
||||||
|
f8g6_19 := int64(f8) * int64(g6_19)
|
||||||
|
f8g7_19 := int64(f8) * int64(g7_19)
|
||||||
|
f8g8_19 := int64(f8) * int64(g8_19)
|
||||||
|
f8g9_19 := int64(f8) * int64(g9_19)
|
||||||
|
f9g0 := int64(f9) * int64(g0)
|
||||||
|
f9g1_38 := int64(f9_2) * int64(g1_19)
|
||||||
|
f9g2_19 := int64(f9) * int64(g2_19)
|
||||||
|
f9g3_38 := int64(f9_2) * int64(g3_19)
|
||||||
|
f9g4_19 := int64(f9) * int64(g4_19)
|
||||||
|
f9g5_38 := int64(f9_2) * int64(g5_19)
|
||||||
|
f9g6_19 := int64(f9) * int64(g6_19)
|
||||||
|
f9g7_38 := int64(f9_2) * int64(g7_19)
|
||||||
|
f9g8_19 := int64(f9) * int64(g8_19)
|
||||||
|
f9g9_38 := int64(f9_2) * int64(g9_19)
|
||||||
|
h0 := f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38
|
||||||
|
h1 := f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19
|
||||||
|
h2 := f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38
|
||||||
|
h3 := f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19
|
||||||
|
h4 := f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38
|
||||||
|
h5 := f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19
|
||||||
|
h6 := f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38
|
||||||
|
h7 := f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19
|
||||||
|
h8 := f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38
|
||||||
|
h9 := f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0
|
||||||
|
var carry [10]int64
|
||||||
|
|
||||||
|
// |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38))
|
||||||
|
// i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8
|
||||||
|
// |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19))
|
||||||
|
// i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9
|
||||||
|
|
||||||
|
carry[0] = (h0 + (1 << 25)) >> 26
|
||||||
|
h1 += carry[0]
|
||||||
|
h0 -= carry[0] << 26
|
||||||
|
carry[4] = (h4 + (1 << 25)) >> 26
|
||||||
|
h5 += carry[4]
|
||||||
|
h4 -= carry[4] << 26
|
||||||
|
// |h0| <= 2^25
|
||||||
|
// |h4| <= 2^25
|
||||||
|
// |h1| <= 1.51*2^58
|
||||||
|
// |h5| <= 1.51*2^58
|
||||||
|
|
||||||
|
carry[1] = (h1 + (1 << 24)) >> 25
|
||||||
|
h2 += carry[1]
|
||||||
|
h1 -= carry[1] << 25
|
||||||
|
carry[5] = (h5 + (1 << 24)) >> 25
|
||||||
|
h6 += carry[5]
|
||||||
|
h5 -= carry[5] << 25
|
||||||
|
// |h1| <= 2^24; from now on fits into int32
|
||||||
|
// |h5| <= 2^24; from now on fits into int32
|
||||||
|
// |h2| <= 1.21*2^59
|
||||||
|
// |h6| <= 1.21*2^59
|
||||||
|
|
||||||
|
carry[2] = (h2 + (1 << 25)) >> 26
|
||||||
|
h3 += carry[2]
|
||||||
|
h2 -= carry[2] << 26
|
||||||
|
carry[6] = (h6 + (1 << 25)) >> 26
|
||||||
|
h7 += carry[6]
|
||||||
|
h6 -= carry[6] << 26
|
||||||
|
// |h2| <= 2^25; from now on fits into int32 unchanged
|
||||||
|
// |h6| <= 2^25; from now on fits into int32 unchanged
|
||||||
|
// |h3| <= 1.51*2^58
|
||||||
|
// |h7| <= 1.51*2^58
|
||||||
|
|
||||||
|
carry[3] = (h3 + (1 << 24)) >> 25
|
||||||
|
h4 += carry[3]
|
||||||
|
h3 -= carry[3] << 25
|
||||||
|
carry[7] = (h7 + (1 << 24)) >> 25
|
||||||
|
h8 += carry[7]
|
||||||
|
h7 -= carry[7] << 25
|
||||||
|
// |h3| <= 2^24; from now on fits into int32 unchanged
|
||||||
|
// |h7| <= 2^24; from now on fits into int32 unchanged
|
||||||
|
// |h4| <= 1.52*2^33
|
||||||
|
// |h8| <= 1.52*2^33
|
||||||
|
|
||||||
|
carry[4] = (h4 + (1 << 25)) >> 26
|
||||||
|
h5 += carry[4]
|
||||||
|
h4 -= carry[4] << 26
|
||||||
|
carry[8] = (h8 + (1 << 25)) >> 26
|
||||||
|
h9 += carry[8]
|
||||||
|
h8 -= carry[8] << 26
|
||||||
|
// |h4| <= 2^25; from now on fits into int32 unchanged
|
||||||
|
// |h8| <= 2^25; from now on fits into int32 unchanged
|
||||||
|
// |h5| <= 1.01*2^24
|
||||||
|
// |h9| <= 1.51*2^58
|
||||||
|
|
||||||
|
carry[9] = (h9 + (1 << 24)) >> 25
|
||||||
|
h0 += carry[9] * 19
|
||||||
|
h9 -= carry[9] << 25
|
||||||
|
// |h9| <= 2^24; from now on fits into int32 unchanged
|
||||||
|
// |h0| <= 1.8*2^37
|
||||||
|
|
||||||
|
carry[0] = (h0 + (1 << 25)) >> 26
|
||||||
|
h1 += carry[0]
|
||||||
|
h0 -= carry[0] << 26
|
||||||
|
// |h0| <= 2^25; from now on fits into int32 unchanged
|
||||||
|
// |h1| <= 1.01*2^24
|
||||||
|
|
||||||
|
h[0] = int32(h0)
|
||||||
|
h[1] = int32(h1)
|
||||||
|
h[2] = int32(h2)
|
||||||
|
h[3] = int32(h3)
|
||||||
|
h[4] = int32(h4)
|
||||||
|
h[5] = int32(h5)
|
||||||
|
h[6] = int32(h6)
|
||||||
|
h[7] = int32(h7)
|
||||||
|
h[8] = int32(h8)
|
||||||
|
h[9] = int32(h9)
|
||||||
|
}
|
||||||
|
|
||||||
|
// feSquare calculates h = f*f. Can overlap h with f.
|
||||||
|
//
|
||||||
|
// Preconditions:
|
||||||
|
// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
|
||||||
|
//
|
||||||
|
// Postconditions:
|
||||||
|
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
|
||||||
|
func feSquare(h, f *fieldElement) {
|
||||||
|
f0 := f[0]
|
||||||
|
f1 := f[1]
|
||||||
|
f2 := f[2]
|
||||||
|
f3 := f[3]
|
||||||
|
f4 := f[4]
|
||||||
|
f5 := f[5]
|
||||||
|
f6 := f[6]
|
||||||
|
f7 := f[7]
|
||||||
|
f8 := f[8]
|
||||||
|
f9 := f[9]
|
||||||
|
f0_2 := 2 * f0
|
||||||
|
f1_2 := 2 * f1
|
||||||
|
f2_2 := 2 * f2
|
||||||
|
f3_2 := 2 * f3
|
||||||
|
f4_2 := 2 * f4
|
||||||
|
f5_2 := 2 * f5
|
||||||
|
f6_2 := 2 * f6
|
||||||
|
f7_2 := 2 * f7
|
||||||
|
f5_38 := 38 * f5 // 1.31*2^30
|
||||||
|
f6_19 := 19 * f6 // 1.31*2^30
|
||||||
|
f7_38 := 38 * f7 // 1.31*2^30
|
||||||
|
f8_19 := 19 * f8 // 1.31*2^30
|
||||||
|
f9_38 := 38 * f9 // 1.31*2^30
|
||||||
|
f0f0 := int64(f0) * int64(f0)
|
||||||
|
f0f1_2 := int64(f0_2) * int64(f1)
|
||||||
|
f0f2_2 := int64(f0_2) * int64(f2)
|
||||||
|
f0f3_2 := int64(f0_2) * int64(f3)
|
||||||
|
f0f4_2 := int64(f0_2) * int64(f4)
|
||||||
|
f0f5_2 := int64(f0_2) * int64(f5)
|
||||||
|
f0f6_2 := int64(f0_2) * int64(f6)
|
||||||
|
f0f7_2 := int64(f0_2) * int64(f7)
|
||||||
|
f0f8_2 := int64(f0_2) * int64(f8)
|
||||||
|
f0f9_2 := int64(f0_2) * int64(f9)
|
||||||
|
f1f1_2 := int64(f1_2) * int64(f1)
|
||||||
|
f1f2_2 := int64(f1_2) * int64(f2)
|
||||||
|
f1f3_4 := int64(f1_2) * int64(f3_2)
|
||||||
|
f1f4_2 := int64(f1_2) * int64(f4)
|
||||||
|
f1f5_4 := int64(f1_2) * int64(f5_2)
|
||||||
|
f1f6_2 := int64(f1_2) * int64(f6)
|
||||||
|
f1f7_4 := int64(f1_2) * int64(f7_2)
|
||||||
|
f1f8_2 := int64(f1_2) * int64(f8)
|
||||||
|
f1f9_76 := int64(f1_2) * int64(f9_38)
|
||||||
|
f2f2 := int64(f2) * int64(f2)
|
||||||
|
f2f3_2 := int64(f2_2) * int64(f3)
|
||||||
|
f2f4_2 := int64(f2_2) * int64(f4)
|
||||||
|
f2f5_2 := int64(f2_2) * int64(f5)
|
||||||
|
f2f6_2 := int64(f2_2) * int64(f6)
|
||||||
|
f2f7_2 := int64(f2_2) * int64(f7)
|
||||||
|
f2f8_38 := int64(f2_2) * int64(f8_19)
|
||||||
|
f2f9_38 := int64(f2) * int64(f9_38)
|
||||||
|
f3f3_2 := int64(f3_2) * int64(f3)
|
||||||
|
f3f4_2 := int64(f3_2) * int64(f4)
|
||||||
|
f3f5_4 := int64(f3_2) * int64(f5_2)
|
||||||
|
f3f6_2 := int64(f3_2) * int64(f6)
|
||||||
|
f3f7_76 := int64(f3_2) * int64(f7_38)
|
||||||
|
f3f8_38 := int64(f3_2) * int64(f8_19)
|
||||||
|
f3f9_76 := int64(f3_2) * int64(f9_38)
|
||||||
|
f4f4 := int64(f4) * int64(f4)
|
||||||
|
f4f5_2 := int64(f4_2) * int64(f5)
|
||||||
|
f4f6_38 := int64(f4_2) * int64(f6_19)
|
||||||
|
f4f7_38 := int64(f4) * int64(f7_38)
|
||||||
|
f4f8_38 := int64(f4_2) * int64(f8_19)
|
||||||
|
f4f9_38 := int64(f4) * int64(f9_38)
|
||||||
|
f5f5_38 := int64(f5) * int64(f5_38)
|
||||||
|
f5f6_38 := int64(f5_2) * int64(f6_19)
|
||||||
|
f5f7_76 := int64(f5_2) * int64(f7_38)
|
||||||
|
f5f8_38 := int64(f5_2) * int64(f8_19)
|
||||||
|
f5f9_76 := int64(f5_2) * int64(f9_38)
|
||||||
|
f6f6_19 := int64(f6) * int64(f6_19)
|
||||||
|
f6f7_38 := int64(f6) * int64(f7_38)
|
||||||
|
f6f8_38 := int64(f6_2) * int64(f8_19)
|
||||||
|
f6f9_38 := int64(f6) * int64(f9_38)
|
||||||
|
f7f7_38 := int64(f7) * int64(f7_38)
|
||||||
|
f7f8_38 := int64(f7_2) * int64(f8_19)
|
||||||
|
f7f9_76 := int64(f7_2) * int64(f9_38)
|
||||||
|
f8f8_19 := int64(f8) * int64(f8_19)
|
||||||
|
f8f9_38 := int64(f8) * int64(f9_38)
|
||||||
|
f9f9_38 := int64(f9) * int64(f9_38)
|
||||||
|
h0 := f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38
|
||||||
|
h1 := f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38
|
||||||
|
h2 := f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19
|
||||||
|
h3 := f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38
|
||||||
|
h4 := f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38
|
||||||
|
h5 := f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38
|
||||||
|
h6 := f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19
|
||||||
|
h7 := f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38
|
||||||
|
h8 := f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38
|
||||||
|
h9 := f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2
|
||||||
|
var carry [10]int64
|
||||||
|
|
||||||
|
carry[0] = (h0 + (1 << 25)) >> 26
|
||||||
|
h1 += carry[0]
|
||||||
|
h0 -= carry[0] << 26
|
||||||
|
carry[4] = (h4 + (1 << 25)) >> 26
|
||||||
|
h5 += carry[4]
|
||||||
|
h4 -= carry[4] << 26
|
||||||
|
|
||||||
|
carry[1] = (h1 + (1 << 24)) >> 25
|
||||||
|
h2 += carry[1]
|
||||||
|
h1 -= carry[1] << 25
|
||||||
|
carry[5] = (h5 + (1 << 24)) >> 25
|
||||||
|
h6 += carry[5]
|
||||||
|
h5 -= carry[5] << 25
|
||||||
|
|
||||||
|
carry[2] = (h2 + (1 << 25)) >> 26
|
||||||
|
h3 += carry[2]
|
||||||
|
h2 -= carry[2] << 26
|
||||||
|
carry[6] = (h6 + (1 << 25)) >> 26
|
||||||
|
h7 += carry[6]
|
||||||
|
h6 -= carry[6] << 26
|
||||||
|
|
||||||
|
carry[3] = (h3 + (1 << 24)) >> 25
|
||||||
|
h4 += carry[3]
|
||||||
|
h3 -= carry[3] << 25
|
||||||
|
carry[7] = (h7 + (1 << 24)) >> 25
|
||||||
|
h8 += carry[7]
|
||||||
|
h7 -= carry[7] << 25
|
||||||
|
|
||||||
|
carry[4] = (h4 + (1 << 25)) >> 26
|
||||||
|
h5 += carry[4]
|
||||||
|
h4 -= carry[4] << 26
|
||||||
|
carry[8] = (h8 + (1 << 25)) >> 26
|
||||||
|
h9 += carry[8]
|
||||||
|
h8 -= carry[8] << 26
|
||||||
|
|
||||||
|
carry[9] = (h9 + (1 << 24)) >> 25
|
||||||
|
h0 += carry[9] * 19
|
||||||
|
h9 -= carry[9] << 25
|
||||||
|
|
||||||
|
carry[0] = (h0 + (1 << 25)) >> 26
|
||||||
|
h1 += carry[0]
|
||||||
|
h0 -= carry[0] << 26
|
||||||
|
|
||||||
|
h[0] = int32(h0)
|
||||||
|
h[1] = int32(h1)
|
||||||
|
h[2] = int32(h2)
|
||||||
|
h[3] = int32(h3)
|
||||||
|
h[4] = int32(h4)
|
||||||
|
h[5] = int32(h5)
|
||||||
|
h[6] = int32(h6)
|
||||||
|
h[7] = int32(h7)
|
||||||
|
h[8] = int32(h8)
|
||||||
|
h[9] = int32(h9)
|
||||||
|
}
|
||||||
|
|
||||||
|
// feMul121666 calculates h = f * 121666. Can overlap h with f.
|
||||||
|
//
|
||||||
|
// Preconditions:
|
||||||
|
// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
|
||||||
|
//
|
||||||
|
// Postconditions:
|
||||||
|
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
|
||||||
|
func feMul121666(h, f *fieldElement) {
|
||||||
|
h0 := int64(f[0]) * 121666
|
||||||
|
h1 := int64(f[1]) * 121666
|
||||||
|
h2 := int64(f[2]) * 121666
|
||||||
|
h3 := int64(f[3]) * 121666
|
||||||
|
h4 := int64(f[4]) * 121666
|
||||||
|
h5 := int64(f[5]) * 121666
|
||||||
|
h6 := int64(f[6]) * 121666
|
||||||
|
h7 := int64(f[7]) * 121666
|
||||||
|
h8 := int64(f[8]) * 121666
|
||||||
|
h9 := int64(f[9]) * 121666
|
||||||
|
var carry [10]int64
|
||||||
|
|
||||||
|
carry[9] = (h9 + (1 << 24)) >> 25
|
||||||
|
h0 += carry[9] * 19
|
||||||
|
h9 -= carry[9] << 25
|
||||||
|
carry[1] = (h1 + (1 << 24)) >> 25
|
||||||
|
h2 += carry[1]
|
||||||
|
h1 -= carry[1] << 25
|
||||||
|
carry[3] = (h3 + (1 << 24)) >> 25
|
||||||
|
h4 += carry[3]
|
||||||
|
h3 -= carry[3] << 25
|
||||||
|
carry[5] = (h5 + (1 << 24)) >> 25
|
||||||
|
h6 += carry[5]
|
||||||
|
h5 -= carry[5] << 25
|
||||||
|
carry[7] = (h7 + (1 << 24)) >> 25
|
||||||
|
h8 += carry[7]
|
||||||
|
h7 -= carry[7] << 25
|
||||||
|
|
||||||
|
carry[0] = (h0 + (1 << 25)) >> 26
|
||||||
|
h1 += carry[0]
|
||||||
|
h0 -= carry[0] << 26
|
||||||
|
carry[2] = (h2 + (1 << 25)) >> 26
|
||||||
|
h3 += carry[2]
|
||||||
|
h2 -= carry[2] << 26
|
||||||
|
carry[4] = (h4 + (1 << 25)) >> 26
|
||||||
|
h5 += carry[4]
|
||||||
|
h4 -= carry[4] << 26
|
||||||
|
carry[6] = (h6 + (1 << 25)) >> 26
|
||||||
|
h7 += carry[6]
|
||||||
|
h6 -= carry[6] << 26
|
||||||
|
carry[8] = (h8 + (1 << 25)) >> 26
|
||||||
|
h9 += carry[8]
|
||||||
|
h8 -= carry[8] << 26
|
||||||
|
|
||||||
|
h[0] = int32(h0)
|
||||||
|
h[1] = int32(h1)
|
||||||
|
h[2] = int32(h2)
|
||||||
|
h[3] = int32(h3)
|
||||||
|
h[4] = int32(h4)
|
||||||
|
h[5] = int32(h5)
|
||||||
|
h[6] = int32(h6)
|
||||||
|
h[7] = int32(h7)
|
||||||
|
h[8] = int32(h8)
|
||||||
|
h[9] = int32(h9)
|
||||||
|
}
|
||||||
|
|
||||||
|
// feInvert sets out = z^-1.
|
||||||
|
func feInvert(out, z *fieldElement) {
|
||||||
|
var t0, t1, t2, t3 fieldElement
|
||||||
|
var i int
|
||||||
|
|
||||||
|
feSquare(&t0, z)
|
||||||
|
for i = 1; i < 1; i++ {
|
||||||
|
feSquare(&t0, &t0)
|
||||||
|
}
|
||||||
|
feSquare(&t1, &t0)
|
||||||
|
for i = 1; i < 2; i++ {
|
||||||
|
feSquare(&t1, &t1)
|
||||||
|
}
|
||||||
|
feMul(&t1, z, &t1)
|
||||||
|
feMul(&t0, &t0, &t1)
|
||||||
|
feSquare(&t2, &t0)
|
||||||
|
for i = 1; i < 1; i++ {
|
||||||
|
feSquare(&t2, &t2)
|
||||||
|
}
|
||||||
|
feMul(&t1, &t1, &t2)
|
||||||
|
feSquare(&t2, &t1)
|
||||||
|
for i = 1; i < 5; i++ {
|
||||||
|
feSquare(&t2, &t2)
|
||||||
|
}
|
||||||
|
feMul(&t1, &t2, &t1)
|
||||||
|
feSquare(&t2, &t1)
|
||||||
|
for i = 1; i < 10; i++ {
|
||||||
|
feSquare(&t2, &t2)
|
||||||
|
}
|
||||||
|
feMul(&t2, &t2, &t1)
|
||||||
|
feSquare(&t3, &t2)
|
||||||
|
for i = 1; i < 20; i++ {
|
||||||
|
feSquare(&t3, &t3)
|
||||||
|
}
|
||||||
|
feMul(&t2, &t3, &t2)
|
||||||
|
feSquare(&t2, &t2)
|
||||||
|
for i = 1; i < 10; i++ {
|
||||||
|
feSquare(&t2, &t2)
|
||||||
|
}
|
||||||
|
feMul(&t1, &t2, &t1)
|
||||||
|
feSquare(&t2, &t1)
|
||||||
|
for i = 1; i < 50; i++ {
|
||||||
|
feSquare(&t2, &t2)
|
||||||
|
}
|
||||||
|
feMul(&t2, &t2, &t1)
|
||||||
|
feSquare(&t3, &t2)
|
||||||
|
for i = 1; i < 100; i++ {
|
||||||
|
feSquare(&t3, &t3)
|
||||||
|
}
|
||||||
|
feMul(&t2, &t3, &t2)
|
||||||
|
feSquare(&t2, &t2)
|
||||||
|
for i = 1; i < 50; i++ {
|
||||||
|
feSquare(&t2, &t2)
|
||||||
|
}
|
||||||
|
feMul(&t1, &t2, &t1)
|
||||||
|
feSquare(&t1, &t1)
|
||||||
|
for i = 1; i < 5; i++ {
|
||||||
|
feSquare(&t1, &t1)
|
||||||
|
}
|
||||||
|
feMul(out, &t1, &t0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func scalarMultGeneric(out, in, base *[32]byte) {
|
||||||
|
var e [32]byte
|
||||||
|
|
||||||
|
copy(e[:], in[:])
|
||||||
|
e[0] &= 248
|
||||||
|
e[31] &= 127
|
||||||
|
e[31] |= 64
|
||||||
|
|
||||||
|
var x1, x2, z2, x3, z3, tmp0, tmp1 fieldElement
|
||||||
|
feFromBytes(&x1, base)
|
||||||
|
feOne(&x2)
|
||||||
|
feCopy(&x3, &x1)
|
||||||
|
feOne(&z3)
|
||||||
|
|
||||||
|
swap := int32(0)
|
||||||
|
for pos := 254; pos >= 0; pos-- {
|
||||||
|
b := e[pos/8] >> uint(pos&7)
|
||||||
|
b &= 1
|
||||||
|
swap ^= int32(b)
|
||||||
|
feCSwap(&x2, &x3, swap)
|
||||||
|
feCSwap(&z2, &z3, swap)
|
||||||
|
swap = int32(b)
|
||||||
|
|
||||||
|
feSub(&tmp0, &x3, &z3)
|
||||||
|
feSub(&tmp1, &x2, &z2)
|
||||||
|
feAdd(&x2, &x2, &z2)
|
||||||
|
feAdd(&z2, &x3, &z3)
|
||||||
|
feMul(&z3, &tmp0, &x2)
|
||||||
|
feMul(&z2, &z2, &tmp1)
|
||||||
|
feSquare(&tmp0, &tmp1)
|
||||||
|
feSquare(&tmp1, &x2)
|
||||||
|
feAdd(&x3, &z3, &z2)
|
||||||
|
feSub(&z2, &z3, &z2)
|
||||||
|
feMul(&x2, &tmp1, &tmp0)
|
||||||
|
feSub(&tmp1, &tmp1, &tmp0)
|
||||||
|
feSquare(&z2, &z2)
|
||||||
|
feMul121666(&z3, &tmp1)
|
||||||
|
feSquare(&x3, &x3)
|
||||||
|
feAdd(&tmp0, &tmp0, &z3)
|
||||||
|
feMul(&z3, &x1, &z2)
|
||||||
|
feMul(&z2, &tmp1, &tmp0)
|
||||||
|
}
|
||||||
|
|
||||||
|
feCSwap(&x2, &x3, swap)
|
||||||
|
feCSwap(&z2, &z3, swap)
|
||||||
|
|
||||||
|
feInvert(&z2, &z2)
|
||||||
|
feMul(&x2, &x2, &z2)
|
||||||
|
feToBytes(out, &x2)
|
||||||
|
}
|
11
vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go
generated
vendored
Normal file
11
vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !amd64 gccgo appengine purego
|
||||||
|
|
||||||
|
package curve25519
|
||||||
|
|
||||||
|
func scalarMult(out, in, base *[32]byte) {
|
||||||
|
scalarMultGeneric(out, in, base)
|
||||||
|
}
|
23
vendor/golang.org/x/crypto/curve25519/doc.go
generated
vendored
23
vendor/golang.org/x/crypto/curve25519/doc.go
generated
vendored
@ -1,23 +0,0 @@
|
|||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package curve25519 provides an implementation of scalar multiplication on
|
|
||||||
// the elliptic curve known as curve25519. See https://cr.yp.to/ecdh.html
|
|
||||||
package curve25519 // import "golang.org/x/crypto/curve25519"
|
|
||||||
|
|
||||||
// basePoint is the x coordinate of the generator of the curve.
|
|
||||||
var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
|
||||||
|
|
||||||
// ScalarMult sets dst to the product in*base where dst and base are the x
|
|
||||||
// coordinates of group points and all values are in little-endian form.
|
|
||||||
func ScalarMult(dst, in, base *[32]byte) {
|
|
||||||
scalarMult(dst, in, base)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ScalarBaseMult sets dst to the product in*base where dst and base are the x
|
|
||||||
// coordinates of group points, base is the standard generator and all values
|
|
||||||
// are in little-endian form.
|
|
||||||
func ScalarBaseMult(dst, in *[32]byte) {
|
|
||||||
ScalarMult(dst, in, &basePoint)
|
|
||||||
}
|
|
73
vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
generated
vendored
73
vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
generated
vendored
@ -1,73 +0,0 @@
|
|||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// This code was translated into a form compatible with 6a from the public
|
|
||||||
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
|
|
||||||
|
|
||||||
// +build amd64,!gccgo,!appengine
|
|
||||||
|
|
||||||
#include "const_amd64.h"
|
|
||||||
|
|
||||||
// func freeze(inout *[5]uint64)
|
|
||||||
TEXT ·freeze(SB),7,$0-8
|
|
||||||
MOVQ inout+0(FP), DI
|
|
||||||
|
|
||||||
MOVQ 0(DI),SI
|
|
||||||
MOVQ 8(DI),DX
|
|
||||||
MOVQ 16(DI),CX
|
|
||||||
MOVQ 24(DI),R8
|
|
||||||
MOVQ 32(DI),R9
|
|
||||||
MOVQ $REDMASK51,AX
|
|
||||||
MOVQ AX,R10
|
|
||||||
SUBQ $18,R10
|
|
||||||
MOVQ $3,R11
|
|
||||||
REDUCELOOP:
|
|
||||||
MOVQ SI,R12
|
|
||||||
SHRQ $51,R12
|
|
||||||
ANDQ AX,SI
|
|
||||||
ADDQ R12,DX
|
|
||||||
MOVQ DX,R12
|
|
||||||
SHRQ $51,R12
|
|
||||||
ANDQ AX,DX
|
|
||||||
ADDQ R12,CX
|
|
||||||
MOVQ CX,R12
|
|
||||||
SHRQ $51,R12
|
|
||||||
ANDQ AX,CX
|
|
||||||
ADDQ R12,R8
|
|
||||||
MOVQ R8,R12
|
|
||||||
SHRQ $51,R12
|
|
||||||
ANDQ AX,R8
|
|
||||||
ADDQ R12,R9
|
|
||||||
MOVQ R9,R12
|
|
||||||
SHRQ $51,R12
|
|
||||||
ANDQ AX,R9
|
|
||||||
IMUL3Q $19,R12,R12
|
|
||||||
ADDQ R12,SI
|
|
||||||
SUBQ $1,R11
|
|
||||||
JA REDUCELOOP
|
|
||||||
MOVQ $1,R12
|
|
||||||
CMPQ R10,SI
|
|
||||||
CMOVQLT R11,R12
|
|
||||||
CMPQ AX,DX
|
|
||||||
CMOVQNE R11,R12
|
|
||||||
CMPQ AX,CX
|
|
||||||
CMOVQNE R11,R12
|
|
||||||
CMPQ AX,R8
|
|
||||||
CMOVQNE R11,R12
|
|
||||||
CMPQ AX,R9
|
|
||||||
CMOVQNE R11,R12
|
|
||||||
NEGQ R12
|
|
||||||
ANDQ R12,AX
|
|
||||||
ANDQ R12,R10
|
|
||||||
SUBQ R10,SI
|
|
||||||
SUBQ AX,DX
|
|
||||||
SUBQ AX,CX
|
|
||||||
SUBQ AX,R8
|
|
||||||
SUBQ AX,R9
|
|
||||||
MOVQ SI,0(DI)
|
|
||||||
MOVQ DX,8(DI)
|
|
||||||
MOVQ CX,16(DI)
|
|
||||||
MOVQ R8,24(DI)
|
|
||||||
MOVQ R9,32(DI)
|
|
||||||
RET
|
|
169
vendor/golang.org/x/crypto/curve25519/mul_amd64.s
generated
vendored
169
vendor/golang.org/x/crypto/curve25519/mul_amd64.s
generated
vendored
@ -1,169 +0,0 @@
|
|||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// This code was translated into a form compatible with 6a from the public
|
|
||||||
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
|
|
||||||
|
|
||||||
// +build amd64,!gccgo,!appengine
|
|
||||||
|
|
||||||
#include "const_amd64.h"
|
|
||||||
|
|
||||||
// func mul(dest, a, b *[5]uint64)
|
|
||||||
TEXT ·mul(SB),0,$16-24
|
|
||||||
MOVQ dest+0(FP), DI
|
|
||||||
MOVQ a+8(FP), SI
|
|
||||||
MOVQ b+16(FP), DX
|
|
||||||
|
|
||||||
MOVQ DX,CX
|
|
||||||
MOVQ 24(SI),DX
|
|
||||||
IMUL3Q $19,DX,AX
|
|
||||||
MOVQ AX,0(SP)
|
|
||||||
MULQ 16(CX)
|
|
||||||
MOVQ AX,R8
|
|
||||||
MOVQ DX,R9
|
|
||||||
MOVQ 32(SI),DX
|
|
||||||
IMUL3Q $19,DX,AX
|
|
||||||
MOVQ AX,8(SP)
|
|
||||||
MULQ 8(CX)
|
|
||||||
ADDQ AX,R8
|
|
||||||
ADCQ DX,R9
|
|
||||||
MOVQ 0(SI),AX
|
|
||||||
MULQ 0(CX)
|
|
||||||
ADDQ AX,R8
|
|
||||||
ADCQ DX,R9
|
|
||||||
MOVQ 0(SI),AX
|
|
||||||
MULQ 8(CX)
|
|
||||||
MOVQ AX,R10
|
|
||||||
MOVQ DX,R11
|
|
||||||
MOVQ 0(SI),AX
|
|
||||||
MULQ 16(CX)
|
|
||||||
MOVQ AX,R12
|
|
||||||
MOVQ DX,R13
|
|
||||||
MOVQ 0(SI),AX
|
|
||||||
MULQ 24(CX)
|
|
||||||
MOVQ AX,R14
|
|
||||||
MOVQ DX,R15
|
|
||||||
MOVQ 0(SI),AX
|
|
||||||
MULQ 32(CX)
|
|
||||||
MOVQ AX,BX
|
|
||||||
MOVQ DX,BP
|
|
||||||
MOVQ 8(SI),AX
|
|
||||||
MULQ 0(CX)
|
|
||||||
ADDQ AX,R10
|
|
||||||
ADCQ DX,R11
|
|
||||||
MOVQ 8(SI),AX
|
|
||||||
MULQ 8(CX)
|
|
||||||
ADDQ AX,R12
|
|
||||||
ADCQ DX,R13
|
|
||||||
MOVQ 8(SI),AX
|
|
||||||
MULQ 16(CX)
|
|
||||||
ADDQ AX,R14
|
|
||||||
ADCQ DX,R15
|
|
||||||
MOVQ 8(SI),AX
|
|
||||||
MULQ 24(CX)
|
|
||||||
ADDQ AX,BX
|
|
||||||
ADCQ DX,BP
|
|
||||||
MOVQ 8(SI),DX
|
|
||||||
IMUL3Q $19,DX,AX
|
|
||||||
MULQ 32(CX)
|
|
||||||
ADDQ AX,R8
|
|
||||||
ADCQ DX,R9
|
|
||||||
MOVQ 16(SI),AX
|
|
||||||
MULQ 0(CX)
|
|
||||||
ADDQ AX,R12
|
|
||||||
ADCQ DX,R13
|
|
||||||
MOVQ 16(SI),AX
|
|
||||||
MULQ 8(CX)
|
|
||||||
ADDQ AX,R14
|
|
||||||
ADCQ DX,R15
|
|
||||||
MOVQ 16(SI),AX
|
|
||||||
MULQ 16(CX)
|
|
||||||
ADDQ AX,BX
|
|
||||||
ADCQ DX,BP
|
|
||||||
MOVQ 16(SI),DX
|
|
||||||
IMUL3Q $19,DX,AX
|
|
||||||
MULQ 24(CX)
|
|
||||||
ADDQ AX,R8
|
|
||||||
ADCQ DX,R9
|
|
||||||
MOVQ 16(SI),DX
|
|
||||||
IMUL3Q $19,DX,AX
|
|
||||||
MULQ 32(CX)
|
|
||||||
ADDQ AX,R10
|
|
||||||
ADCQ DX,R11
|
|
||||||
MOVQ 24(SI),AX
|
|
||||||
MULQ 0(CX)
|
|
||||||
ADDQ AX,R14
|
|
||||||
ADCQ DX,R15
|
|
||||||
MOVQ 24(SI),AX
|
|
||||||
MULQ 8(CX)
|
|
||||||
ADDQ AX,BX
|
|
||||||
ADCQ DX,BP
|
|
||||||
MOVQ 0(SP),AX
|
|
||||||
MULQ 24(CX)
|
|
||||||
ADDQ AX,R10
|
|
||||||
ADCQ DX,R11
|
|
||||||
MOVQ 0(SP),AX
|
|
||||||
MULQ 32(CX)
|
|
||||||
ADDQ AX,R12
|
|
||||||
ADCQ DX,R13
|
|
||||||
MOVQ 32(SI),AX
|
|
||||||
MULQ 0(CX)
|
|
||||||
ADDQ AX,BX
|
|
||||||
ADCQ DX,BP
|
|
||||||
MOVQ 8(SP),AX
|
|
||||||
MULQ 16(CX)
|
|
||||||
ADDQ AX,R10
|
|
||||||
ADCQ DX,R11
|
|
||||||
MOVQ 8(SP),AX
|
|
||||||
MULQ 24(CX)
|
|
||||||
ADDQ AX,R12
|
|
||||||
ADCQ DX,R13
|
|
||||||
MOVQ 8(SP),AX
|
|
||||||
MULQ 32(CX)
|
|
||||||
ADDQ AX,R14
|
|
||||||
ADCQ DX,R15
|
|
||||||
MOVQ $REDMASK51,SI
|
|
||||||
SHLQ $13,R8,R9
|
|
||||||
ANDQ SI,R8
|
|
||||||
SHLQ $13,R10,R11
|
|
||||||
ANDQ SI,R10
|
|
||||||
ADDQ R9,R10
|
|
||||||
SHLQ $13,R12,R13
|
|
||||||
ANDQ SI,R12
|
|
||||||
ADDQ R11,R12
|
|
||||||
SHLQ $13,R14,R15
|
|
||||||
ANDQ SI,R14
|
|
||||||
ADDQ R13,R14
|
|
||||||
SHLQ $13,BX,BP
|
|
||||||
ANDQ SI,BX
|
|
||||||
ADDQ R15,BX
|
|
||||||
IMUL3Q $19,BP,DX
|
|
||||||
ADDQ DX,R8
|
|
||||||
MOVQ R8,DX
|
|
||||||
SHRQ $51,DX
|
|
||||||
ADDQ R10,DX
|
|
||||||
MOVQ DX,CX
|
|
||||||
SHRQ $51,DX
|
|
||||||
ANDQ SI,R8
|
|
||||||
ADDQ R12,DX
|
|
||||||
MOVQ DX,R9
|
|
||||||
SHRQ $51,DX
|
|
||||||
ANDQ SI,CX
|
|
||||||
ADDQ R14,DX
|
|
||||||
MOVQ DX,AX
|
|
||||||
SHRQ $51,DX
|
|
||||||
ANDQ SI,R9
|
|
||||||
ADDQ BX,DX
|
|
||||||
MOVQ DX,R10
|
|
||||||
SHRQ $51,DX
|
|
||||||
ANDQ SI,AX
|
|
||||||
IMUL3Q $19,DX,DX
|
|
||||||
ADDQ DX,R8
|
|
||||||
ANDQ SI,R10
|
|
||||||
MOVQ R8,0(DI)
|
|
||||||
MOVQ CX,8(DI)
|
|
||||||
MOVQ R9,16(DI)
|
|
||||||
MOVQ AX,24(DI)
|
|
||||||
MOVQ R10,32(DI)
|
|
||||||
RET
|
|
132
vendor/golang.org/x/crypto/curve25519/square_amd64.s
generated
vendored
132
vendor/golang.org/x/crypto/curve25519/square_amd64.s
generated
vendored
@ -1,132 +0,0 @@
|
|||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// This code was translated into a form compatible with 6a from the public
|
|
||||||
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
|
|
||||||
|
|
||||||
// +build amd64,!gccgo,!appengine
|
|
||||||
|
|
||||||
#include "const_amd64.h"
|
|
||||||
|
|
||||||
// func square(out, in *[5]uint64)
|
|
||||||
TEXT ·square(SB),7,$0-16
|
|
||||||
MOVQ out+0(FP), DI
|
|
||||||
MOVQ in+8(FP), SI
|
|
||||||
|
|
||||||
MOVQ 0(SI),AX
|
|
||||||
MULQ 0(SI)
|
|
||||||
MOVQ AX,CX
|
|
||||||
MOVQ DX,R8
|
|
||||||
MOVQ 0(SI),AX
|
|
||||||
SHLQ $1,AX
|
|
||||||
MULQ 8(SI)
|
|
||||||
MOVQ AX,R9
|
|
||||||
MOVQ DX,R10
|
|
||||||
MOVQ 0(SI),AX
|
|
||||||
SHLQ $1,AX
|
|
||||||
MULQ 16(SI)
|
|
||||||
MOVQ AX,R11
|
|
||||||
MOVQ DX,R12
|
|
||||||
MOVQ 0(SI),AX
|
|
||||||
SHLQ $1,AX
|
|
||||||
MULQ 24(SI)
|
|
||||||
MOVQ AX,R13
|
|
||||||
MOVQ DX,R14
|
|
||||||
MOVQ 0(SI),AX
|
|
||||||
SHLQ $1,AX
|
|
||||||
MULQ 32(SI)
|
|
||||||
MOVQ AX,R15
|
|
||||||
MOVQ DX,BX
|
|
||||||
MOVQ 8(SI),AX
|
|
||||||
MULQ 8(SI)
|
|
||||||
ADDQ AX,R11
|
|
||||||
ADCQ DX,R12
|
|
||||||
MOVQ 8(SI),AX
|
|
||||||
SHLQ $1,AX
|
|
||||||
MULQ 16(SI)
|
|
||||||
ADDQ AX,R13
|
|
||||||
ADCQ DX,R14
|
|
||||||
MOVQ 8(SI),AX
|
|
||||||
SHLQ $1,AX
|
|
||||||
MULQ 24(SI)
|
|
||||||
ADDQ AX,R15
|
|
||||||
ADCQ DX,BX
|
|
||||||
MOVQ 8(SI),DX
|
|
||||||
IMUL3Q $38,DX,AX
|
|
||||||
MULQ 32(SI)
|
|
||||||
ADDQ AX,CX
|
|
||||||
ADCQ DX,R8
|
|
||||||
MOVQ 16(SI),AX
|
|
||||||
MULQ 16(SI)
|
|
||||||
ADDQ AX,R15
|
|
||||||
ADCQ DX,BX
|
|
||||||
MOVQ 16(SI),DX
|
|
||||||
IMUL3Q $38,DX,AX
|
|
||||||
MULQ 24(SI)
|
|
||||||
ADDQ AX,CX
|
|
||||||
ADCQ DX,R8
|
|
||||||
MOVQ 16(SI),DX
|
|
||||||
IMUL3Q $38,DX,AX
|
|
||||||
MULQ 32(SI)
|
|
||||||
ADDQ AX,R9
|
|
||||||
ADCQ DX,R10
|
|
||||||
MOVQ 24(SI),DX
|
|
||||||
IMUL3Q $19,DX,AX
|
|
||||||
MULQ 24(SI)
|
|
||||||
ADDQ AX,R9
|
|
||||||
ADCQ DX,R10
|
|
||||||
MOVQ 24(SI),DX
|
|
||||||
IMUL3Q $38,DX,AX
|
|
||||||
MULQ 32(SI)
|
|
||||||
ADDQ AX,R11
|
|
||||||
ADCQ DX,R12
|
|
||||||
MOVQ 32(SI),DX
|
|
||||||
IMUL3Q $19,DX,AX
|
|
||||||
MULQ 32(SI)
|
|
||||||
ADDQ AX,R13
|
|
||||||
ADCQ DX,R14
|
|
||||||
MOVQ $REDMASK51,SI
|
|
||||||
SHLQ $13,CX,R8
|
|
||||||
ANDQ SI,CX
|
|
||||||
SHLQ $13,R9,R10
|
|
||||||
ANDQ SI,R9
|
|
||||||
ADDQ R8,R9
|
|
||||||
SHLQ $13,R11,R12
|
|
||||||
ANDQ SI,R11
|
|
||||||
ADDQ R10,R11
|
|
||||||
SHLQ $13,R13,R14
|
|
||||||
ANDQ SI,R13
|
|
||||||
ADDQ R12,R13
|
|
||||||
SHLQ $13,R15,BX
|
|
||||||
ANDQ SI,R15
|
|
||||||
ADDQ R14,R15
|
|
||||||
IMUL3Q $19,BX,DX
|
|
||||||
ADDQ DX,CX
|
|
||||||
MOVQ CX,DX
|
|
||||||
SHRQ $51,DX
|
|
||||||
ADDQ R9,DX
|
|
||||||
ANDQ SI,CX
|
|
||||||
MOVQ DX,R8
|
|
||||||
SHRQ $51,DX
|
|
||||||
ADDQ R11,DX
|
|
||||||
ANDQ SI,R8
|
|
||||||
MOVQ DX,R9
|
|
||||||
SHRQ $51,DX
|
|
||||||
ADDQ R13,DX
|
|
||||||
ANDQ SI,R9
|
|
||||||
MOVQ DX,AX
|
|
||||||
SHRQ $51,DX
|
|
||||||
ADDQ R15,DX
|
|
||||||
ANDQ SI,AX
|
|
||||||
MOVQ DX,R10
|
|
||||||
SHRQ $51,DX
|
|
||||||
IMUL3Q $19,DX,DX
|
|
||||||
ADDQ DX,CX
|
|
||||||
ANDQ SI,R10
|
|
||||||
MOVQ CX,0(DI)
|
|
||||||
MOVQ R8,8(DI)
|
|
||||||
MOVQ R9,16(DI)
|
|
||||||
MOVQ AX,24(DI)
|
|
||||||
MOVQ R10,32(DI)
|
|
||||||
RET
|
|
668
vendor/golang.org/x/crypto/internal/chacha20/asm_ppc64le.s
generated
vendored
668
vendor/golang.org/x/crypto/internal/chacha20/asm_ppc64le.s
generated
vendored
@ -1,668 +0,0 @@
|
|||||||
// Copyright 2019 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Based on CRYPTOGAMS code with the following comment:
|
|
||||||
// # ====================================================================
|
|
||||||
// # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
|
|
||||||
// # project. The module is, however, dual licensed under OpenSSL and
|
|
||||||
// # CRYPTOGAMS licenses depending on where you obtain it. For further
|
|
||||||
// # details see http://www.openssl.org/~appro/cryptogams/.
|
|
||||||
// # ====================================================================
|
|
||||||
|
|
||||||
// Original code can be found at the link below:
|
|
||||||
// https://github.com/dot-asm/cryptogams/commit/a60f5b50ed908e91e5c39ca79126a4a876d5d8ff
|
|
||||||
|
|
||||||
// There are some differences between CRYPTOGAMS code and this one. The round
|
|
||||||
// loop for "_int" isn't the same as the original. Some adjustments were
|
|
||||||
// necessary because there are less vector registers available. For example, some
|
|
||||||
// X variables (r12, r13, r14, and r15) share the same register used by the
|
|
||||||
// counter. The original code uses ctr to name the counter. Here we use CNT
|
|
||||||
// because golang uses CTR as the counter register name.
|
|
||||||
|
|
||||||
// +build ppc64le,!gccgo,!appengine
|
|
||||||
|
|
||||||
#include "textflag.h"
|
|
||||||
|
|
||||||
#define OUT R3
|
|
||||||
#define INP R4
|
|
||||||
#define LEN R5
|
|
||||||
#define KEY R6
|
|
||||||
#define CNT R7
|
|
||||||
|
|
||||||
#define TEMP R8
|
|
||||||
|
|
||||||
#define X0 R11
|
|
||||||
#define X1 R12
|
|
||||||
#define X2 R14
|
|
||||||
#define X3 R15
|
|
||||||
#define X4 R16
|
|
||||||
#define X5 R17
|
|
||||||
#define X6 R18
|
|
||||||
#define X7 R19
|
|
||||||
#define X8 R20
|
|
||||||
#define X9 R21
|
|
||||||
#define X10 R22
|
|
||||||
#define X11 R23
|
|
||||||
#define X12 R24
|
|
||||||
#define X13 R25
|
|
||||||
#define X14 R26
|
|
||||||
#define X15 R27
|
|
||||||
|
|
||||||
#define CON0 X0
|
|
||||||
#define CON1 X1
|
|
||||||
#define CON2 X2
|
|
||||||
#define CON3 X3
|
|
||||||
|
|
||||||
#define KEY0 X4
|
|
||||||
#define KEY1 X5
|
|
||||||
#define KEY2 X6
|
|
||||||
#define KEY3 X7
|
|
||||||
#define KEY4 X8
|
|
||||||
#define KEY5 X9
|
|
||||||
#define KEY6 X10
|
|
||||||
#define KEY7 X11
|
|
||||||
|
|
||||||
#define CNT0 X12
|
|
||||||
#define CNT1 X13
|
|
||||||
#define CNT2 X14
|
|
||||||
#define CNT3 X15
|
|
||||||
|
|
||||||
#define TMP0 R9
|
|
||||||
#define TMP1 R10
|
|
||||||
#define TMP2 R28
|
|
||||||
#define TMP3 R29
|
|
||||||
|
|
||||||
#define CONSTS R8
|
|
||||||
|
|
||||||
#define A0 V0
|
|
||||||
#define B0 V1
|
|
||||||
#define C0 V2
|
|
||||||
#define D0 V3
|
|
||||||
#define A1 V4
|
|
||||||
#define B1 V5
|
|
||||||
#define C1 V6
|
|
||||||
#define D1 V7
|
|
||||||
#define A2 V8
|
|
||||||
#define B2 V9
|
|
||||||
#define C2 V10
|
|
||||||
#define D2 V11
|
|
||||||
#define T0 V12
|
|
||||||
#define T1 V13
|
|
||||||
#define T2 V14
|
|
||||||
|
|
||||||
#define K0 V15
|
|
||||||
#define K1 V16
|
|
||||||
#define K2 V17
|
|
||||||
#define K3 V18
|
|
||||||
#define K4 V19
|
|
||||||
#define K5 V20
|
|
||||||
|
|
||||||
#define FOUR V21
|
|
||||||
#define SIXTEEN V22
|
|
||||||
#define TWENTY4 V23
|
|
||||||
#define TWENTY V24
|
|
||||||
#define TWELVE V25
|
|
||||||
#define TWENTY5 V26
|
|
||||||
#define SEVEN V27
|
|
||||||
|
|
||||||
#define INPPERM V28
|
|
||||||
#define OUTPERM V29
|
|
||||||
#define OUTMASK V30
|
|
||||||
|
|
||||||
#define DD0 V31
|
|
||||||
#define DD1 SEVEN
|
|
||||||
#define DD2 T0
|
|
||||||
#define DD3 T1
|
|
||||||
#define DD4 T2
|
|
||||||
|
|
||||||
DATA ·consts+0x00(SB)/8, $0x3320646e61707865
|
|
||||||
DATA ·consts+0x08(SB)/8, $0x6b20657479622d32
|
|
||||||
DATA ·consts+0x10(SB)/8, $0x0000000000000001
|
|
||||||
DATA ·consts+0x18(SB)/8, $0x0000000000000000
|
|
||||||
DATA ·consts+0x20(SB)/8, $0x0000000000000004
|
|
||||||
DATA ·consts+0x28(SB)/8, $0x0000000000000000
|
|
||||||
DATA ·consts+0x30(SB)/8, $0x0a0b08090e0f0c0d
|
|
||||||
DATA ·consts+0x38(SB)/8, $0x0203000106070405
|
|
||||||
DATA ·consts+0x40(SB)/8, $0x090a0b080d0e0f0c
|
|
||||||
DATA ·consts+0x48(SB)/8, $0x0102030005060704
|
|
||||||
GLOBL ·consts(SB), RODATA, $80
|
|
||||||
|
|
||||||
//func chaCha20_ctr32_vmx(out, inp *byte, len int, key *[32]byte, counter *[16]byte)
|
|
||||||
TEXT ·chaCha20_ctr32_vmx(SB),NOSPLIT|NOFRAME,$0
|
|
||||||
// Load the arguments inside the registers
|
|
||||||
MOVD out+0(FP), OUT
|
|
||||||
MOVD inp+8(FP), INP
|
|
||||||
MOVD len+16(FP), LEN
|
|
||||||
MOVD key+24(FP), KEY
|
|
||||||
MOVD counter+32(FP), CNT
|
|
||||||
|
|
||||||
MOVD $·consts(SB), CONSTS // point to consts addr
|
|
||||||
|
|
||||||
MOVD $16, X0
|
|
||||||
MOVD $32, X1
|
|
||||||
MOVD $48, X2
|
|
||||||
MOVD $64, X3
|
|
||||||
MOVD $31, X4
|
|
||||||
MOVD $15, X5
|
|
||||||
|
|
||||||
// Load key
|
|
||||||
LVX (KEY)(R0), K1
|
|
||||||
LVSR (KEY)(R0), T0
|
|
||||||
LVX (KEY)(X0), K2
|
|
||||||
LVX (KEY)(X4), DD0
|
|
||||||
|
|
||||||
// Load counter
|
|
||||||
LVX (CNT)(R0), K3
|
|
||||||
LVSR (CNT)(R0), T1
|
|
||||||
LVX (CNT)(X5), DD1
|
|
||||||
|
|
||||||
// Load constants
|
|
||||||
LVX (CONSTS)(R0), K0
|
|
||||||
LVX (CONSTS)(X0), K5
|
|
||||||
LVX (CONSTS)(X1), FOUR
|
|
||||||
LVX (CONSTS)(X2), SIXTEEN
|
|
||||||
LVX (CONSTS)(X3), TWENTY4
|
|
||||||
|
|
||||||
// Align key and counter
|
|
||||||
VPERM K2, K1, T0, K1
|
|
||||||
VPERM DD0, K2, T0, K2
|
|
||||||
VPERM DD1, K3, T1, K3
|
|
||||||
|
|
||||||
// Load counter to GPR
|
|
||||||
MOVWZ 0(CNT), CNT0
|
|
||||||
MOVWZ 4(CNT), CNT1
|
|
||||||
MOVWZ 8(CNT), CNT2
|
|
||||||
MOVWZ 12(CNT), CNT3
|
|
||||||
|
|
||||||
// Adjust vectors for the initial state
|
|
||||||
VADDUWM K3, K5, K3
|
|
||||||
VADDUWM K3, K5, K4
|
|
||||||
VADDUWM K4, K5, K5
|
|
||||||
|
|
||||||
// Synthesized constants
|
|
||||||
VSPLTISW $-12, TWENTY
|
|
||||||
VSPLTISW $12, TWELVE
|
|
||||||
VSPLTISW $-7, TWENTY5
|
|
||||||
|
|
||||||
VXOR T0, T0, T0
|
|
||||||
VSPLTISW $-1, OUTMASK
|
|
||||||
LVSR (INP)(R0), INPPERM
|
|
||||||
LVSL (OUT)(R0), OUTPERM
|
|
||||||
VPERM OUTMASK, T0, OUTPERM, OUTMASK
|
|
||||||
|
|
||||||
loop_outer_vmx:
|
|
||||||
// Load constant
|
|
||||||
MOVD $0x61707865, CON0
|
|
||||||
MOVD $0x3320646e, CON1
|
|
||||||
MOVD $0x79622d32, CON2
|
|
||||||
MOVD $0x6b206574, CON3
|
|
||||||
|
|
||||||
VOR K0, K0, A0
|
|
||||||
VOR K0, K0, A1
|
|
||||||
VOR K0, K0, A2
|
|
||||||
VOR K1, K1, B0
|
|
||||||
|
|
||||||
MOVD $10, TEMP
|
|
||||||
|
|
||||||
// Load key to GPR
|
|
||||||
MOVWZ 0(KEY), X4
|
|
||||||
MOVWZ 4(KEY), X5
|
|
||||||
MOVWZ 8(KEY), X6
|
|
||||||
MOVWZ 12(KEY), X7
|
|
||||||
VOR K1, K1, B1
|
|
||||||
VOR K1, K1, B2
|
|
||||||
MOVWZ 16(KEY), X8
|
|
||||||
MOVWZ 0(CNT), X12
|
|
||||||
MOVWZ 20(KEY), X9
|
|
||||||
MOVWZ 4(CNT), X13
|
|
||||||
VOR K2, K2, C0
|
|
||||||
VOR K2, K2, C1
|
|
||||||
MOVWZ 24(KEY), X10
|
|
||||||
MOVWZ 8(CNT), X14
|
|
||||||
VOR K2, K2, C2
|
|
||||||
VOR K3, K3, D0
|
|
||||||
MOVWZ 28(KEY), X11
|
|
||||||
MOVWZ 12(CNT), X15
|
|
||||||
VOR K4, K4, D1
|
|
||||||
VOR K5, K5, D2
|
|
||||||
|
|
||||||
MOVD X4, TMP0
|
|
||||||
MOVD X5, TMP1
|
|
||||||
MOVD X6, TMP2
|
|
||||||
MOVD X7, TMP3
|
|
||||||
VSPLTISW $7, SEVEN
|
|
||||||
|
|
||||||
MOVD TEMP, CTR
|
|
||||||
|
|
||||||
loop_vmx:
|
|
||||||
// CRYPTOGAMS uses a macro to create a loop using perl. This isn't possible
|
|
||||||
// using assembly macros. Therefore, the macro expansion result was used
|
|
||||||
// in order to maintain the algorithm efficiency.
|
|
||||||
// This loop generates three keystream blocks using VMX instructions and,
|
|
||||||
// in parallel, one keystream block using scalar instructions.
|
|
||||||
ADD X4, X0, X0
|
|
||||||
ADD X5, X1, X1
|
|
||||||
VADDUWM A0, B0, A0
|
|
||||||
VADDUWM A1, B1, A1
|
|
||||||
ADD X6, X2, X2
|
|
||||||
ADD X7, X3, X3
|
|
||||||
VADDUWM A2, B2, A2
|
|
||||||
VXOR D0, A0, D0
|
|
||||||
XOR X0, X12, X12
|
|
||||||
XOR X1, X13, X13
|
|
||||||
VXOR D1, A1, D1
|
|
||||||
VXOR D2, A2, D2
|
|
||||||
XOR X2, X14, X14
|
|
||||||
XOR X3, X15, X15
|
|
||||||
VPERM D0, D0, SIXTEEN, D0
|
|
||||||
VPERM D1, D1, SIXTEEN, D1
|
|
||||||
ROTLW $16, X12, X12
|
|
||||||
ROTLW $16, X13, X13
|
|
||||||
VPERM D2, D2, SIXTEEN, D2
|
|
||||||
VADDUWM C0, D0, C0
|
|
||||||
ROTLW $16, X14, X14
|
|
||||||
ROTLW $16, X15, X15
|
|
||||||
VADDUWM C1, D1, C1
|
|
||||||
VADDUWM C2, D2, C2
|
|
||||||
ADD X12, X8, X8
|
|
||||||
ADD X13, X9, X9
|
|
||||||
VXOR B0, C0, T0
|
|
||||||
VXOR B1, C1, T1
|
|
||||||
ADD X14, X10, X10
|
|
||||||
ADD X15, X11, X11
|
|
||||||
VXOR B2, C2, T2
|
|
||||||
VRLW T0, TWELVE, B0
|
|
||||||
XOR X8, X4, X4
|
|
||||||
XOR X9, X5, X5
|
|
||||||
VRLW T1, TWELVE, B1
|
|
||||||
VRLW T2, TWELVE, B2
|
|
||||||
XOR X10, X6, X6
|
|
||||||
XOR X11, X7, X7
|
|
||||||
VADDUWM A0, B0, A0
|
|
||||||
VADDUWM A1, B1, A1
|
|
||||||
ROTLW $12, X4, X4
|
|
||||||
ROTLW $12, X5, X5
|
|
||||||
VADDUWM A2, B2, A2
|
|
||||||
VXOR D0, A0, D0
|
|
||||||
ROTLW $12, X6, X6
|
|
||||||
ROTLW $12, X7, X7
|
|
||||||
VXOR D1, A1, D1
|
|
||||||
VXOR D2, A2, D2
|
|
||||||
ADD X4, X0, X0
|
|
||||||
ADD X5, X1, X1
|
|
||||||
VPERM D0, D0, TWENTY4, D0
|
|
||||||
VPERM D1, D1, TWENTY4, D1
|
|
||||||
ADD X6, X2, X2
|
|
||||||
ADD X7, X3, X3
|
|
||||||
VPERM D2, D2, TWENTY4, D2
|
|
||||||
VADDUWM C0, D0, C0
|
|
||||||
XOR X0, X12, X12
|
|
||||||
XOR X1, X13, X13
|
|
||||||
VADDUWM C1, D1, C1
|
|
||||||
VADDUWM C2, D2, C2
|
|
||||||
XOR X2, X14, X14
|
|
||||||
XOR X3, X15, X15
|
|
||||||
VXOR B0, C0, T0
|
|
||||||
VXOR B1, C1, T1
|
|
||||||
ROTLW $8, X12, X12
|
|
||||||
ROTLW $8, X13, X13
|
|
||||||
VXOR B2, C2, T2
|
|
||||||
VRLW T0, SEVEN, B0
|
|
||||||
ROTLW $8, X14, X14
|
|
||||||
ROTLW $8, X15, X15
|
|
||||||
VRLW T1, SEVEN, B1
|
|
||||||
VRLW T2, SEVEN, B2
|
|
||||||
ADD X12, X8, X8
|
|
||||||
ADD X13, X9, X9
|
|
||||||
VSLDOI $8, C0, C0, C0
|
|
||||||
VSLDOI $8, C1, C1, C1
|
|
||||||
ADD X14, X10, X10
|
|
||||||
ADD X15, X11, X11
|
|
||||||
VSLDOI $8, C2, C2, C2
|
|
||||||
VSLDOI $12, B0, B0, B0
|
|
||||||
XOR X8, X4, X4
|
|
||||||
XOR X9, X5, X5
|
|
||||||
VSLDOI $12, B1, B1, B1
|
|
||||||
VSLDOI $12, B2, B2, B2
|
|
||||||
XOR X10, X6, X6
|
|
||||||
XOR X11, X7, X7
|
|
||||||
VSLDOI $4, D0, D0, D0
|
|
||||||
VSLDOI $4, D1, D1, D1
|
|
||||||
ROTLW $7, X4, X4
|
|
||||||
ROTLW $7, X5, X5
|
|
||||||
VSLDOI $4, D2, D2, D2
|
|
||||||
VADDUWM A0, B0, A0
|
|
||||||
ROTLW $7, X6, X6
|
|
||||||
ROTLW $7, X7, X7
|
|
||||||
VADDUWM A1, B1, A1
|
|
||||||
VADDUWM A2, B2, A2
|
|
||||||
ADD X5, X0, X0
|
|
||||||
ADD X6, X1, X1
|
|
||||||
VXOR D0, A0, D0
|
|
||||||
VXOR D1, A1, D1
|
|
||||||
ADD X7, X2, X2
|
|
||||||
ADD X4, X3, X3
|
|
||||||
VXOR D2, A2, D2
|
|
||||||
VPERM D0, D0, SIXTEEN, D0
|
|
||||||
XOR X0, X15, X15
|
|
||||||
XOR X1, X12, X12
|
|
||||||
VPERM D1, D1, SIXTEEN, D1
|
|
||||||
VPERM D2, D2, SIXTEEN, D2
|
|
||||||
XOR X2, X13, X13
|
|
||||||
XOR X3, X14, X14
|
|
||||||
VADDUWM C0, D0, C0
|
|
||||||
VADDUWM C1, D1, C1
|
|
||||||
ROTLW $16, X15, X15
|
|
||||||
ROTLW $16, X12, X12
|
|
||||||
VADDUWM C2, D2, C2
|
|
||||||
VXOR B0, C0, T0
|
|
||||||
ROTLW $16, X13, X13
|
|
||||||
ROTLW $16, X14, X14
|
|
||||||
VXOR B1, C1, T1
|
|
||||||
VXOR B2, C2, T2
|
|
||||||
ADD X15, X10, X10
|
|
||||||
ADD X12, X11, X11
|
|
||||||
VRLW T0, TWELVE, B0
|
|
||||||
VRLW T1, TWELVE, B1
|
|
||||||
ADD X13, X8, X8
|
|
||||||
ADD X14, X9, X9
|
|
||||||
VRLW T2, TWELVE, B2
|
|
||||||
VADDUWM A0, B0, A0
|
|
||||||
XOR X10, X5, X5
|
|
||||||
XOR X11, X6, X6
|
|
||||||
VADDUWM A1, B1, A1
|
|
||||||
VADDUWM A2, B2, A2
|
|
||||||
XOR X8, X7, X7
|
|
||||||
XOR X9, X4, X4
|
|
||||||
VXOR D0, A0, D0
|
|
||||||
VXOR D1, A1, D1
|
|
||||||
ROTLW $12, X5, X5
|
|
||||||
ROTLW $12, X6, X6
|
|
||||||
VXOR D2, A2, D2
|
|
||||||
VPERM D0, D0, TWENTY4, D0
|
|
||||||
ROTLW $12, X7, X7
|
|
||||||
ROTLW $12, X4, X4
|
|
||||||
VPERM D1, D1, TWENTY4, D1
|
|
||||||
VPERM D2, D2, TWENTY4, D2
|
|
||||||
ADD X5, X0, X0
|
|
||||||
ADD X6, X1, X1
|
|
||||||
VADDUWM C0, D0, C0
|
|
||||||
VADDUWM C1, D1, C1
|
|
||||||
ADD X7, X2, X2
|
|
||||||
ADD X4, X3, X3
|
|
||||||
VADDUWM C2, D2, C2
|
|
||||||
VXOR B0, C0, T0
|
|
||||||
XOR X0, X15, X15
|
|
||||||
XOR X1, X12, X12
|
|
||||||
VXOR B1, C1, T1
|
|
||||||
VXOR B2, C2, T2
|
|
||||||
XOR X2, X13, X13
|
|
||||||
XOR X3, X14, X14
|
|
||||||
VRLW T0, SEVEN, B0
|
|
||||||
VRLW T1, SEVEN, B1
|
|
||||||
ROTLW $8, X15, X15
|
|
||||||
ROTLW $8, X12, X12
|
|
||||||
VRLW T2, SEVEN, B2
|
|
||||||
VSLDOI $8, C0, C0, C0
|
|
||||||
ROTLW $8, X13, X13
|
|
||||||
ROTLW $8, X14, X14
|
|
||||||
VSLDOI $8, C1, C1, C1
|
|
||||||
VSLDOI $8, C2, C2, C2
|
|
||||||
ADD X15, X10, X10
|
|
||||||
ADD X12, X11, X11
|
|
||||||
VSLDOI $4, B0, B0, B0
|
|
||||||
VSLDOI $4, B1, B1, B1
|
|
||||||
ADD X13, X8, X8
|
|
||||||
ADD X14, X9, X9
|
|
||||||
VSLDOI $4, B2, B2, B2
|
|
||||||
VSLDOI $12, D0, D0, D0
|
|
||||||
XOR X10, X5, X5
|
|
||||||
XOR X11, X6, X6
|
|
||||||
VSLDOI $12, D1, D1, D1
|
|
||||||
VSLDOI $12, D2, D2, D2
|
|
||||||
XOR X8, X7, X7
|
|
||||||
XOR X9, X4, X4
|
|
||||||
ROTLW $7, X5, X5
|
|
||||||
ROTLW $7, X6, X6
|
|
||||||
ROTLW $7, X7, X7
|
|
||||||
ROTLW $7, X4, X4
|
|
||||||
BC 0x10, 0, loop_vmx
|
|
||||||
|
|
||||||
SUB $256, LEN, LEN
|
|
||||||
|
|
||||||
// Accumulate key block
|
|
||||||
ADD $0x61707865, X0, X0
|
|
||||||
ADD $0x3320646e, X1, X1
|
|
||||||
ADD $0x79622d32, X2, X2
|
|
||||||
ADD $0x6b206574, X3, X3
|
|
||||||
ADD TMP0, X4, X4
|
|
||||||
ADD TMP1, X5, X5
|
|
||||||
ADD TMP2, X6, X6
|
|
||||||
ADD TMP3, X7, X7
|
|
||||||
MOVWZ 16(KEY), TMP0
|
|
||||||
MOVWZ 20(KEY), TMP1
|
|
||||||
MOVWZ 24(KEY), TMP2
|
|
||||||
MOVWZ 28(KEY), TMP3
|
|
||||||
ADD TMP0, X8, X8
|
|
||||||
ADD TMP1, X9, X9
|
|
||||||
ADD TMP2, X10, X10
|
|
||||||
ADD TMP3, X11, X11
|
|
||||||
|
|
||||||
MOVWZ 12(CNT), TMP0
|
|
||||||
MOVWZ 8(CNT), TMP1
|
|
||||||
MOVWZ 4(CNT), TMP2
|
|
||||||
MOVWZ 0(CNT), TEMP
|
|
||||||
ADD TMP0, X15, X15
|
|
||||||
ADD TMP1, X14, X14
|
|
||||||
ADD TMP2, X13, X13
|
|
||||||
ADD TEMP, X12, X12
|
|
||||||
|
|
||||||
// Accumulate key block
|
|
||||||
VADDUWM A0, K0, A0
|
|
||||||
VADDUWM A1, K0, A1
|
|
||||||
VADDUWM A2, K0, A2
|
|
||||||
VADDUWM B0, K1, B0
|
|
||||||
VADDUWM B1, K1, B1
|
|
||||||
VADDUWM B2, K1, B2
|
|
||||||
VADDUWM C0, K2, C0
|
|
||||||
VADDUWM C1, K2, C1
|
|
||||||
VADDUWM C2, K2, C2
|
|
||||||
VADDUWM D0, K3, D0
|
|
||||||
VADDUWM D1, K4, D1
|
|
||||||
VADDUWM D2, K5, D2
|
|
||||||
|
|
||||||
// Increment counter
|
|
||||||
ADD $4, TEMP, TEMP
|
|
||||||
MOVW TEMP, 0(CNT)
|
|
||||||
|
|
||||||
VADDUWM K3, FOUR, K3
|
|
||||||
VADDUWM K4, FOUR, K4
|
|
||||||
VADDUWM K5, FOUR, K5
|
|
||||||
|
|
||||||
// XOR the input slice (INP) with the keystream, which is stored in GPRs (X0-X3).
|
|
||||||
|
|
||||||
// Load input (aligned or not)
|
|
||||||
MOVWZ 0(INP), TMP0
|
|
||||||
MOVWZ 4(INP), TMP1
|
|
||||||
MOVWZ 8(INP), TMP2
|
|
||||||
MOVWZ 12(INP), TMP3
|
|
||||||
|
|
||||||
// XOR with input
|
|
||||||
XOR TMP0, X0, X0
|
|
||||||
XOR TMP1, X1, X1
|
|
||||||
XOR TMP2, X2, X2
|
|
||||||
XOR TMP3, X3, X3
|
|
||||||
MOVWZ 16(INP), TMP0
|
|
||||||
MOVWZ 20(INP), TMP1
|
|
||||||
MOVWZ 24(INP), TMP2
|
|
||||||
MOVWZ 28(INP), TMP3
|
|
||||||
XOR TMP0, X4, X4
|
|
||||||
XOR TMP1, X5, X5
|
|
||||||
XOR TMP2, X6, X6
|
|
||||||
XOR TMP3, X7, X7
|
|
||||||
MOVWZ 32(INP), TMP0
|
|
||||||
MOVWZ 36(INP), TMP1
|
|
||||||
MOVWZ 40(INP), TMP2
|
|
||||||
MOVWZ 44(INP), TMP3
|
|
||||||
XOR TMP0, X8, X8
|
|
||||||
XOR TMP1, X9, X9
|
|
||||||
XOR TMP2, X10, X10
|
|
||||||
XOR TMP3, X11, X11
|
|
||||||
MOVWZ 48(INP), TMP0
|
|
||||||
MOVWZ 52(INP), TMP1
|
|
||||||
MOVWZ 56(INP), TMP2
|
|
||||||
MOVWZ 60(INP), TMP3
|
|
||||||
XOR TMP0, X12, X12
|
|
||||||
XOR TMP1, X13, X13
|
|
||||||
XOR TMP2, X14, X14
|
|
||||||
XOR TMP3, X15, X15
|
|
||||||
|
|
||||||
// Store output (aligned or not)
|
|
||||||
MOVW X0, 0(OUT)
|
|
||||||
MOVW X1, 4(OUT)
|
|
||||||
MOVW X2, 8(OUT)
|
|
||||||
MOVW X3, 12(OUT)
|
|
||||||
|
|
||||||
ADD $64, INP, INP // INP points to the end of the slice for the alignment code below
|
|
||||||
|
|
||||||
MOVW X4, 16(OUT)
|
|
||||||
MOVD $16, TMP0
|
|
||||||
MOVW X5, 20(OUT)
|
|
||||||
MOVD $32, TMP1
|
|
||||||
MOVW X6, 24(OUT)
|
|
||||||
MOVD $48, TMP2
|
|
||||||
MOVW X7, 28(OUT)
|
|
||||||
MOVD $64, TMP3
|
|
||||||
MOVW X8, 32(OUT)
|
|
||||||
MOVW X9, 36(OUT)
|
|
||||||
MOVW X10, 40(OUT)
|
|
||||||
MOVW X11, 44(OUT)
|
|
||||||
MOVW X12, 48(OUT)
|
|
||||||
MOVW X13, 52(OUT)
|
|
||||||
MOVW X14, 56(OUT)
|
|
||||||
MOVW X15, 60(OUT)
|
|
||||||
ADD $64, OUT, OUT
|
|
||||||
|
|
||||||
// Load input
|
|
||||||
LVX (INP)(R0), DD0
|
|
||||||
LVX (INP)(TMP0), DD1
|
|
||||||
LVX (INP)(TMP1), DD2
|
|
||||||
LVX (INP)(TMP2), DD3
|
|
||||||
LVX (INP)(TMP3), DD4
|
|
||||||
ADD $64, INP, INP
|
|
||||||
|
|
||||||
VPERM DD1, DD0, INPPERM, DD0 // Align input
|
|
||||||
VPERM DD2, DD1, INPPERM, DD1
|
|
||||||
VPERM DD3, DD2, INPPERM, DD2
|
|
||||||
VPERM DD4, DD3, INPPERM, DD3
|
|
||||||
VXOR A0, DD0, A0 // XOR with input
|
|
||||||
VXOR B0, DD1, B0
|
|
||||||
LVX (INP)(TMP0), DD1 // Keep loading input
|
|
||||||
VXOR C0, DD2, C0
|
|
||||||
LVX (INP)(TMP1), DD2
|
|
||||||
VXOR D0, DD3, D0
|
|
||||||
LVX (INP)(TMP2), DD3
|
|
||||||
LVX (INP)(TMP3), DD0
|
|
||||||
ADD $64, INP, INP
|
|
||||||
MOVD $63, TMP3 // 63 is not a typo
|
|
||||||
VPERM A0, A0, OUTPERM, A0
|
|
||||||
VPERM B0, B0, OUTPERM, B0
|
|
||||||
VPERM C0, C0, OUTPERM, C0
|
|
||||||
VPERM D0, D0, OUTPERM, D0
|
|
||||||
|
|
||||||
VPERM DD1, DD4, INPPERM, DD4 // Align input
|
|
||||||
VPERM DD2, DD1, INPPERM, DD1
|
|
||||||
VPERM DD3, DD2, INPPERM, DD2
|
|
||||||
VPERM DD0, DD3, INPPERM, DD3
|
|
||||||
VXOR A1, DD4, A1
|
|
||||||
VXOR B1, DD1, B1
|
|
||||||
LVX (INP)(TMP0), DD1 // Keep loading
|
|
||||||
VXOR C1, DD2, C1
|
|
||||||
LVX (INP)(TMP1), DD2
|
|
||||||
VXOR D1, DD3, D1
|
|
||||||
LVX (INP)(TMP2), DD3
|
|
||||||
|
|
||||||
// Note that the LVX address is always rounded down to the nearest 16-byte
|
|
||||||
// boundary, and that it always points to at most 15 bytes beyond the end of
|
|
||||||
// the slice, so we cannot cross a page boundary.
|
|
||||||
LVX (INP)(TMP3), DD4 // Redundant in aligned case.
|
|
||||||
ADD $64, INP, INP
|
|
||||||
VPERM A1, A1, OUTPERM, A1 // Pre-misalign output
|
|
||||||
VPERM B1, B1, OUTPERM, B1
|
|
||||||
VPERM C1, C1, OUTPERM, C1
|
|
||||||
VPERM D1, D1, OUTPERM, D1
|
|
||||||
|
|
||||||
VPERM DD1, DD0, INPPERM, DD0 // Align Input
|
|
||||||
VPERM DD2, DD1, INPPERM, DD1
|
|
||||||
VPERM DD3, DD2, INPPERM, DD2
|
|
||||||
VPERM DD4, DD3, INPPERM, DD3
|
|
||||||
VXOR A2, DD0, A2
|
|
||||||
VXOR B2, DD1, B2
|
|
||||||
VXOR C2, DD2, C2
|
|
||||||
VXOR D2, DD3, D2
|
|
||||||
VPERM A2, A2, OUTPERM, A2
|
|
||||||
VPERM B2, B2, OUTPERM, B2
|
|
||||||
VPERM C2, C2, OUTPERM, C2
|
|
||||||
VPERM D2, D2, OUTPERM, D2
|
|
||||||
|
|
||||||
ANDCC $15, OUT, X1 // Is out aligned?
|
|
||||||
MOVD OUT, X0
|
|
||||||
|
|
||||||
VSEL A0, B0, OUTMASK, DD0 // Collect pre-misaligned output
|
|
||||||
VSEL B0, C0, OUTMASK, DD1
|
|
||||||
VSEL C0, D0, OUTMASK, DD2
|
|
||||||
VSEL D0, A1, OUTMASK, DD3
|
|
||||||
VSEL A1, B1, OUTMASK, B0
|
|
||||||
VSEL B1, C1, OUTMASK, C0
|
|
||||||
VSEL C1, D1, OUTMASK, D0
|
|
||||||
VSEL D1, A2, OUTMASK, A1
|
|
||||||
VSEL A2, B2, OUTMASK, B1
|
|
||||||
VSEL B2, C2, OUTMASK, C1
|
|
||||||
VSEL C2, D2, OUTMASK, D1
|
|
||||||
|
|
||||||
STVX DD0, (OUT+TMP0)
|
|
||||||
STVX DD1, (OUT+TMP1)
|
|
||||||
STVX DD2, (OUT+TMP2)
|
|
||||||
ADD $64, OUT, OUT
|
|
||||||
STVX DD3, (OUT+R0)
|
|
||||||
STVX B0, (OUT+TMP0)
|
|
||||||
STVX C0, (OUT+TMP1)
|
|
||||||
STVX D0, (OUT+TMP2)
|
|
||||||
ADD $64, OUT, OUT
|
|
||||||
STVX A1, (OUT+R0)
|
|
||||||
STVX B1, (OUT+TMP0)
|
|
||||||
STVX C1, (OUT+TMP1)
|
|
||||||
STVX D1, (OUT+TMP2)
|
|
||||||
ADD $64, OUT, OUT
|
|
||||||
|
|
||||||
BEQ aligned_vmx
|
|
||||||
|
|
||||||
SUB X1, OUT, X2 // in misaligned case edges
|
|
||||||
MOVD $0, X3 // are written byte-by-byte
|
|
||||||
|
|
||||||
unaligned_tail_vmx:
|
|
||||||
STVEBX D2, (X2+X3)
|
|
||||||
ADD $1, X3, X3
|
|
||||||
CMPW X3, X1
|
|
||||||
BNE unaligned_tail_vmx
|
|
||||||
SUB X1, X0, X2
|
|
||||||
|
|
||||||
unaligned_head_vmx:
|
|
||||||
STVEBX A0, (X2+X1)
|
|
||||||
CMPW X1, $15
|
|
||||||
ADD $1, X1, X1
|
|
||||||
BNE unaligned_head_vmx
|
|
||||||
|
|
||||||
CMPU LEN, $255 // done with 256-byte block yet?
|
|
||||||
BGT loop_outer_vmx
|
|
||||||
|
|
||||||
JMP done_vmx
|
|
||||||
|
|
||||||
aligned_vmx:
|
|
||||||
STVX A0, (X0+R0)
|
|
||||||
CMPU LEN, $255 // done with 256-byte block yet?
|
|
||||||
BGT loop_outer_vmx
|
|
||||||
|
|
||||||
done_vmx:
|
|
||||||
RET
|
|
31
vendor/golang.org/x/crypto/internal/chacha20/chacha_arm64.go
generated
vendored
31
vendor/golang.org/x/crypto/internal/chacha20/chacha_arm64.go
generated
vendored
@ -1,31 +0,0 @@
|
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build go1.11
|
|
||||||
// +build !gccgo
|
|
||||||
|
|
||||||
package chacha20
|
|
||||||
|
|
||||||
const (
|
|
||||||
haveAsm = true
|
|
||||||
bufSize = 256
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
|
|
||||||
|
|
||||||
func (c *Cipher) xorKeyStreamAsm(dst, src []byte) {
|
|
||||||
|
|
||||||
if len(src) >= bufSize {
|
|
||||||
xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(src)%bufSize != 0 {
|
|
||||||
i := len(src) - len(src)%bufSize
|
|
||||||
c.buf = [bufSize]byte{}
|
|
||||||
copy(c.buf[:], src[i:])
|
|
||||||
xorKeyStreamVX(c.buf[:], c.buf[:], &c.key, &c.nonce, &c.counter)
|
|
||||||
c.len = bufSize - copy(dst[i:], c.buf[:len(src)%bufSize])
|
|
||||||
}
|
|
||||||
}
|
|
264
vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go
generated
vendored
264
vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go
generated
vendored
@ -1,264 +0,0 @@
|
|||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package ChaCha20 implements the core ChaCha20 function as specified
|
|
||||||
// in https://tools.ietf.org/html/rfc7539#section-2.3.
|
|
||||||
package chacha20
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/cipher"
|
|
||||||
"encoding/binary"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/internal/subtle"
|
|
||||||
)
|
|
||||||
|
|
||||||
// assert that *Cipher implements cipher.Stream
|
|
||||||
var _ cipher.Stream = (*Cipher)(nil)
|
|
||||||
|
|
||||||
// Cipher is a stateful instance of ChaCha20 using a particular key
|
|
||||||
// and nonce. A *Cipher implements the cipher.Stream interface.
|
|
||||||
type Cipher struct {
|
|
||||||
key [8]uint32
|
|
||||||
counter uint32 // incremented after each block
|
|
||||||
nonce [3]uint32
|
|
||||||
buf [bufSize]byte // buffer for unused keystream bytes
|
|
||||||
len int // number of unused keystream bytes at end of buf
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates a new ChaCha20 stream cipher with the given key and nonce.
|
|
||||||
// The initial counter value is set to 0.
|
|
||||||
func New(key [8]uint32, nonce [3]uint32) *Cipher {
|
|
||||||
return &Cipher{key: key, nonce: nonce}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChaCha20 constants spelling "expand 32-byte k"
|
|
||||||
const (
|
|
||||||
j0 uint32 = 0x61707865
|
|
||||||
j1 uint32 = 0x3320646e
|
|
||||||
j2 uint32 = 0x79622d32
|
|
||||||
j3 uint32 = 0x6b206574
|
|
||||||
)
|
|
||||||
|
|
||||||
func quarterRound(a, b, c, d uint32) (uint32, uint32, uint32, uint32) {
|
|
||||||
a += b
|
|
||||||
d ^= a
|
|
||||||
d = (d << 16) | (d >> 16)
|
|
||||||
c += d
|
|
||||||
b ^= c
|
|
||||||
b = (b << 12) | (b >> 20)
|
|
||||||
a += b
|
|
||||||
d ^= a
|
|
||||||
d = (d << 8) | (d >> 24)
|
|
||||||
c += d
|
|
||||||
b ^= c
|
|
||||||
b = (b << 7) | (b >> 25)
|
|
||||||
return a, b, c, d
|
|
||||||
}
|
|
||||||
|
|
||||||
// XORKeyStream XORs each byte in the given slice with a byte from the
|
|
||||||
// cipher's key stream. Dst and src must overlap entirely or not at all.
|
|
||||||
//
|
|
||||||
// If len(dst) < len(src), XORKeyStream will panic. It is acceptable
|
|
||||||
// to pass a dst bigger than src, and in that case, XORKeyStream will
|
|
||||||
// only update dst[:len(src)] and will not touch the rest of dst.
|
|
||||||
//
|
|
||||||
// Multiple calls to XORKeyStream behave as if the concatenation of
|
|
||||||
// the src buffers was passed in a single run. That is, Cipher
|
|
||||||
// maintains state and does not reset at each XORKeyStream call.
|
|
||||||
func (s *Cipher) XORKeyStream(dst, src []byte) {
|
|
||||||
if len(dst) < len(src) {
|
|
||||||
panic("chacha20: output smaller than input")
|
|
||||||
}
|
|
||||||
if subtle.InexactOverlap(dst[:len(src)], src) {
|
|
||||||
panic("chacha20: invalid buffer overlap")
|
|
||||||
}
|
|
||||||
|
|
||||||
// xor src with buffered keystream first
|
|
||||||
if s.len != 0 {
|
|
||||||
buf := s.buf[len(s.buf)-s.len:]
|
|
||||||
if len(src) < len(buf) {
|
|
||||||
buf = buf[:len(src)]
|
|
||||||
}
|
|
||||||
td, ts := dst[:len(buf)], src[:len(buf)] // BCE hint
|
|
||||||
for i, b := range buf {
|
|
||||||
td[i] = ts[i] ^ b
|
|
||||||
}
|
|
||||||
s.len -= len(buf)
|
|
||||||
if s.len != 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s.buf = [len(s.buf)]byte{} // zero the empty buffer
|
|
||||||
src = src[len(buf):]
|
|
||||||
dst = dst[len(buf):]
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(src) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if haveAsm {
|
|
||||||
if uint64(len(src))+uint64(s.counter)*64 > (1<<38)-64 {
|
|
||||||
panic("chacha20: counter overflow")
|
|
||||||
}
|
|
||||||
s.xorKeyStreamAsm(dst, src)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// set up a 64-byte buffer to pad out the final block if needed
|
|
||||||
// (hoisted out of the main loop to avoid spills)
|
|
||||||
rem := len(src) % 64 // length of final block
|
|
||||||
fin := len(src) - rem // index of final block
|
|
||||||
if rem > 0 {
|
|
||||||
copy(s.buf[len(s.buf)-64:], src[fin:])
|
|
||||||
}
|
|
||||||
|
|
||||||
// pre-calculate most of the first round
|
|
||||||
s1, s5, s9, s13 := quarterRound(j1, s.key[1], s.key[5], s.nonce[0])
|
|
||||||
s2, s6, s10, s14 := quarterRound(j2, s.key[2], s.key[6], s.nonce[1])
|
|
||||||
s3, s7, s11, s15 := quarterRound(j3, s.key[3], s.key[7], s.nonce[2])
|
|
||||||
|
|
||||||
n := len(src)
|
|
||||||
src, dst = src[:n:n], dst[:n:n] // BCE hint
|
|
||||||
for i := 0; i < n; i += 64 {
|
|
||||||
// calculate the remainder of the first round
|
|
||||||
s0, s4, s8, s12 := quarterRound(j0, s.key[0], s.key[4], s.counter)
|
|
||||||
|
|
||||||
// execute the second round
|
|
||||||
x0, x5, x10, x15 := quarterRound(s0, s5, s10, s15)
|
|
||||||
x1, x6, x11, x12 := quarterRound(s1, s6, s11, s12)
|
|
||||||
x2, x7, x8, x13 := quarterRound(s2, s7, s8, s13)
|
|
||||||
x3, x4, x9, x14 := quarterRound(s3, s4, s9, s14)
|
|
||||||
|
|
||||||
// execute the remaining 18 rounds
|
|
||||||
for i := 0; i < 9; i++ {
|
|
||||||
x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12)
|
|
||||||
x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13)
|
|
||||||
x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14)
|
|
||||||
x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15)
|
|
||||||
|
|
||||||
x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15)
|
|
||||||
x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12)
|
|
||||||
x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13)
|
|
||||||
x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14)
|
|
||||||
}
|
|
||||||
|
|
||||||
x0 += j0
|
|
||||||
x1 += j1
|
|
||||||
x2 += j2
|
|
||||||
x3 += j3
|
|
||||||
|
|
||||||
x4 += s.key[0]
|
|
||||||
x5 += s.key[1]
|
|
||||||
x6 += s.key[2]
|
|
||||||
x7 += s.key[3]
|
|
||||||
x8 += s.key[4]
|
|
||||||
x9 += s.key[5]
|
|
||||||
x10 += s.key[6]
|
|
||||||
x11 += s.key[7]
|
|
||||||
|
|
||||||
x12 += s.counter
|
|
||||||
x13 += s.nonce[0]
|
|
||||||
x14 += s.nonce[1]
|
|
||||||
x15 += s.nonce[2]
|
|
||||||
|
|
||||||
// increment the counter
|
|
||||||
s.counter += 1
|
|
||||||
if s.counter == 0 {
|
|
||||||
panic("chacha20: counter overflow")
|
|
||||||
}
|
|
||||||
|
|
||||||
// pad to 64 bytes if needed
|
|
||||||
in, out := src[i:], dst[i:]
|
|
||||||
if i == fin {
|
|
||||||
// src[fin:] has already been copied into s.buf before
|
|
||||||
// the main loop
|
|
||||||
in, out = s.buf[len(s.buf)-64:], s.buf[len(s.buf)-64:]
|
|
||||||
}
|
|
||||||
in, out = in[:64], out[:64] // BCE hint
|
|
||||||
|
|
||||||
// XOR the key stream with the source and write out the result
|
|
||||||
xor(out[0:], in[0:], x0)
|
|
||||||
xor(out[4:], in[4:], x1)
|
|
||||||
xor(out[8:], in[8:], x2)
|
|
||||||
xor(out[12:], in[12:], x3)
|
|
||||||
xor(out[16:], in[16:], x4)
|
|
||||||
xor(out[20:], in[20:], x5)
|
|
||||||
xor(out[24:], in[24:], x6)
|
|
||||||
xor(out[28:], in[28:], x7)
|
|
||||||
xor(out[32:], in[32:], x8)
|
|
||||||
xor(out[36:], in[36:], x9)
|
|
||||||
xor(out[40:], in[40:], x10)
|
|
||||||
xor(out[44:], in[44:], x11)
|
|
||||||
xor(out[48:], in[48:], x12)
|
|
||||||
xor(out[52:], in[52:], x13)
|
|
||||||
xor(out[56:], in[56:], x14)
|
|
||||||
xor(out[60:], in[60:], x15)
|
|
||||||
}
|
|
||||||
// copy any trailing bytes out of the buffer and into dst
|
|
||||||
if rem != 0 {
|
|
||||||
s.len = 64 - rem
|
|
||||||
copy(dst[fin:], s.buf[len(s.buf)-64:])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Advance discards bytes in the key stream until the next 64 byte block
|
|
||||||
// boundary is reached and updates the counter accordingly. If the key
|
|
||||||
// stream is already at a block boundary no bytes will be discarded and
|
|
||||||
// the counter will be unchanged.
|
|
||||||
func (s *Cipher) Advance() {
|
|
||||||
s.len -= s.len % 64
|
|
||||||
if s.len == 0 {
|
|
||||||
s.buf = [len(s.buf)]byte{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// XORKeyStream crypts bytes from in to out using the given key and counters.
|
|
||||||
// In and out must overlap entirely or not at all. Counter contains the raw
|
|
||||||
// ChaCha20 counter bytes (i.e. block counter followed by nonce).
|
|
||||||
func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
|
|
||||||
s := Cipher{
|
|
||||||
key: [8]uint32{
|
|
||||||
binary.LittleEndian.Uint32(key[0:4]),
|
|
||||||
binary.LittleEndian.Uint32(key[4:8]),
|
|
||||||
binary.LittleEndian.Uint32(key[8:12]),
|
|
||||||
binary.LittleEndian.Uint32(key[12:16]),
|
|
||||||
binary.LittleEndian.Uint32(key[16:20]),
|
|
||||||
binary.LittleEndian.Uint32(key[20:24]),
|
|
||||||
binary.LittleEndian.Uint32(key[24:28]),
|
|
||||||
binary.LittleEndian.Uint32(key[28:32]),
|
|
||||||
},
|
|
||||||
nonce: [3]uint32{
|
|
||||||
binary.LittleEndian.Uint32(counter[4:8]),
|
|
||||||
binary.LittleEndian.Uint32(counter[8:12]),
|
|
||||||
binary.LittleEndian.Uint32(counter[12:16]),
|
|
||||||
},
|
|
||||||
counter: binary.LittleEndian.Uint32(counter[0:4]),
|
|
||||||
}
|
|
||||||
s.XORKeyStream(out, in)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HChaCha20 uses the ChaCha20 core to generate a derived key from a key and a
|
|
||||||
// nonce. It should only be used as part of the XChaCha20 construction.
|
|
||||||
func HChaCha20(key *[8]uint32, nonce *[4]uint32) [8]uint32 {
|
|
||||||
x0, x1, x2, x3 := j0, j1, j2, j3
|
|
||||||
x4, x5, x6, x7 := key[0], key[1], key[2], key[3]
|
|
||||||
x8, x9, x10, x11 := key[4], key[5], key[6], key[7]
|
|
||||||
x12, x13, x14, x15 := nonce[0], nonce[1], nonce[2], nonce[3]
|
|
||||||
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12)
|
|
||||||
x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13)
|
|
||||||
x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14)
|
|
||||||
x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15)
|
|
||||||
|
|
||||||
x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15)
|
|
||||||
x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12)
|
|
||||||
x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13)
|
|
||||||
x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14)
|
|
||||||
}
|
|
||||||
|
|
||||||
var out [8]uint32
|
|
||||||
out[0], out[1], out[2], out[3] = x0, x1, x2, x3
|
|
||||||
out[4], out[5], out[6], out[7] = x12, x13, x14, x15
|
|
||||||
return out
|
|
||||||
}
|
|
16
vendor/golang.org/x/crypto/internal/chacha20/chacha_noasm.go
generated
vendored
16
vendor/golang.org/x/crypto/internal/chacha20/chacha_noasm.go
generated
vendored
@ -1,16 +0,0 @@
|
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build !ppc64le,!arm64,!s390x arm64,!go1.11 gccgo appengine
|
|
||||||
|
|
||||||
package chacha20
|
|
||||||
|
|
||||||
const (
|
|
||||||
bufSize = 64
|
|
||||||
haveAsm = false
|
|
||||||
)
|
|
||||||
|
|
||||||
func (*Cipher) xorKeyStreamAsm(dst, src []byte) {
|
|
||||||
panic("not implemented")
|
|
||||||
}
|
|
52
vendor/golang.org/x/crypto/internal/chacha20/chacha_ppc64le.go
generated
vendored
52
vendor/golang.org/x/crypto/internal/chacha20/chacha_ppc64le.go
generated
vendored
@ -1,52 +0,0 @@
|
|||||||
// Copyright 2019 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ppc64le,!gccgo,!appengine
|
|
||||||
|
|
||||||
package chacha20
|
|
||||||
|
|
||||||
import "encoding/binary"
|
|
||||||
|
|
||||||
const (
|
|
||||||
bufSize = 256
|
|
||||||
haveAsm = true
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
func chaCha20_ctr32_vmx(out, inp *byte, len int, key *[8]uint32, counter *uint32)
|
|
||||||
|
|
||||||
func (c *Cipher) xorKeyStreamAsm(dst, src []byte) {
|
|
||||||
if len(src) >= bufSize {
|
|
||||||
chaCha20_ctr32_vmx(&dst[0], &src[0], len(src)-len(src)%bufSize, &c.key, &c.counter)
|
|
||||||
}
|
|
||||||
if len(src)%bufSize != 0 {
|
|
||||||
chaCha20_ctr32_vmx(&c.buf[0], &c.buf[0], bufSize, &c.key, &c.counter)
|
|
||||||
start := len(src) - len(src)%bufSize
|
|
||||||
ts, td, tb := src[start:], dst[start:], c.buf[:]
|
|
||||||
// Unroll loop to XOR 32 bytes per iteration.
|
|
||||||
for i := 0; i < len(ts)-32; i += 32 {
|
|
||||||
td, tb = td[:len(ts)], tb[:len(ts)] // bounds check elimination
|
|
||||||
s0 := binary.LittleEndian.Uint64(ts[0:8])
|
|
||||||
s1 := binary.LittleEndian.Uint64(ts[8:16])
|
|
||||||
s2 := binary.LittleEndian.Uint64(ts[16:24])
|
|
||||||
s3 := binary.LittleEndian.Uint64(ts[24:32])
|
|
||||||
b0 := binary.LittleEndian.Uint64(tb[0:8])
|
|
||||||
b1 := binary.LittleEndian.Uint64(tb[8:16])
|
|
||||||
b2 := binary.LittleEndian.Uint64(tb[16:24])
|
|
||||||
b3 := binary.LittleEndian.Uint64(tb[24:32])
|
|
||||||
binary.LittleEndian.PutUint64(td[0:8], s0^b0)
|
|
||||||
binary.LittleEndian.PutUint64(td[8:16], s1^b1)
|
|
||||||
binary.LittleEndian.PutUint64(td[16:24], s2^b2)
|
|
||||||
binary.LittleEndian.PutUint64(td[24:32], s3^b3)
|
|
||||||
ts, td, tb = ts[32:], td[32:], tb[32:]
|
|
||||||
}
|
|
||||||
td, tb = td[:len(ts)], tb[:len(ts)] // bounds check elimination
|
|
||||||
for i, v := range ts {
|
|
||||||
td[i] = tb[i] ^ v
|
|
||||||
}
|
|
||||||
c.len = bufSize - (len(src) % bufSize)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user