Update Dependencies #390
43
go.mod
43
go.mod
|
@ -6,34 +6,35 @@ require (
|
|||
code.gitea.io/gitea-vet v0.2.1
|
||||
code.gitea.io/sdk/gitea v0.15.0
|
||||
gitea.com/noerw/unidiff-comments v0.0.0-20201219085024-64aec5658f2b
|
||||
github.com/AlecAivazis/survey/v2 v2.2.8
|
||||
github.com/Microsoft/go-winio v0.4.16 // indirect
|
||||
github.com/adrg/xdg v0.3.1
|
||||
github.com/araddon/dateparse v0.0.0-20210207001429-0eec95c9db7e
|
||||
github.com/charmbracelet/glamour v0.2.0
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
|
||||
github.com/go-git/go-git/v5 v5.2.0
|
||||
github.com/AlecAivazis/survey/v2 v2.3.1
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210707164159-52430bf6b52c // indirect
|
||||
github.com/adrg/xdg v0.3.3
|
||||
github.com/alecthomas/chroma v0.9.2 // indirect
|
||||
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de
|
||||
github.com/charmbracelet/glamour v0.3.0
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
|
||||
github.com/go-git/go-git/v5 v5.4.2
|
||||
github.com/hashicorp/go-version v1.3.0 // indirect
|
||||
github.com/imdario/mergo v0.3.11 // indirect
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/kevinburke/ssh_config v1.1.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.8 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||
github.com/muesli/termenv v0.7.4
|
||||
github.com/microcosm-cc/bluemonday v1.0.15 // indirect
|
||||
github.com/muesli/reflow v0.3.0 // indirect
|
||||
github.com/muesli/termenv v0.9.0
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sergi/go-diff v1.2.0 // indirect
|
||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/urfave/cli/v2 v2.3.0
|
||||
github.com/xanzy/ssh-agent v0.3.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect
|
||||
golang.org/x/sys v0.0.0-20210305034016-7844c3c200c3 // indirect
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect
|
||||
golang.org/x/text v0.3.5 // indirect
|
||||
golang.org/x/tools v0.1.0 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.1 // indirect
|
||||
github.com/yuin/goldmark v1.4.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d // indirect
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf // indirect
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/tools v0.1.5 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
||||
replace github.com/charmbracelet/glamour => github.com/noerw/glamour v0.2.1-0.20210305125354-f0a29f1de0c2
|
||||
replace github.com/charmbracelet/glamour => github.com/noerw/glamour v0.3.0-patch
|
||||
|
|
169
go.sum
169
go.sum
|
@ -4,22 +4,27 @@ code.gitea.io/sdk/gitea v0.15.0 h1:tsNhxDM/2N1Ohv1Xq5UWrht/esg0WmtRj4wsHVHriTg=
|
|||
code.gitea.io/sdk/gitea v0.15.0/go.mod h1:klY2LVI3s3NChzIk/MzMn7G1FHrfU7qd63iSMVoHRBA=
|
||||
gitea.com/noerw/unidiff-comments v0.0.0-20201219085024-64aec5658f2b h1:CLYsMGcGLohESQDMth+RgJ4cB3CCHToxnj0zBbvB3sE=
|
||||
gitea.com/noerw/unidiff-comments v0.0.0-20201219085024-64aec5658f2b/go.mod h1:Fc8iyPm4NINRWujeIk2bTfcbGc4ZYY29/oMAAGcr4qI=
|
||||
github.com/AlecAivazis/survey/v2 v2.2.8 h1:TgxCwybKdBckmC+/P9/5h49rw/nAHe/itZL0dgHs+Q0=
|
||||
github.com/AlecAivazis/survey/v2 v2.2.8/go.mod h1:9DYvHgXtiXm6nCn+jXnOXLKbH+Yo9u8fAS/SduGdoPk=
|
||||
github.com/AlecAivazis/survey/v2 v2.3.1 h1:lzkuHA60pER7L4eYL8qQJor4bUWlJe4V0gqAT19tdOA=
|
||||
github.com/AlecAivazis/survey/v2 v2.3.1/go.mod h1:TH2kPCDU3Kqq7pLbnCWwZXDBjnhZtmsCle5EiYDJ2fg=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk=
|
||||
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
|
||||
github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU=
|
||||
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
|
||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
|
||||
github.com/adrg/xdg v0.3.1 h1:uIyL9BYfXaFgDyVRKE8wjtm6ETQULweQqTofphEFJYY=
|
||||
github.com/adrg/xdg v0.3.1/go.mod h1:7I2hH/IT30IsupOpKZ5ue7/qNi3CoKzD6tL3HwpaRMQ=
|
||||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
|
||||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210707164159-52430bf6b52c h1:FP7mMdsXy0ybzar1sJeIcZtaJka0U/ZmLTW4wRpolYk=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210707164159-52430bf6b52c/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
|
||||
github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
|
||||
github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
|
||||
github.com/adrg/xdg v0.3.3 h1:s/tV7MdqQnzB1nKY8aqHvAMD+uCiuEDzVB5HLRY849U=
|
||||
github.com/adrg/xdg v0.3.3/go.mod h1:61xAR2VZcggl2St4O9ohF5qCKe08+JDmE4VNzPFQvOQ=
|
||||
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U=
|
||||
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
|
||||
github.com/alecthomas/chroma v0.8.1 h1:ym20sbvyC6RXz45u4qDglcgr8E313oPROshcuCHqiEE=
|
||||
github.com/alecthomas/chroma v0.8.1/go.mod h1:sko8vR34/90zvl5QdcUdvzL3J8NKjAUx9va9jPuFNoM=
|
||||
github.com/alecthomas/chroma v0.8.2/go.mod h1:sko8vR34/90zvl5QdcUdvzL3J8NKjAUx9va9jPuFNoM=
|
||||
github.com/alecthomas/chroma v0.9.2 h1:yU1sE2+TZbLIQPMk30SolL2Hn53SR/Pv750f7qZ/XMs=
|
||||
github.com/alecthomas/chroma v0.9.2/go.mod h1:eMuEnpA18XbG/WhOWtCzJHS7WqEtDAI+HxdwoW0nVSk=
|
||||
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo=
|
||||
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
|
||||
github.com/alecthomas/kong v0.2.4/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE=
|
||||
|
@ -27,25 +32,25 @@ github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkx
|
|||
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/araddon/dateparse v0.0.0-20210207001429-0eec95c9db7e h1:OjdSMCht0ZVX7IH0nTdf00xEustvbtUGRgMh3gbdmOg=
|
||||
github.com/araddon/dateparse v0.0.0-20210207001429-0eec95c9db7e/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw=
|
||||
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhPwqqXc4/vE0f7GvRjuAsbW+HOIe8KnA=
|
||||
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
||||
github.com/chris-ramon/douceur v0.2.0 h1:IDMEdxlEUUBYBKE4z/mJnFyVXox+MjuEVDJNN27glkU=
|
||||
github.com/chris-ramon/douceur v0.2.0/go.mod h1:wDW5xjJdeoMm1mRt4sD4c/LbF/mWdEpRXQKjTR8nIBE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
|
||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk=
|
||||
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
|
||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
|
||||
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
|
||||
|
@ -54,12 +59,13 @@ github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
|
|||
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
|
||||
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
|
||||
github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM=
|
||||
github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 h1:PbKy9zOy4aAKrJ5pibIRpVO2BXnK1Tlcg+caKI7Ox5M=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
|
||||
github.com/go-git/go-git/v5 v5.2.0 h1:YPBLG/3UK1we1ohRkncLjaXWLW+HKp5QNM/jTli2JgI=
|
||||
github.com/go-git/go-git/v5 v5.2.0/go.mod h1:kh02eMX+wdqqxgNMEyq8YgwlIOsDOa9homkUq1PoTMs=
|
||||
github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||
github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34=
|
||||
github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.2.1 h1:n9gGL1Ct/yIw+nfsfr8s4+sbhT+Ncu2SubfXjIWgci8=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0=
|
||||
github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4=
|
||||
github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc=
|
||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
|
||||
|
@ -69,55 +75,60 @@ github.com/hashicorp/go-version v1.3.0 h1:McDWVJIU/y+u1BRV06dPaLfLCaT7fUTJLp5r04
|
|||
github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ=
|
||||
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
|
||||
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
|
||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
|
||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kevinburke/ssh_config v1.1.0 h1:pH/t1WS9NzT8go394IqZeJTMHVm6Cr6ZJ6AQ+mdNo/o=
|
||||
github.com/kevinburke/ssh_config v1.1.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.4 h1:5Myjjh3JY/NaAi4IsUbHADytDyl1VE1Y9PXDlL+P/VQ=
|
||||
github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
|
||||
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
|
||||
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg=
|
||||
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/microcosm-cc/bluemonday v1.0.4 h1:p0L+CTpo/PLFdkoPcJemLXG+fpMD7pYOoDEq1axMbGg=
|
||||
github.com/microcosm-cc/bluemonday v1.0.4/go.mod h1:8iwZnFn2CDDNZ0r6UXhF4xawGvzaqzCRa1n3/lO3W2w=
|
||||
github.com/microcosm-cc/bluemonday v1.0.6/go.mod h1:HOT/6NaBlR0f9XlxD3zolN6Z3N8Lp4pvhp+jLS5ihnI=
|
||||
github.com/microcosm-cc/bluemonday v1.0.15 h1:J4uN+qPng9rvkBZBoBb8YGR+ijuklIMpSOZZLjYpbeY=
|
||||
github.com/microcosm-cc/bluemonday v1.0.15/go.mod h1:ZLvAzeakRwrGnzQEvstVzVt3ZpqOF2+sdFr0Om+ce30=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/muesli/reflow v0.2.0 h1:2o0UBJPHHH4fa2GCXU4Rg4DwOtWPMekCeyc5EWbAQp0=
|
||||
github.com/muesli/reflow v0.2.0/go.mod h1:qT22vjVmM9MIUeLgsVYe/Ye7eZlbv9dZjL3dVhUqLX8=
|
||||
github.com/muesli/termenv v0.7.4 h1:/pBqvU5CpkY53tU0vVn+xgs2ZTX63aH5nY+SSps5Xa8=
|
||||
github.com/muesli/termenv v0.7.4/go.mod h1:pZ7qY9l3F7e5xsAOS0zCew2tME+p7bWeBkotCEcIIcc=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
|
||||
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
|
||||
github.com/muesli/termenv v0.8.1/go.mod h1:kzt/D/4a88RoheZmwfqorY3A+tnsSMA9HJC/fQSFKo0=
|
||||
github.com/muesli/termenv v0.9.0 h1:wnbOaGz+LUR3jNT0zOzinPnyDaCZUQRZj9GxK8eRVl8=
|
||||
github.com/muesli/termenv v0.9.0/go.mod h1:R/LzAKf+suGs4IsO95y7+7DpFHO0KABgnZqtlyx2mBw=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/noerw/glamour v0.2.1-0.20210305125354-f0a29f1de0c2 h1:ACjOTGUGi7rt3JQU9GIFFs8sueFGShy6GcGjQhMmKjs=
|
||||
github.com/noerw/glamour v0.2.1-0.20210305125354-f0a29f1de0c2/go.mod h1:WIVFX8Y2VIK1Y/1qtXYL/Vvzqlcbo3VgVop9i2piPkE=
|
||||
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
|
||||
github.com/noerw/glamour v0.3.0-patch h1:yc3wdbUIySok6KYeX5BtWnlj+PvP1uYeCeTSwq2rtSw=
|
||||
github.com/noerw/glamour v0.3.0-patch/go.mod h1:TzF0koPZhqq0YVBNL100cPHznAAjVj7fksX2RInwjGw=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
|
@ -135,10 +146,12 @@ github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7
|
|||
github.com/seletskiy/tplutil v0.0.0-20200921103632-f880f6245597 h1:nZY1S2jo+VtDrUfjO9XYI137O41hhRkxZNV5Fb5ixCA=
|
||||
github.com/seletskiy/tplutil v0.0.0-20200921103632-f880f6245597/go.mod h1:F8CBHSOjnzjx9EeXyWJTAzJyVxN+Y8JH2WjLMn4utiw=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
|
||||
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA=
|
||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
|
@ -147,74 +160,83 @@ github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
|||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
|
||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
|
||||
github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
|
||||
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
|
||||
github.com/xanzy/ssh-agent v0.3.1 h1:AmzO1SSWxw73zxFZPRwaMN1MohDw8UyHnmuxyceTEGo=
|
||||
github.com/xanzy/ssh-agent v0.3.1/go.mod h1:QIE4lCeL7nkC25x+yA3LBIYfwCc1TFziCtG7cBAac6w=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.1 h1:eVwehsLsZlCJCwXyGLgg+Q4iFWE/eTIMG0e8waCmm/I=
|
||||
github.com/yuin/goldmark v1.3.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.3.3/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.0 h1:OtISOGfH6sOWa1/qXqqAiOIAO6Z5J3AEAE18WAq6BiQ=
|
||||
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark-emoji v1.0.1 h1:ctuWEyzGBwiucEqxzwe0SOYDXPAucOrE9NQC18Wa1os=
|
||||
github.com/yuin/goldmark-emoji v1.0.1/go.mod h1:2w1E6FEWLcDQkoTE+7HU6QF1F6SLlNGjRIBbIZQFqkQ=
|
||||
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
|
||||
golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c=
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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-20190221075227-b4e8571b14e0/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-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210305034016-7844c3c200c3 h1:RdE7htvBru4I4VZQofQjCZk5W9+aLNlSF5n0zgVwm8s=
|
||||
golang.org/x/sys v0.0.0-20210305034016-7844c3c200c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf h1:2ucpDCmfkl8Bd/FsLtiD653Wf96cW37s+iGx93zsu4k=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY=
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -222,8 +244,9 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1N
|
|||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
|
22
vendor/github.com/AlecAivazis/survey/v2/README.md
generated
vendored
22
vendor/github.com/AlecAivazis/survey/v2/README.md
generated
vendored
|
@ -3,7 +3,7 @@
|
|||
[![Build Status](https://travis-ci.org/AlecAivazis/survey.svg?branch=feature%2Fpretty)](https://travis-ci.org/AlecAivazis/survey)
|
||||
[![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg)](https://pkg.go.dev/github.com/AlecAivazis/survey/v2)
|
||||
|
||||
A library for building interactive prompts.
|
||||
A library for building interactive and accessible prompts on terminals supporting ANSI escape sequences.
|
||||
|
||||
<img width="550" src="https://thumbs.gfycat.com/VillainousGraciousKouprey-size_restricted.gif"/>
|
||||
|
||||
|
@ -295,7 +295,7 @@ survey.AskOne(prompt, &color, survey.WithFilter(myFilter))
|
|||
|
||||
## Keeping the filter active
|
||||
|
||||
By default the filter will disappear if the user selects one of the filtered elements. Once the user selects one element the filter setting is gone.
|
||||
By default the filter will disappear if the user selects one of the filtered elements. Once the user selects one element the filter setting is gone.
|
||||
|
||||
However the user can prevent this from happening and keep the filter active for multiple selections in a e.g. MultiSelect:
|
||||
|
||||
|
@ -342,11 +342,13 @@ survey.AskOne(prompt, &color, survey.WithValidator(survey.Required))
|
|||
`survey` comes prepackaged with a few validators to fit common situations. Currently these
|
||||
validators include:
|
||||
|
||||
| name | valid types | description | notes |
|
||||
| ------------ | ----------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------- |
|
||||
| Required | any | Rejects zero values of the response type | Boolean values pass straight through since the zero value (false) is a valid response |
|
||||
| MinLength(n) | string | Enforces that a response is at least the given length | |
|
||||
| MaxLength(n) | string | Enforces that a response is no longer than the given length | |
|
||||
| name | valid types | description | notes |
|
||||
| ------------ | -------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
|
||||
| Required | any | Rejects zero values of the response type | Boolean values pass straight through since the zero value (false) is a valid response |
|
||||
| MinLength(n) | string | Enforces that a response is at least the given length | |
|
||||
| MaxLength(n) | string | Enforces that a response is no longer than the given length | |
|
||||
| MaxItems(n) | []OptionAnswer | Enforces that a response has no more selections of the indicated | |
|
||||
| MinItems(n) | []OptionAnswer | Enforces that a response has no less selections of the indicated | |
|
||||
|
||||
## Help Text
|
||||
|
||||
|
@ -456,6 +458,12 @@ For some examples, you can see any of the tests in this repo.
|
|||
|
||||
## FAQ
|
||||
|
||||
### What kinds of IO are supported by `survey`?
|
||||
|
||||
survey aims to support most terminal emulators; it expects support for ANSI escape sequences.
|
||||
This means that reading from piped stdin or writing to piped stdout is **not supported**,
|
||||
and likely to break your application in these situations. See [#337](https://github.com/AlecAivazis/survey/pull/337#issue-581351617)
|
||||
|
||||
### Why isn't sending a SIGINT (aka. CTRL-C) signal working?
|
||||
|
||||
When you send an interrupt signal to the process, it only interrupts the current prompt instead of the entire process. This manifests in a `github.com/AlecAivazis/survey/v2/terminal.InterruptErr` being returned from `Ask` and `AskOne`. If you want to stop the process, handle the returned error in your code:
|
||||
|
|
8
vendor/github.com/AlecAivazis/survey/v2/_tasks.hcl
generated
vendored
8
vendor/github.com/AlecAivazis/survey/v2/_tasks.hcl
generated
vendored
|
@ -1,19 +1,19 @@
|
|||
task "install-deps" {
|
||||
description = "Install all of package dependencies"
|
||||
pipeline = [
|
||||
"go get {{.files}}",
|
||||
"go get -v {{.files}}",
|
||||
]
|
||||
}
|
||||
|
||||
task "tests" {
|
||||
description = "Run the test suite"
|
||||
command = "go test {{.files}}"
|
||||
environment {
|
||||
command = "go test -v {{.files}}"
|
||||
environment = {
|
||||
GOFLAGS = "-mod=vendor"
|
||||
}
|
||||
}
|
||||
|
||||
variables {
|
||||
variables = {
|
||||
files = "$(go list -v ./... | grep -iEv \"tests|examples\")"
|
||||
}
|
||||
|
||||
|
|
6
vendor/github.com/AlecAivazis/survey/v2/core/template.go
generated
vendored
6
vendor/github.com/AlecAivazis/survey/v2/core/template.go
generated
vendored
|
@ -29,7 +29,7 @@ var TemplateFuncsNoColor = map[string]interface{}{
|
|||
//for colored output. The second string does not contain escape codes
|
||||
//and can be used by the renderer for layout purposes.
|
||||
func RunTemplate(tmpl string, data interface{}) (string, string, error) {
|
||||
tPair, err := getTemplatePair(tmpl)
|
||||
tPair, err := GetTemplatePair(tmpl)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
@ -52,12 +52,12 @@ var (
|
|||
memoMutex = &sync.RWMutex{}
|
||||
)
|
||||
|
||||
//getTemplatePair returns a pair of compiled templates where the
|
||||
//GetTemplatePair returns a pair of compiled templates where the
|
||||
//first template is generated for user-facing output and the
|
||||
//second is generated for use by the renderer. The second
|
||||
//template does not contain any color escape codes, whereas
|
||||
//the first template may or may not depending on DisableColor.
|
||||
func getTemplatePair(tmpl string) ([2]*template.Template, error) {
|
||||
func GetTemplatePair(tmpl string) ([2]*template.Template, error) {
|
||||
memoMutex.RLock()
|
||||
if t, ok := memoizedGetTemplate[tmpl]; ok {
|
||||
memoMutex.RUnlock()
|
||||
|
|
54
vendor/github.com/AlecAivazis/survey/v2/core/write.go
generated
vendored
54
vendor/github.com/AlecAivazis/survey/v2/core/write.go
generated
vendored
|
@ -24,6 +24,11 @@ type OptionAnswer struct {
|
|||
Index int
|
||||
}
|
||||
|
||||
type reflectField struct {
|
||||
value reflect.Value
|
||||
fieldType reflect.StructField
|
||||
}
|
||||
|
||||
func OptionAnswerList(incoming []string) []OptionAnswer {
|
||||
list := []OptionAnswer{}
|
||||
for i, opt := range incoming {
|
||||
|
@ -63,13 +68,12 @@ func WriteAnswer(t interface{}, name string, v interface{}) (err error) {
|
|||
}
|
||||
|
||||
// get the name of the field that matches the string we were given
|
||||
fieldIndex, err := findFieldIndex(elem, name)
|
||||
field, _, err := findField(elem, name)
|
||||
// if something went wrong
|
||||
if err != nil {
|
||||
// bubble up
|
||||
return err
|
||||
}
|
||||
field := elem.Field(fieldIndex)
|
||||
// handle references to the Settable interface aswell
|
||||
if s, ok := field.Interface().(Settable); ok {
|
||||
// use the interface method
|
||||
|
@ -156,37 +160,51 @@ func IsFieldNotMatch(err error) (string, bool) {
|
|||
|
||||
// BUG(AlecAivazis): the current implementation might cause weird conflicts if there are
|
||||
// two fields with same name that only differ by casing.
|
||||
func findFieldIndex(s reflect.Value, name string) (int, error) {
|
||||
// the type of the value
|
||||
sType := s.Type()
|
||||
func findField(s reflect.Value, name string) (reflect.Value, reflect.StructField, error) {
|
||||
|
||||
fields := flattenFields(s)
|
||||
|
||||
// first look for matching tags so we can overwrite matching field names
|
||||
for i := 0; i < sType.NumField(); i++ {
|
||||
// the field we are current scanning
|
||||
field := sType.Field(i)
|
||||
|
||||
for _, f := range fields {
|
||||
// the value of the survey tag
|
||||
tag := field.Tag.Get(tagName)
|
||||
tag := f.fieldType.Tag.Get(tagName)
|
||||
// if the tag matches the name we are looking for
|
||||
if tag != "" && tag == name {
|
||||
// then we found our index
|
||||
return i, nil
|
||||
return f.value, f.fieldType, nil
|
||||
}
|
||||
}
|
||||
|
||||
// then look for matching names
|
||||
for i := 0; i < sType.NumField(); i++ {
|
||||
// the field we are current scanning
|
||||
field := sType.Field(i)
|
||||
|
||||
for _, f := range fields {
|
||||
// if the name of the field matches what we're looking for
|
||||
if strings.ToLower(field.Name) == strings.ToLower(name) {
|
||||
return i, nil
|
||||
if strings.ToLower(f.fieldType.Name) == strings.ToLower(name) {
|
||||
return f.value, f.fieldType, nil
|
||||
}
|
||||
}
|
||||
|
||||
// we didn't find the field
|
||||
return -1, errFieldNotMatch{name}
|
||||
return reflect.Value{}, reflect.StructField{}, errFieldNotMatch{name}
|
||||
}
|
||||
|
||||
func flattenFields(s reflect.Value) []reflectField {
|
||||
sType := s.Type()
|
||||
numField := sType.NumField()
|
||||
fields := make([]reflectField, 0, numField)
|
||||
for i := 0; i < numField; i++ {
|
||||
fieldType := sType.Field(i)
|
||||
field := s.Field(i)
|
||||
|
||||
if field.Kind() == reflect.Struct && fieldType.Anonymous {
|
||||
// field is a promoted structure
|
||||
for _, f := range flattenFields(field) {
|
||||
fields = append(fields, f)
|
||||
}
|
||||
continue
|
||||
}
|
||||
fields = append(fields, reflectField{field, fieldType})
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
// isList returns true if the element is something we can Len()
|
||||
|
|
6
vendor/github.com/AlecAivazis/survey/v2/go.mod
generated
vendored
6
vendor/github.com/AlecAivazis/survey/v2/go.mod
generated
vendored
|
@ -11,9 +11,9 @@ require (
|
|||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/stretchr/testify v1.2.1
|
||||
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5
|
||||
golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1 // indirect
|
||||
golang.org/x/text v0.3.0
|
||||
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5 // indirect
|
||||
golang.org/x/term v0.0.0-20210503060354-a79de5458b56
|
||||
golang.org/x/text v0.3.3
|
||||
)
|
||||
|
||||
go 1.13
|
||||
|
|
10
vendor/github.com/AlecAivazis/survey/v2/go.sum
generated
vendored
10
vendor/github.com/AlecAivazis/survey/v2/go.sum
generated
vendored
|
@ -25,7 +25,11 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||
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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1 h1:R4dVlxdmKenVdMRS/tTspEpSTRWINYrHD8ySIU9yCIU=
|
||||
golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20210503060354-a79de5458b56 h1:b8jxX3zqjpqb2LklXPzKSGJhzyxCOZSz8ncv8Nv+y7w=
|
||||
golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
|
171
vendor/github.com/AlecAivazis/survey/v2/input.go
generated
vendored
171
vendor/github.com/AlecAivazis/survey/v2/input.go
generated
vendored
|
@ -1,6 +1,8 @@
|
|||
package survey
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2/core"
|
||||
"github.com/AlecAivazis/survey/v2/terminal"
|
||||
)
|
||||
|
@ -19,8 +21,8 @@ type Input struct {
|
|||
Default string
|
||||
Help string
|
||||
Suggest func(toComplete string) []string
|
||||
typedAnswer string
|
||||
answer string
|
||||
typedAnswer string
|
||||
options []core.OptionAnswer
|
||||
selectedIndex int
|
||||
showingHelp bool
|
||||
|
@ -58,86 +60,90 @@ var InputQuestionTemplate = `
|
|||
{{- if and .Suggest }}{{color "cyan"}}{{ print .Config.SuggestInput }} for suggestions{{end -}}
|
||||
]{{color "reset"}} {{end}}
|
||||
{{- if .Default}}{{color "white"}}({{.Default}}) {{color "reset"}}{{end}}
|
||||
{{- .Answer -}}
|
||||
{{- end}}`
|
||||
|
||||
func (i *Input) OnChange(key rune, config *PromptConfig) (bool, error) {
|
||||
if key == terminal.KeyEnter || key == '\n' {
|
||||
if i.answer != config.HelpInput || i.Help == "" {
|
||||
// we're done
|
||||
return true, nil
|
||||
} else {
|
||||
i.answer = ""
|
||||
i.showingHelp = true
|
||||
}
|
||||
} else if key == terminal.KeyDeleteWord || key == terminal.KeyDeleteLine {
|
||||
i.answer = ""
|
||||
} else if key == terminal.KeyEscape && i.Suggest != nil {
|
||||
if len(i.options) > 0 {
|
||||
func (i *Input) onRune(config *PromptConfig) terminal.OnRuneFn {
|
||||
return terminal.OnRuneFn(func(key rune, line []rune) ([]rune, bool, error) {
|
||||
if i.options != nil && (key == terminal.KeyEnter || key == '\n') {
|
||||
return []rune(i.answer), true, nil
|
||||
} else if i.options != nil && key == terminal.KeyEscape {
|
||||
i.answer = i.typedAnswer
|
||||
}
|
||||
i.options = nil
|
||||
} else if key == terminal.KeyArrowUp && len(i.options) > 0 {
|
||||
if i.selectedIndex == 0 {
|
||||
i.selectedIndex = len(i.options) - 1
|
||||
} else {
|
||||
i.selectedIndex--
|
||||
}
|
||||
i.answer = i.options[i.selectedIndex].Value
|
||||
} else if (key == terminal.KeyArrowDown || key == terminal.KeyTab) && len(i.options) > 0 {
|
||||
if i.selectedIndex == len(i.options)-1 {
|
||||
i.options = nil
|
||||
} else if key == terminal.KeyArrowUp && len(i.options) > 0 {
|
||||
if i.selectedIndex == 0 {
|
||||
i.selectedIndex = len(i.options) - 1
|
||||
} else {
|
||||
i.selectedIndex--
|
||||
}
|
||||
i.answer = i.options[i.selectedIndex].Value
|
||||
} else if (key == terminal.KeyArrowDown || key == terminal.KeyTab) && len(i.options) > 0 {
|
||||
if i.selectedIndex == len(i.options)-1 {
|
||||
i.selectedIndex = 0
|
||||
} else {
|
||||
i.selectedIndex++
|
||||
}
|
||||
i.answer = i.options[i.selectedIndex].Value
|
||||
} else if key == terminal.KeyTab && i.Suggest != nil {
|
||||
i.answer = string(line)
|
||||
i.typedAnswer = i.answer
|
||||
options := i.Suggest(i.answer)
|
||||
i.selectedIndex = 0
|
||||
} else {
|
||||
i.selectedIndex++
|
||||
}
|
||||
i.answer = i.options[i.selectedIndex].Value
|
||||
} else if key == terminal.KeyTab && i.Suggest != nil {
|
||||
options := i.Suggest(i.answer)
|
||||
i.selectedIndex = 0
|
||||
i.typedAnswer = i.answer
|
||||
if len(options) > 0 {
|
||||
if len(options) == 0 {
|
||||
return line, false, nil
|
||||
}
|
||||
|
||||
i.answer = options[0]
|
||||
if len(options) == 1 {
|
||||
i.typedAnswer = i.answer
|
||||
i.options = nil
|
||||
} else {
|
||||
i.options = core.OptionAnswerList(options)
|
||||
}
|
||||
}
|
||||
} else if key == terminal.KeyDelete || key == terminal.KeyBackspace {
|
||||
if i.answer != "" {
|
||||
runeAnswer := []rune(i.answer)
|
||||
i.answer = string(runeAnswer[0 : len(runeAnswer)-1])
|
||||
}
|
||||
} else if key >= terminal.KeySpace {
|
||||
i.answer += string(key)
|
||||
i.typedAnswer = i.answer
|
||||
i.options = nil
|
||||
}
|
||||
} else {
|
||||
if i.options == nil {
|
||||
return line, false, nil
|
||||
}
|
||||
|
||||
pageSize := config.PageSize
|
||||
opts, idx := paginate(pageSize, i.options, i.selectedIndex)
|
||||
err := i.Render(
|
||||
InputQuestionTemplate,
|
||||
InputTemplateData{
|
||||
Input: *i,
|
||||
Answer: i.answer,
|
||||
ShowHelp: i.showingHelp,
|
||||
SelectedIndex: idx,
|
||||
PageEntries: opts,
|
||||
Config: config,
|
||||
},
|
||||
)
|
||||
if key >= terminal.KeySpace {
|
||||
i.answer += string(key)
|
||||
}
|
||||
i.typedAnswer = i.answer
|
||||
|
||||
return err != nil, err
|
||||
i.options = nil
|
||||
}
|
||||
|
||||
pageSize := config.PageSize
|
||||
opts, idx := paginate(pageSize, i.options, i.selectedIndex)
|
||||
err := i.Render(
|
||||
InputQuestionTemplate,
|
||||
InputTemplateData{
|
||||
Input: *i,
|
||||
Answer: i.answer,
|
||||
ShowHelp: i.showingHelp,
|
||||
SelectedIndex: idx,
|
||||
PageEntries: opts,
|
||||
Config: config,
|
||||
},
|
||||
)
|
||||
|
||||
if err == nil {
|
||||
err = readLineAgain
|
||||
}
|
||||
|
||||
return []rune(i.typedAnswer), true, err
|
||||
})
|
||||
}
|
||||
|
||||
var readLineAgain = errors.New("read line again")
|
||||
|
||||
func (i *Input) Prompt(config *PromptConfig) (interface{}, error) {
|
||||
// render the template
|
||||
err := i.Render(
|
||||
InputQuestionTemplate,
|
||||
InputTemplateData{
|
||||
Input: *i,
|
||||
Config: config,
|
||||
Input: *i,
|
||||
Config: config,
|
||||
ShowHelp: i.showingHelp,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
|
@ -150,30 +156,39 @@ func (i *Input) Prompt(config *PromptConfig) (interface{}, error) {
|
|||
defer rr.RestoreTermMode()
|
||||
|
||||
cursor := i.NewCursor()
|
||||
cursor.Hide() // hide the cursor
|
||||
defer cursor.Show() // show the cursor when we're done
|
||||
if !config.ShowCursor {
|
||||
cursor.Hide() // hide the cursor
|
||||
defer cursor.Show() // show the cursor when we're done
|
||||
}
|
||||
|
||||
var line []rune
|
||||
|
||||
// start waiting for input
|
||||
for {
|
||||
r, _, err := rr.ReadRune()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if r == terminal.KeyInterrupt {
|
||||
return "", terminal.InterruptErr
|
||||
}
|
||||
if r == terminal.KeyEndTransmission {
|
||||
break
|
||||
if i.options != nil {
|
||||
line = []rune{}
|
||||
}
|
||||
|
||||
line, err = rr.ReadLineWithDefault(0, line, i.onRune(config))
|
||||
if err == readLineAgain {
|
||||
continue
|
||||
}
|
||||
|
||||
b, err := i.OnChange(r, config)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if b {
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
i.answer = string(line)
|
||||
// readline print an empty line, go up before we render the follow up
|
||||
cursor.Up(1)
|
||||
|
||||
// if we ran into the help string
|
||||
if i.answer == config.HelpInput && i.Help != "" {
|
||||
// show the help and prompt again
|
||||
i.showingHelp = true
|
||||
return i.Prompt(config)
|
||||
}
|
||||
|
||||
// if the line is empty
|
||||
|
|
69
vendor/github.com/AlecAivazis/survey/v2/multiselect.go
generated
vendored
69
vendor/github.com/AlecAivazis/survey/v2/multiselect.go
generated
vendored
|
@ -45,9 +45,27 @@ type MultiSelectTemplateData struct {
|
|||
ShowHelp bool
|
||||
PageEntries []core.OptionAnswer
|
||||
Config *PromptConfig
|
||||
|
||||
// These fields are used when rendering an individual option
|
||||
CurrentOpt core.OptionAnswer
|
||||
CurrentIndex int
|
||||
}
|
||||
|
||||
// IterateOption sets CurrentOpt and CurrentIndex appropriately so a multiselect option can be rendered individually
|
||||
func (m MultiSelectTemplateData) IterateOption(ix int, opt core.OptionAnswer) interface{} {
|
||||
copy := m
|
||||
copy.CurrentIndex = ix
|
||||
copy.CurrentOpt = opt
|
||||
return copy
|
||||
}
|
||||
|
||||
var MultiSelectQuestionTemplate = `
|
||||
{{- define "option"}}
|
||||
{{- if eq .SelectedIndex .CurrentIndex }}{{color .Config.Icons.SelectFocus.Format }}{{ .Config.Icons.SelectFocus.Text }}{{color "reset"}}{{else}} {{end}}
|
||||
{{- if index .Checked .CurrentOpt.Index }}{{color .Config.Icons.MarkedOption.Format }} {{ .Config.Icons.MarkedOption.Text }} {{else}}{{color .Config.Icons.UnmarkedOption.Format }} {{ .Config.Icons.UnmarkedOption.Text }} {{end}}
|
||||
{{- color "reset"}}
|
||||
{{- " "}}{{- .CurrentOpt.Value}}
|
||||
{{end}}
|
||||
{{- if .ShowHelp }}{{- color .Config.Icons.Help.Format }}{{ .Config.Icons.Help.Text }} {{ .Help }}{{color "reset"}}{{"\n"}}{{end}}
|
||||
{{- color .Config.Icons.Question.Format }}{{ .Config.Icons.Question.Text }} {{color "reset"}}
|
||||
{{- color "default+hb"}}{{ .Message }}{{ .FilterMessage }}{{color "reset"}}
|
||||
|
@ -56,10 +74,7 @@ var MultiSelectQuestionTemplate = `
|
|||
{{- " "}}{{- color "cyan"}}[Use arrows to move, space to select, <right> to all, <left> to none, type to filter{{- if and .Help (not .ShowHelp)}}, {{ .Config.HelpInput }} for more help{{end}}]{{color "reset"}}
|
||||
{{- "\n"}}
|
||||
{{- range $ix, $option := .PageEntries}}
|
||||
{{- if eq $ix $.SelectedIndex }}{{color $.Config.Icons.SelectFocus.Format }}{{ $.Config.Icons.SelectFocus.Text }}{{color "reset"}}{{else}} {{end}}
|
||||
{{- if index $.Checked $option.Index }}{{color $.Config.Icons.MarkedOption.Format }} {{ $.Config.Icons.MarkedOption.Text }} {{else}}{{color $.Config.Icons.UnmarkedOption.Format }} {{ $.Config.Icons.UnmarkedOption.Text }} {{end}}
|
||||
{{- color "reset"}}
|
||||
{{- " "}}{{$option.Value}}{{"\n"}}
|
||||
{{- template "option" $.IterateOption $ix $option}}
|
||||
{{- end}}
|
||||
{{- end}}`
|
||||
|
||||
|
@ -159,18 +174,17 @@ func (m *MultiSelect) OnChange(key rune, config *PromptConfig) {
|
|||
// and we have modified the filter then we should move the page back!
|
||||
opts, idx := paginate(pageSize, options, m.selectedIndex)
|
||||
|
||||
tmplData := MultiSelectTemplateData{
|
||||
MultiSelect: *m,
|
||||
SelectedIndex: idx,
|
||||
Checked: m.checked,
|
||||
ShowHelp: m.showingHelp,
|
||||
PageEntries: opts,
|
||||
Config: config,
|
||||
}
|
||||
|
||||
// render the options
|
||||
m.Render(
|
||||
MultiSelectQuestionTemplate,
|
||||
MultiSelectTemplateData{
|
||||
MultiSelect: *m,
|
||||
SelectedIndex: idx,
|
||||
Checked: m.checked,
|
||||
ShowHelp: m.showingHelp,
|
||||
PageEntries: opts,
|
||||
Config: config,
|
||||
},
|
||||
)
|
||||
m.RenderWithCursorOffset(MultiSelectQuestionTemplate, tmplData, opts, idx)
|
||||
}
|
||||
|
||||
func (m *MultiSelect) filterOptions(config *PromptConfig) []core.OptionAnswer {
|
||||
|
@ -250,20 +264,21 @@ func (m *MultiSelect) Prompt(config *PromptConfig) (interface{}, error) {
|
|||
opts, idx := paginate(pageSize, core.OptionAnswerList(m.Options), m.selectedIndex)
|
||||
|
||||
cursor := m.NewCursor()
|
||||
cursor.Hide() // hide the cursor
|
||||
defer cursor.Show() // show the cursor when we're done
|
||||
cursor.Save() // for proper cursor placement during selection
|
||||
cursor.Hide() // hide the cursor
|
||||
defer cursor.Show() // show the cursor when we're done
|
||||
defer cursor.Restore() // clear any accessibility offsetting on exit
|
||||
|
||||
tmplData := MultiSelectTemplateData{
|
||||
MultiSelect: *m,
|
||||
SelectedIndex: idx,
|
||||
Checked: m.checked,
|
||||
PageEntries: opts,
|
||||
Config: config,
|
||||
}
|
||||
|
||||
// ask the question
|
||||
err := m.Render(
|
||||
MultiSelectQuestionTemplate,
|
||||
MultiSelectTemplateData{
|
||||
MultiSelect: *m,
|
||||
SelectedIndex: idx,
|
||||
Checked: m.checked,
|
||||
PageEntries: opts,
|
||||
Config: config,
|
||||
},
|
||||
)
|
||||
err := m.RenderWithCursorOffset(MultiSelectQuestionTemplate, tmplData, opts, idx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
38
vendor/github.com/AlecAivazis/survey/v2/renderer.go
generated
vendored
38
vendor/github.com/AlecAivazis/survey/v2/renderer.go
generated
vendored
|
@ -7,7 +7,7 @@ import (
|
|||
|
||||
"github.com/AlecAivazis/survey/v2/core"
|
||||
"github.com/AlecAivazis/survey/v2/terminal"
|
||||
goterm "golang.org/x/crypto/ssh/terminal"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
type Renderer struct {
|
||||
|
@ -69,6 +69,14 @@ func (r *Renderer) Error(config *PromptConfig, invalid error) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (r *Renderer) OffsetCursor(offset int) {
|
||||
cursor := r.NewCursor()
|
||||
for offset > 0 {
|
||||
cursor.PreviousLine(1)
|
||||
offset--
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Renderer) Render(tmpl string, data interface{}) error {
|
||||
// cleanup the currently rendered text
|
||||
lineCount := r.countLines(r.renderedText)
|
||||
|
@ -91,6 +99,21 @@ func (r *Renderer) Render(tmpl string, data interface{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (r *Renderer) RenderWithCursorOffset(tmpl string, data IterableOpts, opts []core.OptionAnswer, idx int) error {
|
||||
cursor := r.NewCursor()
|
||||
cursor.Restore() // clear any accessibility offsetting
|
||||
|
||||
if err := r.Render(tmpl, data); err != nil {
|
||||
return err
|
||||
}
|
||||
cursor.Save()
|
||||
|
||||
offset := computeCursorOffset(MultiSelectQuestionTemplate, data, opts, idx, r.termWidthSafe())
|
||||
r.OffsetCursor(offset)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// appendRenderedError appends text to the renderer's error buffer
|
||||
// which is used to track what has been printed. It is not exported
|
||||
// as errors should only be displayed via Error(config, error).
|
||||
|
@ -119,19 +142,24 @@ func (r *Renderer) resetPrompt(lines int) {
|
|||
|
||||
func (r *Renderer) termWidth() (int, error) {
|
||||
fd := int(r.stdio.Out.Fd())
|
||||
termWidth, _, err := goterm.GetSize(fd)
|
||||
termWidth, _, err := term.GetSize(fd)
|
||||
return termWidth, err
|
||||
}
|
||||
|
||||
// countLines will return the count of `\n` with the addition of any
|
||||
// lines that have wrapped due to narrow terminal width
|
||||
func (r *Renderer) countLines(buf bytes.Buffer) int {
|
||||
func (r *Renderer) termWidthSafe() int {
|
||||
w, err := r.termWidth()
|
||||
if err != nil || w == 0 {
|
||||
// if we got an error due to terminal.GetSize not being supported
|
||||
// on current platform then just assume a very wide terminal
|
||||
w = 10000
|
||||
}
|
||||
return w
|
||||
}
|
||||
|
||||
// countLines will return the count of `\n` with the addition of any
|
||||
// lines that have wrapped due to narrow terminal width
|
||||
func (r *Renderer) countLines(buf bytes.Buffer) int {
|
||||
w := r.termWidthSafe()
|
||||
|
||||
bufBytes := buf.Bytes()
|
||||
|
||||
|
|
72
vendor/github.com/AlecAivazis/survey/v2/select.go
generated
vendored
72
vendor/github.com/AlecAivazis/survey/v2/select.go
generated
vendored
|
@ -43,9 +43,26 @@ type SelectTemplateData struct {
|
|||
ShowAnswer bool
|
||||
ShowHelp bool
|
||||
Config *PromptConfig
|
||||
|
||||
// These fields are used when rendering an individual option
|
||||
CurrentOpt core.OptionAnswer
|
||||
CurrentIndex int
|
||||
}
|
||||
|
||||
// IterateOption sets CurrentOpt and CurrentIndex appropriately so a select option can be rendered individually
|
||||
func (s SelectTemplateData) IterateOption(ix int, opt core.OptionAnswer) interface{} {
|
||||
copy := s
|
||||
copy.CurrentIndex = ix
|
||||
copy.CurrentOpt = opt
|
||||
return copy
|
||||
}
|
||||
|
||||
var SelectQuestionTemplate = `
|
||||
{{- define "option"}}
|
||||
{{- if eq .SelectedIndex .CurrentIndex }}{{color .Config.Icons.SelectFocus.Format }}{{ .Config.Icons.SelectFocus.Text }} {{else}}{{color "default"}} {{end}}
|
||||
{{- .CurrentOpt.Value}}
|
||||
{{- color "reset"}}
|
||||
{{end}}
|
||||
{{- if .ShowHelp }}{{- color .Config.Icons.Help.Format }}{{ .Config.Icons.Help.Text }} {{ .Help }}{{color "reset"}}{{"\n"}}{{end}}
|
||||
{{- color .Config.Icons.Question.Format }}{{ .Config.Icons.Question.Text }} {{color "reset"}}
|
||||
{{- color "default+hb"}}{{ .Message }}{{ .FilterMessage }}{{color "reset"}}
|
||||
|
@ -53,10 +70,8 @@ var SelectQuestionTemplate = `
|
|||
{{- else}}
|
||||
{{- " "}}{{- color "cyan"}}[Use arrows to move, type to filter{{- if and .Help (not .ShowHelp)}}, {{ .Config.HelpInput }} for more help{{end}}]{{color "reset"}}
|
||||
{{- "\n"}}
|
||||
{{- range $ix, $choice := .PageEntries}}
|
||||
{{- if eq $ix $.SelectedIndex }}{{color $.Config.Icons.SelectFocus.Format }}{{ $.Config.Icons.SelectFocus.Text }} {{else}}{{color "default"}} {{end}}
|
||||
{{- $choice.Value}}
|
||||
{{- color "reset"}}{{"\n"}}
|
||||
{{- range $ix, $option := .PageEntries}}
|
||||
{{- template "option" $.IterateOption $ix $option}}
|
||||
{{- end}}
|
||||
{{- end}}`
|
||||
|
||||
|
@ -152,17 +167,16 @@ func (s *Select) OnChange(key rune, config *PromptConfig) bool {
|
|||
// and we have modified the filter then we should move the page back!
|
||||
opts, idx := paginate(pageSize, options, s.selectedIndex)
|
||||
|
||||
tmplData := SelectTemplateData{
|
||||
Select: *s,
|
||||
SelectedIndex: idx,
|
||||
ShowHelp: s.showingHelp,
|
||||
PageEntries: opts,
|
||||
Config: config,
|
||||
}
|
||||
|
||||
// render the options
|
||||
s.Render(
|
||||
SelectQuestionTemplate,
|
||||
SelectTemplateData{
|
||||
Select: *s,
|
||||
SelectedIndex: idx,
|
||||
ShowHelp: s.showingHelp,
|
||||
PageEntries: opts,
|
||||
Config: config,
|
||||
},
|
||||
)
|
||||
s.RenderWithCursorOffset(SelectQuestionTemplate, tmplData, opts, idx)
|
||||
|
||||
// keep prompting
|
||||
return false
|
||||
|
@ -234,16 +248,22 @@ func (s *Select) Prompt(config *PromptConfig) (interface{}, error) {
|
|||
// figure out the options and index to render
|
||||
opts, idx := paginate(pageSize, core.OptionAnswerList(s.Options), sel)
|
||||
|
||||
cursor := s.NewCursor()
|
||||
cursor.Save() // for proper cursor placement during selection
|
||||
cursor.Hide() // hide the cursor
|
||||
defer cursor.Show() // show the cursor when we're done
|
||||
defer cursor.Restore() // clear any accessibility offsetting on exit
|
||||
|
||||
tmplData := SelectTemplateData{
|
||||
Select: *s,
|
||||
SelectedIndex: idx,
|
||||
ShowHelp: s.showingHelp,
|
||||
PageEntries: opts,
|
||||
Config: config,
|
||||
}
|
||||
|
||||
// ask the question
|
||||
err := s.Render(
|
||||
SelectQuestionTemplate,
|
||||
SelectTemplateData{
|
||||
Select: *s,
|
||||
PageEntries: opts,
|
||||
SelectedIndex: idx,
|
||||
Config: config,
|
||||
},
|
||||
)
|
||||
err := s.RenderWithCursorOffset(SelectQuestionTemplate, tmplData, opts, idx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -255,10 +275,6 @@ func (s *Select) Prompt(config *PromptConfig) (interface{}, error) {
|
|||
rr.SetTermMode()
|
||||
defer rr.RestoreTermMode()
|
||||
|
||||
cursor := s.NewCursor()
|
||||
cursor.Hide() // hide the cursor
|
||||
defer cursor.Show() // show the cursor when we're done
|
||||
|
||||
// start waiting for input
|
||||
for {
|
||||
r, _, err := rr.ReadRune()
|
||||
|
@ -317,6 +333,8 @@ func (s *Select) Prompt(config *PromptConfig) (interface{}, error) {
|
|||
}
|
||||
|
||||
func (s *Select) Cleanup(config *PromptConfig, val interface{}) error {
|
||||
cursor := s.NewCursor()
|
||||
cursor.Restore()
|
||||
return s.Render(
|
||||
SelectQuestionTemplate,
|
||||
SelectTemplateData{
|
||||
|
|
54
vendor/github.com/AlecAivazis/survey/v2/survey.go
generated
vendored
54
vendor/github.com/AlecAivazis/survey/v2/survey.go
generated
vendored
|
@ -1,10 +1,12 @@
|
|||
package survey
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2/core"
|
||||
"github.com/AlecAivazis/survey/v2/terminal"
|
||||
|
@ -55,6 +57,7 @@ func defaultAskOptions() *AskOptions {
|
|||
return strings.Contains(strings.ToLower(value), filter)
|
||||
},
|
||||
KeepFilter: false,
|
||||
ShowCursor: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -114,6 +117,7 @@ type PromptConfig struct {
|
|||
SuggestInput string
|
||||
Filter func(filter string, option string, index int) bool
|
||||
KeepFilter bool
|
||||
ShowCursor bool
|
||||
}
|
||||
|
||||
// Prompt is the primary interface for the objects that can take user input
|
||||
|
@ -219,6 +223,17 @@ func WithIcons(setIcons func(*IconSet)) AskOpt {
|
|||
}
|
||||
}
|
||||
|
||||
// WithShowCursor sets the show cursor behavior when prompting the user
|
||||
func WithShowCursor(ShowCursor bool) AskOpt {
|
||||
return func(options *AskOptions) error {
|
||||
// set the page size
|
||||
options.PromptConfig.ShowCursor = ShowCursor
|
||||
|
||||
// nothing went wrong
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
AskOne performs the prompt for a single prompt and asks for validation if required.
|
||||
Response types should be something that can be casted from the response type designated
|
||||
|
@ -398,3 +413,42 @@ func paginate(pageSize int, choices []core.OptionAnswer, sel int) ([]core.Option
|
|||
// return the subset we care about and the index
|
||||
return choices[start:end], cursor
|
||||
}
|
||||
|
||||
type IterableOpts interface {
|
||||
IterateOption(int, core.OptionAnswer) interface{}
|
||||
}
|
||||
|
||||
func computeCursorOffset(tmpl string, data IterableOpts, opts []core.OptionAnswer, idx, tWidth int) int {
|
||||
tmpls, err := core.GetTemplatePair(tmpl)
|
||||
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
t := tmpls[0]
|
||||
|
||||
renderOpt := func(ix int, opt core.OptionAnswer) string {
|
||||
buf := bytes.NewBufferString("")
|
||||
t.ExecuteTemplate(buf, "option", data.IterateOption(ix, opt))
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
offset := len(opts) - idx
|
||||
|
||||
for i, o := range opts {
|
||||
if i < idx {
|
||||
continue
|
||||
}
|
||||
renderedOpt := renderOpt(i, o)
|
||||
valWidth := utf8.RuneCount([]byte(renderedOpt))
|
||||
if valWidth > tWidth {
|
||||
splitCount := valWidth / tWidth
|
||||
if valWidth%tWidth == 0 {
|
||||
splitCount -= 1
|
||||
}
|
||||
offset += splitCount
|
||||
}
|
||||
}
|
||||
|
||||
return offset
|
||||
}
|
||||
|
|
10
vendor/github.com/AlecAivazis/survey/v2/terminal/cursor.go
generated
vendored
10
vendor/github.com/AlecAivazis/survey/v2/terminal/cursor.go
generated
vendored
|
@ -43,11 +43,13 @@ func (c *Cursor) Back(n int) {
|
|||
// NextLine moves cursor to beginning of the line n lines down.
|
||||
func (c *Cursor) NextLine(n int) {
|
||||
c.Down(1)
|
||||
c.HorizontalAbsolute(0)
|
||||
}
|
||||
|
||||
// PreviousLine moves cursor to beginning of the line n lines up.
|
||||
func (c *Cursor) PreviousLine(n int) {
|
||||
c.Up(1)
|
||||
c.HorizontalAbsolute(0)
|
||||
}
|
||||
|
||||
// HorizontalAbsolute moves cursor horizontally to x.
|
||||
|
@ -167,8 +169,11 @@ func (c *Cursor) Size(buf *bytes.Buffer) (*Coord, error) {
|
|||
|
||||
// hide the cursor (so it doesn't blink when getting the size of the terminal)
|
||||
c.Hide()
|
||||
defer c.Show()
|
||||
|
||||
// save the current location of the cursor
|
||||
c.Save()
|
||||
defer c.Restore()
|
||||
|
||||
// move the cursor to the very bottom of the terminal
|
||||
c.Move(999, 999)
|
||||
|
@ -179,11 +184,6 @@ func (c *Cursor) Size(buf *bytes.Buffer) (*Coord, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// move back where we began
|
||||
c.Restore()
|
||||
|
||||
// show the cursor
|
||||
c.Show()
|
||||
// since the bottom was calculated in the lower right corner, it
|
||||
// is the dimensions we are looking for
|
||||
return bottom, nil
|
||||
|
|
71
vendor/github.com/AlecAivazis/survey/v2/terminal/runereader.go
generated
vendored
71
vendor/github.com/AlecAivazis/survey/v2/terminal/runereader.go
generated
vendored
|
@ -31,7 +31,13 @@ func (rr *RuneReader) printChar(char rune, mask rune) {
|
|||
}
|
||||
}
|
||||
|
||||
func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
||||
type OnRuneFn func(rune, []rune) ([]rune, bool, error)
|
||||
|
||||
func (rr *RuneReader) ReadLine(mask rune, onRunes ...OnRuneFn) ([]rune, error) {
|
||||
return rr.ReadLineWithDefault(mask, []rune{}, onRunes...)
|
||||
}
|
||||
|
||||
func (rr *RuneReader) ReadLineWithDefault(mask rune, d []rune, onRunes ...OnRuneFn) ([]rune, error) {
|
||||
line := []rune{}
|
||||
// we only care about horizontal displacements from the origin so start counting at 0
|
||||
index := 0
|
||||
|
@ -41,19 +47,56 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
|||
Out: rr.stdio.Out,
|
||||
}
|
||||
|
||||
onRune := func(r rune, line []rune) ([]rune, bool, error) {
|
||||
return line, false, nil
|
||||
}
|
||||
|
||||
// if the user pressed a key the caller was interested in capturing
|
||||
if len(onRunes) > 0 {
|
||||
onRune = onRunes[0]
|
||||
}
|
||||
|
||||
// we get the terminal width and height (if resized after this point the property might become invalid)
|
||||
terminalSize, _ := cursor.Size(rr.Buffer())
|
||||
// we set the current location of the cursor once
|
||||
cursorCurrent, _ := cursor.Location(rr.Buffer())
|
||||
|
||||
increment := func() {
|
||||
if cursorCurrent.CursorIsAtLineEnd(terminalSize) {
|
||||
cursorCurrent.X = COORDINATE_SYSTEM_BEGIN
|
||||
cursorCurrent.Y++
|
||||
} else {
|
||||
cursorCurrent.X++
|
||||
}
|
||||
}
|
||||
decrement := func() {
|
||||
if cursorCurrent.CursorIsAtLineBegin() {
|
||||
cursorCurrent.X = terminalSize.X
|
||||
cursorCurrent.Y--
|
||||
} else {
|
||||
cursorCurrent.X--
|
||||
}
|
||||
}
|
||||
|
||||
if len(d) > 0 {
|
||||
index = len(d)
|
||||
fmt.Fprint(rr.stdio.Out, string(d))
|
||||
line = d
|
||||
for range d {
|
||||
increment()
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
// wait for some input
|
||||
r, _, err := rr.ReadRune()
|
||||
if err != nil {
|
||||
return line, err
|
||||
}
|
||||
// increment cursor location
|
||||
cursorCurrent.X++
|
||||
|
||||
if l, stop, err := onRune(r, line); stop || err != nil {
|
||||
return l, err
|
||||
}
|
||||
|
||||
// if the user pressed enter or some other newline/termination like ctrl+d
|
||||
if r == '\r' || r == '\n' || r == KeyEndTransmission {
|
||||
|
@ -63,13 +106,10 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
|||
EraseLine(rr.stdio.Out, ERASE_LINE_END)
|
||||
cursor.PreviousLine(1)
|
||||
cursor.Forward(int(terminalSize.X))
|
||||
cursorCurrent.X = terminalSize.X
|
||||
cursorCurrent.Y--
|
||||
|
||||
} else {
|
||||
cursor.Back(1)
|
||||
cursorCurrent.X--
|
||||
}
|
||||
decrement()
|
||||
index--
|
||||
}
|
||||
// move the cursor the a new line
|
||||
|
@ -148,6 +188,7 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
|||
|
||||
// decrement the index
|
||||
index--
|
||||
decrement()
|
||||
} else {
|
||||
// otherwise the user pressed backspace while at the beginning of the line
|
||||
soundBell(rr.stdio.Out)
|
||||
|
@ -170,6 +211,7 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
|||
}
|
||||
//decrement the index
|
||||
index--
|
||||
decrement()
|
||||
|
||||
} else {
|
||||
// otherwise we are at the beginning of where we started reading lines
|
||||
|
@ -192,6 +234,7 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
|||
cursor.Forward(runeWidth(line[index]))
|
||||
}
|
||||
index++
|
||||
increment()
|
||||
|
||||
} else {
|
||||
// otherwise we are at the end of the word and can't go past
|
||||
|
@ -208,12 +251,11 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
|||
if cursorCurrent.CursorIsAtLineBegin() {
|
||||
cursor.PreviousLine(1)
|
||||
cursor.Forward(int(terminalSize.X))
|
||||
cursorCurrent.X = terminalSize.X
|
||||
cursorCurrent.Y--
|
||||
|
||||
cursorCurrent.X = terminalSize.X
|
||||
} else {
|
||||
cursor.Back(runeWidth(line[index-1]))
|
||||
cursorCurrent.X--
|
||||
cursorCurrent.X -= Short(runeWidth(line[index-1]))
|
||||
}
|
||||
index--
|
||||
}
|
||||
|
@ -223,12 +265,11 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
|||
for index != len(line) {
|
||||
if cursorCurrent.CursorIsAtLineEnd(terminalSize) {
|
||||
cursor.NextLine(1)
|
||||
cursorCurrent.X = COORDINATE_SYSTEM_BEGIN
|
||||
cursorCurrent.Y++
|
||||
|
||||
cursorCurrent.X = COORDINATE_SYSTEM_BEGIN
|
||||
} else {
|
||||
cursor.Forward(runeWidth(line[index]))
|
||||
cursorCurrent.X++
|
||||
cursorCurrent.X += Short(runeWidth(line[index]))
|
||||
}
|
||||
index++
|
||||
}
|
||||
|
@ -277,6 +318,7 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
|||
line = append(line, r)
|
||||
// save the location of the cursor
|
||||
index++
|
||||
increment()
|
||||
// print out the character
|
||||
rr.printChar(r, mask)
|
||||
} else {
|
||||
|
@ -293,7 +335,7 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
|||
EraseLine(rr.stdio.Out, ERASE_LINE_END)
|
||||
// print out the character
|
||||
rr.printChar(char, mask)
|
||||
cursorCurrent.X++
|
||||
increment()
|
||||
}
|
||||
// if we are at the last line, we want to visually insert a new line and append to it.
|
||||
if cursorCurrent.CursorIsAtLineEnd(terminalSize) && cursorCurrent.Y == terminalSize.Y {
|
||||
|
@ -316,6 +358,7 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
|||
}
|
||||
// increment the index
|
||||
index++
|
||||
increment()
|
||||
|
||||
}
|
||||
}
|
||||
|
|
40
vendor/github.com/AlecAivazis/survey/v2/validate.go
generated
vendored
40
vendor/github.com/AlecAivazis/survey/v2/validate.go
generated
vendored
|
@ -4,6 +4,8 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2/core"
|
||||
)
|
||||
|
||||
// Required does not allow an empty value
|
||||
|
@ -58,6 +60,44 @@ func MinLength(length int) Validator {
|
|||
}
|
||||
}
|
||||
|
||||
// MaxItems requires that the list is no longer than the specified value
|
||||
func MaxItems(numberItems int) Validator {
|
||||
// return a validator that checks the length of the list
|
||||
return func(val interface{}) error {
|
||||
if list, ok := val.([]core.OptionAnswer); ok {
|
||||
// if the list is longer than the given value
|
||||
if len(list) > numberItems {
|
||||
// yell loudly
|
||||
return fmt.Errorf("value is too long. Max items is %v", numberItems)
|
||||
}
|
||||
} else {
|
||||
// otherwise we cannot convert the value into a list of answer and cannot enforce length
|
||||
return fmt.Errorf("cannot impose the length on something other than a list of answers")
|
||||
}
|
||||
// the input is fine
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// MinItems requires that the list is longer or equal in length to the specified value
|
||||
func MinItems(numberItems int) Validator {
|
||||
// return a validator that checks the length of the list
|
||||
return func(val interface{}) error {
|
||||
if list, ok := val.([]core.OptionAnswer); ok {
|
||||
// if the list is shorter than the given value
|
||||
if len(list) < numberItems {
|
||||
// yell loudly
|
||||
return fmt.Errorf("value is too long. Min items is %v", numberItems)
|
||||
}
|
||||
} else {
|
||||
// otherwise we cannot convert the value into a list of answer and cannot enforce length
|
||||
return fmt.Errorf("cannot impose the length on something other than a list of answers")
|
||||
}
|
||||
// the input is fine
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ComposeValidators is a variadic function used to create one validator from many.
|
||||
func ComposeValidators(validators ...Validator) Validator {
|
||||
// return a validator that calls each one sequentially
|
||||
|
|
1
vendor/github.com/Microsoft/go-winio/CODEOWNERS
generated
vendored
Normal file
1
vendor/github.com/Microsoft/go-winio/CODEOWNERS
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
* @microsoft/containerplat
|
2
vendor/github.com/Microsoft/go-winio/README.md
generated
vendored
2
vendor/github.com/Microsoft/go-winio/README.md
generated
vendored
|
@ -1,4 +1,4 @@
|
|||
# go-winio
|
||||
# go-winio [![Build Status](https://github.com/microsoft/go-winio/actions/workflows/ci.yml/badge.svg)](https://github.com/microsoft/go-winio/actions/workflows/ci.yml)
|
||||
|
||||
This repository contains utilities for efficiently performing Win32 IO operations in
|
||||
Go. Currently, this is focused on accessing named pipes and other file handles, and
|
||||
|
|
36
vendor/github.com/Microsoft/go-winio/fileinfo.go
generated
vendored
36
vendor/github.com/Microsoft/go-winio/fileinfo.go
generated
vendored
|
@ -5,21 +5,14 @@ package winio
|
|||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//sys getFileInformationByHandleEx(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) = GetFileInformationByHandleEx
|
||||
//sys setFileInformationByHandle(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) = SetFileInformationByHandle
|
||||
|
||||
const (
|
||||
fileBasicInfo = 0
|
||||
fileIDInfo = 0x12
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// FileBasicInfo contains file access time and file attributes information.
|
||||
type FileBasicInfo struct {
|
||||
CreationTime, LastAccessTime, LastWriteTime, ChangeTime syscall.Filetime
|
||||
CreationTime, LastAccessTime, LastWriteTime, ChangeTime windows.Filetime
|
||||
FileAttributes uint32
|
||||
pad uint32 // padding
|
||||
}
|
||||
|
@ -27,7 +20,7 @@ type FileBasicInfo struct {
|
|||
// GetFileBasicInfo retrieves times and attributes for a file.
|
||||
func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
|
||||
bi := &FileBasicInfo{}
|
||||
if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
|
||||
if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
|
||||
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
|
||||
}
|
||||
runtime.KeepAlive(f)
|
||||
|
@ -36,13 +29,32 @@ func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
|
|||
|
||||
// SetFileBasicInfo sets times and attributes for a file.
|
||||
func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error {
|
||||
if err := setFileInformationByHandle(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
|
||||
if err := windows.SetFileInformationByHandle(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
|
||||
return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err}
|
||||
}
|
||||
runtime.KeepAlive(f)
|
||||
return nil
|
||||
}
|
||||
|
||||
// FileStandardInfo contains extended information for the file.
|
||||
// FILE_STANDARD_INFO in WinBase.h
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-file_standard_info
|
||||
type FileStandardInfo struct {
|
||||
AllocationSize, EndOfFile int64
|
||||
NumberOfLinks uint32
|
||||
DeletePending, Directory bool
|
||||
}
|
||||
|
||||
// GetFileStandardInfo retrieves ended information for the file.
|
||||
func GetFileStandardInfo(f *os.File) (*FileStandardInfo, error) {
|
||||
si := &FileStandardInfo{}
|
||||
if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileStandardInfo, (*byte)(unsafe.Pointer(si)), uint32(unsafe.Sizeof(*si))); err != nil {
|
||||
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
|
||||
}
|
||||
runtime.KeepAlive(f)
|
||||
return si, nil
|
||||
}
|
||||
|
||||
// FileIDInfo contains the volume serial number and file ID for a file. This pair should be
|
||||
// unique on a system.
|
||||
type FileIDInfo struct {
|
||||
|
@ -53,7 +65,7 @@ type FileIDInfo struct {
|
|||
// GetFileID retrieves the unique (volume, file ID) pair for a file.
|
||||
func GetFileID(f *os.File) (*FileIDInfo, error) {
|
||||
fileID := &FileIDInfo{}
|
||||
if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileIDInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil {
|
||||
if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileIdInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil {
|
||||
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
|
||||
}
|
||||
runtime.KeepAlive(f)
|
||||
|
|
4
vendor/github.com/Microsoft/go-winio/go.mod
generated
vendored
4
vendor/github.com/Microsoft/go-winio/go.mod
generated
vendored
|
@ -4,6 +4,6 @@ go 1.12
|
|||
|
||||
require (
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/sirupsen/logrus v1.4.1
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3
|
||||
github.com/sirupsen/logrus v1.7.0
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
|
||||
)
|
||||
|
|
14
vendor/github.com/Microsoft/go-winio/go.sum
generated
vendored
14
vendor/github.com/Microsoft/go-winio/go.sum
generated
vendored
|
@ -1,16 +1,14 @@
|
|||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
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/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 h1:7TYNF4UdlohbFwpNH04CoPMp1cHUZgO1Ebq5r2hIjfo=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
2
vendor/github.com/Microsoft/go-winio/hvsock.go
generated
vendored
2
vendor/github.com/Microsoft/go-winio/hvsock.go
generated
vendored
|
@ -1,3 +1,5 @@
|
|||
// +build windows
|
||||
|
||||
package winio
|
||||
|
||||
import (
|
||||
|
|
2
vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go
generated
vendored
2
vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go
generated
vendored
|
@ -1,3 +1,5 @@
|
|||
// +build windows
|
||||
|
||||
// Package guid provides a GUID type. The backing structure for a GUID is
|
||||
// identical to that used by the golang.org/x/sys/windows GUID type.
|
||||
// There are two main binary encodings used for a GUID, the big-endian encoding,
|
||||
|
|
5
vendor/github.com/Microsoft/go-winio/privilege.go
generated
vendored
5
vendor/github.com/Microsoft/go-winio/privilege.go
generated
vendored
|
@ -28,8 +28,9 @@ const (
|
|||
|
||||
ERROR_NOT_ALL_ASSIGNED syscall.Errno = 1300
|
||||
|
||||
SeBackupPrivilege = "SeBackupPrivilege"
|
||||
SeRestorePrivilege = "SeRestorePrivilege"
|
||||
SeBackupPrivilege = "SeBackupPrivilege"
|
||||
SeRestorePrivilege = "SeRestorePrivilege"
|
||||
SeSecurityPrivilege = "SeSecurityPrivilege"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
2
vendor/github.com/Microsoft/go-winio/syscall.go
generated
vendored
2
vendor/github.com/Microsoft/go-winio/syscall.go
generated
vendored
|
@ -1,3 +1,3 @@
|
|||
package winio
|
||||
|
||||
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go hvsock.go
|
||||
//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go hvsock.go
|
||||
|
|
621
vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
generated
vendored
621
vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
generated
vendored
|
@ -19,6 +19,7 @@ const (
|
|||
|
||||
var (
|
||||
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
|
||||
errERROR_EINVAL error = syscall.EINVAL
|
||||
)
|
||||
|
||||
// errnoErr returns common boxed Errno values, to prevent
|
||||
|
@ -26,7 +27,7 @@ var (
|
|||
func errnoErr(e syscall.Errno) error {
|
||||
switch e {
|
||||
case 0:
|
||||
return nil
|
||||
return errERROR_EINVAL
|
||||
case errnoERROR_IO_PENDING:
|
||||
return errERROR_IO_PENDING
|
||||
}
|
||||
|
@ -37,243 +38,62 @@ func errnoErr(e syscall.Errno) error {
|
|||
}
|
||||
|
||||
var (
|
||||
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
modws2_32 = windows.NewLazySystemDLL("ws2_32.dll")
|
||||
modntdll = windows.NewLazySystemDLL("ntdll.dll")
|
||||
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
|
||||
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
modntdll = windows.NewLazySystemDLL("ntdll.dll")
|
||||
modws2_32 = windows.NewLazySystemDLL("ws2_32.dll")
|
||||
|
||||
procCancelIoEx = modkernel32.NewProc("CancelIoEx")
|
||||
procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort")
|
||||
procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus")
|
||||
procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes")
|
||||
procWSAGetOverlappedResult = modws2_32.NewProc("WSAGetOverlappedResult")
|
||||
procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe")
|
||||
procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW")
|
||||
procCreateFileW = modkernel32.NewProc("CreateFileW")
|
||||
procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo")
|
||||
procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW")
|
||||
procLocalAlloc = modkernel32.NewProc("LocalAlloc")
|
||||
procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile")
|
||||
procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb")
|
||||
procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U")
|
||||
procRtlDefaultNpAcl = modntdll.NewProc("RtlDefaultNpAcl")
|
||||
procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW")
|
||||
procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges")
|
||||
procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW")
|
||||
procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW")
|
||||
procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW")
|
||||
procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW")
|
||||
procLocalFree = modkernel32.NewProc("LocalFree")
|
||||
procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength")
|
||||
procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx")
|
||||
procSetFileInformationByHandle = modkernel32.NewProc("SetFileInformationByHandle")
|
||||
procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges")
|
||||
procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf")
|
||||
procRevertToSelf = modadvapi32.NewProc("RevertToSelf")
|
||||
procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken")
|
||||
procGetCurrentThread = modkernel32.NewProc("GetCurrentThread")
|
||||
procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW")
|
||||
procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW")
|
||||
procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW")
|
||||
procLookupPrivilegeDisplayNameW = modadvapi32.NewProc("LookupPrivilegeDisplayNameW")
|
||||
procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW")
|
||||
procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW")
|
||||
procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken")
|
||||
procRevertToSelf = modadvapi32.NewProc("RevertToSelf")
|
||||
procBackupRead = modkernel32.NewProc("BackupRead")
|
||||
procBackupWrite = modkernel32.NewProc("BackupWrite")
|
||||
procCancelIoEx = modkernel32.NewProc("CancelIoEx")
|
||||
procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe")
|
||||
procCreateFileW = modkernel32.NewProc("CreateFileW")
|
||||
procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort")
|
||||
procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW")
|
||||
procGetCurrentThread = modkernel32.NewProc("GetCurrentThread")
|
||||
procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW")
|
||||
procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo")
|
||||
procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus")
|
||||
procLocalAlloc = modkernel32.NewProc("LocalAlloc")
|
||||
procLocalFree = modkernel32.NewProc("LocalFree")
|
||||
procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes")
|
||||
procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile")
|
||||
procRtlDefaultNpAcl = modntdll.NewProc("RtlDefaultNpAcl")
|
||||
procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U")
|
||||
procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb")
|
||||
procWSAGetOverlappedResult = modws2_32.NewProc("WSAGetOverlappedResult")
|
||||
procbind = modws2_32.NewProc("bind")
|
||||
)
|
||||
|
||||
func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(file), uintptr(unsafe.Pointer(o)), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0)
|
||||
newport = syscall.Handle(r0)
|
||||
if newport == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(h), uintptr(flags), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) {
|
||||
func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) {
|
||||
var _p0 uint32
|
||||
if wait {
|
||||
if releaseAll {
|
||||
_p0 = 1
|
||||
} else {
|
||||
_p0 = 0
|
||||
}
|
||||
r1, _, e1 := syscall.Syscall6(procWSAGetOverlappedResult.Addr(), 5, uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags)), 0)
|
||||
r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(input)), uintptr(outputSize), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(requiredSize)))
|
||||
success = r0 != 0
|
||||
if true {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), 5, uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(secInfo), uintptr(unsafe.Pointer(sddl)), uintptr(unsafe.Pointer(sddlSize)), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return _createNamedPipe(_p0, flags, pipeMode, maxInstances, outSize, inSize, defaultTimeout, sa)
|
||||
}
|
||||
|
||||
func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0)
|
||||
handle = syscall.Handle(r0)
|
||||
if handle == syscall.InvalidHandle {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return _createFile(_p0, access, mode, sa, createmode, attrs, templatefile)
|
||||
}
|
||||
|
||||
func _createFile(name *uint16, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0)
|
||||
handle = syscall.Handle(r0)
|
||||
if handle == syscall.InvalidHandle {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procGetNamedPipeInfo.Addr(), 5, uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances)), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall9(procGetNamedPipeHandleStateW.Addr(), 7, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize), 0, 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func localAlloc(uFlags uint32, length uint32) (ptr uintptr) {
|
||||
r0, _, _ := syscall.Syscall(procLocalAlloc.Addr(), 2, uintptr(uFlags), uintptr(length), 0)
|
||||
ptr = uintptr(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) {
|
||||
r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0)
|
||||
status = ntstatus(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func rtlNtStatusToDosError(status ntstatus) (winerr error) {
|
||||
r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0)
|
||||
if r0 != 0 {
|
||||
winerr = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) {
|
||||
r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved), 0, 0)
|
||||
status = ntstatus(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) {
|
||||
r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0)
|
||||
status = ntstatus(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(accountName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return _lookupAccountName(systemName, _p0, sid, sidSize, refDomain, refDomainSize, sidNameUse)
|
||||
}
|
||||
|
||||
func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -281,11 +101,7 @@ func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidS
|
|||
func convertSidToStringSid(sid *byte, str **uint16) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(str)), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -302,126 +118,73 @@ func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision ui
|
|||
func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision uint32, sd *uintptr, size *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), 4, uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size)), 0, 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), 5, uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(secInfo), uintptr(unsafe.Pointer(sddl)), uintptr(unsafe.Pointer(sddlSize)), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func localFree(mem uintptr) {
|
||||
syscall.Syscall(procLocalFree.Addr(), 1, uintptr(mem), 0, 0)
|
||||
return
|
||||
}
|
||||
|
||||
func getSecurityDescriptorLength(sd uintptr) (len uint32) {
|
||||
r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0)
|
||||
len = uint32(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func getFileInformationByHandleEx(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), 4, uintptr(h), uintptr(class), uintptr(unsafe.Pointer(buffer)), uintptr(size), 0, 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func setFileInformationByHandle(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procSetFileInformationByHandle.Addr(), 4, uintptr(h), uintptr(class), uintptr(unsafe.Pointer(buffer)), uintptr(size), 0, 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) {
|
||||
var _p0 uint32
|
||||
if releaseAll {
|
||||
_p0 = 1
|
||||
} else {
|
||||
_p0 = 0
|
||||
}
|
||||
r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(input)), uintptr(outputSize), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(requiredSize)))
|
||||
success = r0 != 0
|
||||
if true {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func impersonateSelf(level uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(level), 0, 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func revertToSelf() (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0)
|
||||
func lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(accountName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return _lookupAccountName(systemName, _p0, sid, sidSize, refDomain, refDomainSize, sidNameUse)
|
||||
}
|
||||
|
||||
func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) {
|
||||
var _p0 uint32
|
||||
if openAsSelf {
|
||||
_p0 = 1
|
||||
} else {
|
||||
_p0 = 0
|
||||
func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(systemName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(thread), uintptr(accessMask), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0)
|
||||
return _lookupPrivilegeDisplayName(_p0, name, buffer, size, languageId)
|
||||
}
|
||||
|
||||
func _lookupPrivilegeDisplayName(systemName *uint16, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procLookupPrivilegeDisplayNameW.Addr(), 5, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), uintptr(unsafe.Pointer(languageId)), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getCurrentThread() (h syscall.Handle) {
|
||||
r0, _, _ := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0)
|
||||
h = syscall.Handle(r0)
|
||||
func lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(systemName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return _lookupPrivilegeName(_p0, luid, buffer, size)
|
||||
}
|
||||
|
||||
func _lookupPrivilegeName(systemName *uint16, luid *uint64, buffer *uint16, size *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procLookupPrivilegeNameW.Addr(), 4, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -442,53 +205,27 @@ func lookupPrivilegeValue(systemName string, name string, luid *uint64) (err err
|
|||
func _lookupPrivilegeValue(systemName *uint16, name *uint16, luid *uint64) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid)))
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(systemName)
|
||||
if err != nil {
|
||||
return
|
||||
func openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) {
|
||||
var _p0 uint32
|
||||
if openAsSelf {
|
||||
_p0 = 1
|
||||
}
|
||||
return _lookupPrivilegeName(_p0, luid, buffer, size)
|
||||
}
|
||||
|
||||
func _lookupPrivilegeName(systemName *uint16, luid *uint64, buffer *uint16, size *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procLookupPrivilegeNameW.Addr(), 4, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), 0, 0)
|
||||
r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(thread), uintptr(accessMask), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(systemName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return _lookupPrivilegeDisplayName(_p0, name, buffer, size, languageId)
|
||||
}
|
||||
|
||||
func _lookupPrivilegeDisplayName(systemName *uint16, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procLookupPrivilegeDisplayNameW.Addr(), 5, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), uintptr(unsafe.Pointer(languageId)), 0)
|
||||
func revertToSelf() (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -501,22 +238,14 @@ func backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, proce
|
|||
var _p1 uint32
|
||||
if abort {
|
||||
_p1 = 1
|
||||
} else {
|
||||
_p1 = 0
|
||||
}
|
||||
var _p2 uint32
|
||||
if processSecurity {
|
||||
_p2 = 1
|
||||
} else {
|
||||
_p2 = 0
|
||||
}
|
||||
r1, _, e1 := syscall.Syscall9(procBackupRead.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesRead)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -529,22 +258,162 @@ func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, p
|
|||
var _p1 uint32
|
||||
if abort {
|
||||
_p1 = 1
|
||||
} else {
|
||||
_p1 = 0
|
||||
}
|
||||
var _p2 uint32
|
||||
if processSecurity {
|
||||
_p2 = 1
|
||||
} else {
|
||||
_p2 = 0
|
||||
}
|
||||
r1, _, e1 := syscall.Syscall9(procBackupWrite.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesWritten)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(file), uintptr(unsafe.Pointer(o)), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return _createFile(_p0, access, mode, sa, createmode, attrs, templatefile)
|
||||
}
|
||||
|
||||
func _createFile(name *uint16, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0)
|
||||
handle = syscall.Handle(r0)
|
||||
if handle == syscall.InvalidHandle {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0)
|
||||
newport = syscall.Handle(r0)
|
||||
if newport == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return _createNamedPipe(_p0, flags, pipeMode, maxInstances, outSize, inSize, defaultTimeout, sa)
|
||||
}
|
||||
|
||||
func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0)
|
||||
handle = syscall.Handle(r0)
|
||||
if handle == syscall.InvalidHandle {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getCurrentThread() (h syscall.Handle) {
|
||||
r0, _, _ := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0)
|
||||
h = syscall.Handle(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall9(procGetNamedPipeHandleStateW.Addr(), 7, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procGetNamedPipeInfo.Addr(), 5, uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances)), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func localAlloc(uFlags uint32, length uint32) (ptr uintptr) {
|
||||
r0, _, _ := syscall.Syscall(procLocalAlloc.Addr(), 2, uintptr(uFlags), uintptr(length), 0)
|
||||
ptr = uintptr(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func localFree(mem uintptr) {
|
||||
syscall.Syscall(procLocalFree.Addr(), 1, uintptr(mem), 0, 0)
|
||||
return
|
||||
}
|
||||
|
||||
func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(h), uintptr(flags), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) {
|
||||
r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0)
|
||||
status = ntstatus(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) {
|
||||
r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0)
|
||||
status = ntstatus(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) {
|
||||
r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved), 0, 0)
|
||||
status = ntstatus(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func rtlNtStatusToDosError(status ntstatus) (winerr error) {
|
||||
r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0)
|
||||
if r0 != 0 {
|
||||
winerr = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) {
|
||||
var _p0 uint32
|
||||
if wait {
|
||||
_p0 = 1
|
||||
}
|
||||
r1, _, e1 := syscall.Syscall6(procWSAGetOverlappedResult.Addr(), 5, uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags)), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -552,11 +421,7 @@ func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, p
|
|||
func bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
|
||||
if r1 == socketError {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
3
vendor/github.com/ProtonMail/go-crypto/AUTHORS
generated
vendored
Normal file
3
vendor/github.com/ProtonMail/go-crypto/AUTHORS
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
# This source code refers to The Go Authors for copyright purposes.
|
||||
# The master list of authors is in the main Go distribution,
|
||||
# visible at https://tip.golang.org/AUTHORS.
|
3
vendor/github.com/ProtonMail/go-crypto/CONTRIBUTORS
generated
vendored
Normal file
3
vendor/github.com/ProtonMail/go-crypto/CONTRIBUTORS
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
# This source code was written by the Go contributors.
|
||||
# The master list of contributors is in the main Go distribution,
|
||||
# visible at https://tip.golang.org/CONTRIBUTORS.
|
27
vendor/github.com/ProtonMail/go-crypto/LICENSE
generated
vendored
Normal file
27
vendor/github.com/ProtonMail/go-crypto/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
22
vendor/github.com/ProtonMail/go-crypto/PATENTS
generated
vendored
Normal file
22
vendor/github.com/ProtonMail/go-crypto/PATENTS
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
Additional IP Rights Grant (Patents)
|
||||
|
||||
"This implementation" means the copyrightable works distributed by
|
||||
Google as part of the Go project.
|
||||
|
||||
Google hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||
no-charge, royalty-free, irrevocable (except as stated in this section)
|
||||
patent license to make, have made, use, offer to sell, sell, import,
|
||||
transfer and otherwise run, modify and propagate the contents of this
|
||||
implementation of Go, where such license applies only to those patent
|
||||
claims, both currently owned or controlled by Google and acquired in
|
||||
the future, licensable by Google that are necessarily infringed by this
|
||||
implementation of Go. This grant does not include claims that would be
|
||||
infringed only as a consequence of further modification of this
|
||||
implementation. If you or your agent or exclusive licensee institute or
|
||||
order or agree to the institution of patent litigation against any
|
||||
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||
that this implementation of Go or any code incorporated within this
|
||||
implementation of Go constitutes direct or contributory patent
|
||||
infringement, or inducement of patent infringement, then any patent
|
||||
rights granted to you under this License for this implementation of Go
|
||||
shall terminate as of the date such litigation is filed.
|
381
vendor/github.com/ProtonMail/go-crypto/bitcurves/bitcurve.go
generated
vendored
Normal file
381
vendor/github.com/ProtonMail/go-crypto/bitcurves/bitcurve.go
generated
vendored
Normal file
|
@ -0,0 +1,381 @@
|
|||
package bitcurves
|
||||
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Copyright 2011 ThePiachu. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package bitelliptic implements several Koblitz elliptic curves over prime
|
||||
// fields.
|
||||
|
||||
// This package operates, internally, on Jacobian coordinates. For a given
|
||||
// (x, y) position on the curve, the Jacobian coordinates are (x1, y1, z1)
|
||||
// where x = x1/z1² and y = y1/z1³. The greatest speedups come when the whole
|
||||
// calculation can be performed within the transform (as in ScalarMult and
|
||||
// ScalarBaseMult). But even for Add and Double, it's faster to apply and
|
||||
// reverse the transform than to operate in affine coordinates.
|
||||
|
||||
import (
|
||||
"crypto/elliptic"
|
||||
"io"
|
||||
"math/big"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// A BitCurve represents a Koblitz Curve with a=0.
|
||||
// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw.html
|
||||
type BitCurve struct {
|
||||
Name string
|
||||
P *big.Int // the order of the underlying field
|
||||
N *big.Int // the order of the base point
|
||||
B *big.Int // the constant of the BitCurve equation
|
||||
Gx, Gy *big.Int // (x,y) of the base point
|
||||
BitSize int // the size of the underlying field
|
||||
}
|
||||
|
||||
// Params returns the parameters of the given BitCurve (see BitCurve struct)
|
||||
func (bitCurve *BitCurve) Params() (cp *elliptic.CurveParams) {
|
||||
cp = new(elliptic.CurveParams)
|
||||
cp.Name = bitCurve.Name
|
||||
cp.P = bitCurve.P
|
||||
cp.N = bitCurve.N
|
||||
cp.Gx = bitCurve.Gx
|
||||
cp.Gy = bitCurve.Gy
|
||||
cp.BitSize = bitCurve.BitSize
|
||||
return cp
|
||||
}
|
||||
|
||||
// IsOnCurve returns true if the given (x,y) lies on the BitCurve.
|
||||
func (bitCurve *BitCurve) IsOnCurve(x, y *big.Int) bool {
|
||||
// y² = x³ + b
|
||||
y2 := new(big.Int).Mul(y, y) //y²
|
||||
y2.Mod(y2, bitCurve.P) //y²%P
|
||||
|
||||
x3 := new(big.Int).Mul(x, x) //x²
|
||||
x3.Mul(x3, x) //x³
|
||||
|
||||
x3.Add(x3, bitCurve.B) //x³+B
|
||||
x3.Mod(x3, bitCurve.P) //(x³+B)%P
|
||||
|
||||
return x3.Cmp(y2) == 0
|
||||
}
|
||||
|
||||
// affineFromJacobian reverses the Jacobian transform. See the comment at the
|
||||
// top of the file.
|
||||
func (bitCurve *BitCurve) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) {
|
||||
if z.Cmp(big.NewInt(0)) == 0 {
|
||||
panic("bitcurve: Can't convert to affine with Jacobian Z = 0")
|
||||
}
|
||||
// x = YZ^2 mod P
|
||||
zinv := new(big.Int).ModInverse(z, bitCurve.P)
|
||||
zinvsq := new(big.Int).Mul(zinv, zinv)
|
||||
|
||||
xOut = new(big.Int).Mul(x, zinvsq)
|
||||
xOut.Mod(xOut, bitCurve.P)
|
||||
// y = YZ^3 mod P
|
||||
zinvsq.Mul(zinvsq, zinv)
|
||||
yOut = new(big.Int).Mul(y, zinvsq)
|
||||
yOut.Mod(yOut, bitCurve.P)
|
||||
return xOut, yOut
|
||||
}
|
||||
|
||||
// Add returns the sum of (x1,y1) and (x2,y2)
|
||||
func (bitCurve *BitCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
|
||||
z := new(big.Int).SetInt64(1)
|
||||
x, y, z := bitCurve.addJacobian(x1, y1, z, x2, y2, z)
|
||||
return bitCurve.affineFromJacobian(x, y, z)
|
||||
}
|
||||
|
||||
// addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and
|
||||
// (x2, y2, z2) and returns their sum, also in Jacobian form.
|
||||
func (bitCurve *BitCurve) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) {
|
||||
// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
|
||||
z1z1 := new(big.Int).Mul(z1, z1)
|
||||
z1z1.Mod(z1z1, bitCurve.P)
|
||||
z2z2 := new(big.Int).Mul(z2, z2)
|
||||
z2z2.Mod(z2z2, bitCurve.P)
|
||||
|
||||
u1 := new(big.Int).Mul(x1, z2z2)
|
||||
u1.Mod(u1, bitCurve.P)
|
||||
u2 := new(big.Int).Mul(x2, z1z1)
|
||||
u2.Mod(u2, bitCurve.P)
|
||||
h := new(big.Int).Sub(u2, u1)
|
||||
if h.Sign() == -1 {
|
||||
h.Add(h, bitCurve.P)
|
||||
}
|
||||
i := new(big.Int).Lsh(h, 1)
|
||||
i.Mul(i, i)
|
||||
j := new(big.Int).Mul(h, i)
|
||||
|
||||
s1 := new(big.Int).Mul(y1, z2)
|
||||
s1.Mul(s1, z2z2)
|
||||
s1.Mod(s1, bitCurve.P)
|
||||
s2 := new(big.Int).Mul(y2, z1)
|
||||
s2.Mul(s2, z1z1)
|
||||
s2.Mod(s2, bitCurve.P)
|
||||
r := new(big.Int).Sub(s2, s1)
|
||||
if r.Sign() == -1 {
|
||||
r.Add(r, bitCurve.P)
|
||||
}
|
||||
r.Lsh(r, 1)
|
||||
v := new(big.Int).Mul(u1, i)
|
||||
|
||||
x3 := new(big.Int).Set(r)
|
||||
x3.Mul(x3, x3)
|
||||
x3.Sub(x3, j)
|
||||
x3.Sub(x3, v)
|
||||
x3.Sub(x3, v)
|
||||
x3.Mod(x3, bitCurve.P)
|
||||
|
||||
y3 := new(big.Int).Set(r)
|
||||
v.Sub(v, x3)
|
||||
y3.Mul(y3, v)
|
||||
s1.Mul(s1, j)
|
||||
s1.Lsh(s1, 1)
|
||||
y3.Sub(y3, s1)
|
||||
y3.Mod(y3, bitCurve.P)
|
||||
|
||||
z3 := new(big.Int).Add(z1, z2)
|
||||
z3.Mul(z3, z3)
|
||||
z3.Sub(z3, z1z1)
|
||||
if z3.Sign() == -1 {
|
||||
z3.Add(z3, bitCurve.P)
|
||||
}
|
||||
z3.Sub(z3, z2z2)
|
||||
if z3.Sign() == -1 {
|
||||
z3.Add(z3, bitCurve.P)
|
||||
}
|
||||
z3.Mul(z3, h)
|
||||
z3.Mod(z3, bitCurve.P)
|
||||
|
||||
return x3, y3, z3
|
||||
}
|
||||
|
||||
// Double returns 2*(x,y)
|
||||
func (bitCurve *BitCurve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
|
||||
z1 := new(big.Int).SetInt64(1)
|
||||
return bitCurve.affineFromJacobian(bitCurve.doubleJacobian(x1, y1, z1))
|
||||
}
|
||||
|
||||
// doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and
|
||||
// returns its double, also in Jacobian form.
|
||||
func (bitCurve *BitCurve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) {
|
||||
// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
|
||||
|
||||
a := new(big.Int).Mul(x, x) //X1²
|
||||
b := new(big.Int).Mul(y, y) //Y1²
|
||||
c := new(big.Int).Mul(b, b) //B²
|
||||
|
||||
d := new(big.Int).Add(x, b) //X1+B
|
||||
d.Mul(d, d) //(X1+B)²
|
||||
d.Sub(d, a) //(X1+B)²-A
|
||||
d.Sub(d, c) //(X1+B)²-A-C
|
||||
d.Mul(d, big.NewInt(2)) //2*((X1+B)²-A-C)
|
||||
|
||||
e := new(big.Int).Mul(big.NewInt(3), a) //3*A
|
||||
f := new(big.Int).Mul(e, e) //E²
|
||||
|
||||
x3 := new(big.Int).Mul(big.NewInt(2), d) //2*D
|
||||
x3.Sub(f, x3) //F-2*D
|
||||
x3.Mod(x3, bitCurve.P)
|
||||
|
||||
y3 := new(big.Int).Sub(d, x3) //D-X3
|
||||
y3.Mul(e, y3) //E*(D-X3)
|
||||
y3.Sub(y3, new(big.Int).Mul(big.NewInt(8), c)) //E*(D-X3)-8*C
|
||||
y3.Mod(y3, bitCurve.P)
|
||||
|
||||
z3 := new(big.Int).Mul(y, z) //Y1*Z1
|
||||
z3.Mul(big.NewInt(2), z3) //3*Y1*Z1
|
||||
z3.Mod(z3, bitCurve.P)
|
||||
|
||||
return x3, y3, z3
|
||||
}
|
||||
|
||||
//TODO: double check if it is okay
|
||||
// ScalarMult returns k*(Bx,By) where k is a number in big-endian form.
|
||||
func (bitCurve *BitCurve) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) {
|
||||
// We have a slight problem in that the identity of the group (the
|
||||
// point at infinity) cannot be represented in (x, y) form on a finite
|
||||
// machine. Thus the standard add/double algorithm has to be tweaked
|
||||
// slightly: our initial state is not the identity, but x, and we
|
||||
// ignore the first true bit in |k|. If we don't find any true bits in
|
||||
// |k|, then we return nil, nil, because we cannot return the identity
|
||||
// element.
|
||||
|
||||
Bz := new(big.Int).SetInt64(1)
|
||||
x := Bx
|
||||
y := By
|
||||
z := Bz
|
||||
|
||||
seenFirstTrue := false
|
||||
for _, byte := range k {
|
||||
for bitNum := 0; bitNum < 8; bitNum++ {
|
||||
if seenFirstTrue {
|
||||
x, y, z = bitCurve.doubleJacobian(x, y, z)
|
||||
}
|
||||
if byte&0x80 == 0x80 {
|
||||
if !seenFirstTrue {
|
||||
seenFirstTrue = true
|
||||
} else {
|
||||
x, y, z = bitCurve.addJacobian(Bx, By, Bz, x, y, z)
|
||||
}
|
||||
}
|
||||
byte <<= 1
|
||||
}
|
||||
}
|
||||
|
||||
if !seenFirstTrue {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return bitCurve.affineFromJacobian(x, y, z)
|
||||
}
|
||||
|
||||
// ScalarBaseMult returns k*G, where G is the base point of the group and k is
|
||||
// an integer in big-endian form.
|
||||
func (bitCurve *BitCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
|
||||
return bitCurve.ScalarMult(bitCurve.Gx, bitCurve.Gy, k)
|
||||
}
|
||||
|
||||
var mask = []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f}
|
||||
|
||||
//TODO: double check if it is okay
|
||||
// GenerateKey returns a public/private key pair. The private key is generated
|
||||
// using the given reader, which must return random data.
|
||||
func (bitCurve *BitCurve) GenerateKey(rand io.Reader) (priv []byte, x, y *big.Int, err error) {
|
||||
byteLen := (bitCurve.BitSize + 7) >> 3
|
||||
priv = make([]byte, byteLen)
|
||||
|
||||
for x == nil {
|
||||
_, err = io.ReadFull(rand, priv)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// We have to mask off any excess bits in the case that the size of the
|
||||
// underlying field is not a whole number of bytes.
|
||||
priv[0] &= mask[bitCurve.BitSize%8]
|
||||
// This is because, in tests, rand will return all zeros and we don't
|
||||
// want to get the point at infinity and loop forever.
|
||||
priv[1] ^= 0x42
|
||||
x, y = bitCurve.ScalarBaseMult(priv)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Marshal converts a point into the form specified in section 4.3.6 of ANSI
|
||||
// X9.62.
|
||||
func (bitCurve *BitCurve) Marshal(x, y *big.Int) []byte {
|
||||
byteLen := (bitCurve.BitSize + 7) >> 3
|
||||
|
||||
ret := make([]byte, 1+2*byteLen)
|
||||
ret[0] = 4 // uncompressed point
|
||||
|
||||
xBytes := x.Bytes()
|
||||
copy(ret[1+byteLen-len(xBytes):], xBytes)
|
||||
yBytes := y.Bytes()
|
||||
copy(ret[1+2*byteLen-len(yBytes):], yBytes)
|
||||
return ret
|
||||
}
|
||||
|
||||
// Unmarshal converts a point, serialised by Marshal, into an x, y pair. On
|
||||
// error, x = nil.
|
||||
func (bitCurve *BitCurve) Unmarshal(data []byte) (x, y *big.Int) {
|
||||
byteLen := (bitCurve.BitSize + 7) >> 3
|
||||
if len(data) != 1+2*byteLen {
|
||||
return
|
||||
}
|
||||
if data[0] != 4 { // uncompressed form
|
||||
return
|
||||
}
|
||||
x = new(big.Int).SetBytes(data[1 : 1+byteLen])
|
||||
y = new(big.Int).SetBytes(data[1+byteLen:])
|
||||
return
|
||||
}
|
||||
|
||||
//curve parameters taken from:
|
||||
//http://www.secg.org/collateral/sec2_final.pdf
|
||||
|
||||
var initonce sync.Once
|
||||
var secp160k1 *BitCurve
|
||||
var secp192k1 *BitCurve
|
||||
var secp224k1 *BitCurve
|
||||
var secp256k1 *BitCurve
|
||||
|
||||
func initAll() {
|
||||
initS160()
|
||||
initS192()
|
||||
initS224()
|
||||
initS256()
|
||||
}
|
||||
|
||||
func initS160() {
|
||||
// See SEC 2 section 2.4.1
|
||||
secp160k1 = new(BitCurve)
|
||||
secp160k1.Name = "secp160k1"
|
||||
secp160k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", 16)
|
||||
secp160k1.N, _ = new(big.Int).SetString("0100000000000000000001B8FA16DFAB9ACA16B6B3", 16)
|
||||
secp160k1.B, _ = new(big.Int).SetString("0000000000000000000000000000000000000007", 16)
|
||||
secp160k1.Gx, _ = new(big.Int).SetString("3B4C382CE37AA192A4019E763036F4F5DD4D7EBB", 16)
|
||||
secp160k1.Gy, _ = new(big.Int).SetString("938CF935318FDCED6BC28286531733C3F03C4FEE", 16)
|
||||
secp160k1.BitSize = 160
|
||||
}
|
||||
|
||||
func initS192() {
|
||||
// See SEC 2 section 2.5.1
|
||||
secp192k1 = new(BitCurve)
|
||||
secp192k1.Name = "secp192k1"
|
||||
secp192k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", 16)
|
||||
secp192k1.N, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", 16)
|
||||
secp192k1.B, _ = new(big.Int).SetString("000000000000000000000000000000000000000000000003", 16)
|
||||
secp192k1.Gx, _ = new(big.Int).SetString("DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", 16)
|
||||
secp192k1.Gy, _ = new(big.Int).SetString("9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", 16)
|
||||
secp192k1.BitSize = 192
|
||||
}
|
||||
|
||||
func initS224() {
|
||||
// See SEC 2 section 2.6.1
|
||||
secp224k1 = new(BitCurve)
|
||||
secp224k1.Name = "secp224k1"
|
||||
secp224k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", 16)
|
||||
secp224k1.N, _ = new(big.Int).SetString("010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", 16)
|
||||
secp224k1.B, _ = new(big.Int).SetString("00000000000000000000000000000000000000000000000000000005", 16)
|
||||
secp224k1.Gx, _ = new(big.Int).SetString("A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C", 16)
|
||||
secp224k1.Gy, _ = new(big.Int).SetString("7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", 16)
|
||||
secp224k1.BitSize = 224
|
||||
}
|
||||
|
||||
func initS256() {
|
||||
// See SEC 2 section 2.7.1
|
||||
secp256k1 = new(BitCurve)
|
||||
secp256k1.Name = "secp256k1"
|
||||
secp256k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16)
|
||||
secp256k1.N, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16)
|
||||
secp256k1.B, _ = new(big.Int).SetString("0000000000000000000000000000000000000000000000000000000000000007", 16)
|
||||
secp256k1.Gx, _ = new(big.Int).SetString("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16)
|
||||
secp256k1.Gy, _ = new(big.Int).SetString("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16)
|
||||
secp256k1.BitSize = 256
|
||||
}
|
||||
|
||||
// S160 returns a BitCurve which implements secp160k1 (see SEC 2 section 2.4.1)
|
||||
func S160() *BitCurve {
|
||||
initonce.Do(initAll)
|
||||
return secp160k1
|
||||
}
|
||||
|
||||
// S192 returns a BitCurve which implements secp192k1 (see SEC 2 section 2.5.1)
|
||||
func S192() *BitCurve {
|
||||
initonce.Do(initAll)
|
||||
return secp192k1
|
||||
}
|
||||
|
||||
// S224 returns a BitCurve which implements secp224k1 (see SEC 2 section 2.6.1)
|
||||
func S224() *BitCurve {
|
||||
initonce.Do(initAll)
|
||||
return secp224k1
|
||||
}
|
||||
|
||||
// S256 returns a BitCurve which implements bitcurves (see SEC 2 section 2.7.1)
|
||||
func S256() *BitCurve {
|
||||
initonce.Do(initAll)
|
||||
return secp256k1
|
||||
}
|
134
vendor/github.com/ProtonMail/go-crypto/brainpool/brainpool.go
generated
vendored
Normal file
134
vendor/github.com/ProtonMail/go-crypto/brainpool/brainpool.go
generated
vendored
Normal file
|
@ -0,0 +1,134 @@
|
|||
// Package brainpool implements Brainpool elliptic curves.
|
||||
// Implementation of rcurves is from github.com/ebfe/brainpool
|
||||
// Note that these curves are implemented with naive, non-constant time operations
|
||||
// and are likely not suitable for enviroments where timing attacks are a concern.
|
||||
package brainpool
|
||||
|
||||
import (
|
||||
"crypto/elliptic"
|
||||
"math/big"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
once sync.Once
|
||||
p256t1, p384t1, p512t1 *elliptic.CurveParams
|
||||
p256r1, p384r1, p512r1 *rcurve
|
||||
)
|
||||
|
||||
func initAll() {
|
||||
initP256t1()
|
||||
initP384t1()
|
||||
initP512t1()
|
||||
initP256r1()
|
||||
initP384r1()
|
||||
initP512r1()
|
||||
}
|
||||
|
||||
func initP256t1() {
|
||||
p256t1 = &elliptic.CurveParams{Name: "brainpoolP256t1"}
|
||||
p256t1.P, _ = new(big.Int).SetString("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", 16)
|
||||
p256t1.N, _ = new(big.Int).SetString("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16)
|
||||
p256t1.B, _ = new(big.Int).SetString("662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04", 16)
|
||||
p256t1.Gx, _ = new(big.Int).SetString("A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F4", 16)
|
||||
p256t1.Gy, _ = new(big.Int).SetString("2D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE", 16)
|
||||
p256t1.BitSize = 256
|
||||
}
|
||||
|
||||
func initP256r1() {
|
||||
twisted := p256t1
|
||||
params := &elliptic.CurveParams{
|
||||
Name: "brainpoolP256r1",
|
||||
P: twisted.P,
|
||||
N: twisted.N,
|
||||
BitSize: twisted.BitSize,
|
||||
}
|
||||
params.Gx, _ = new(big.Int).SetString("8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", 16)
|
||||
params.Gy, _ = new(big.Int).SetString("547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", 16)
|
||||
z, _ := new(big.Int).SetString("3E2D4BD9597B58639AE7AA669CAB9837CF5CF20A2C852D10F655668DFC150EF0", 16)
|
||||
p256r1 = newrcurve(twisted, params, z)
|
||||
}
|
||||
|
||||
func initP384t1() {
|
||||
p384t1 = &elliptic.CurveParams{Name: "brainpoolP384t1"}
|
||||
p384t1.P, _ = new(big.Int).SetString("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", 16)
|
||||
p384t1.N, _ = new(big.Int).SetString("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 16)
|
||||
p384t1.B, _ = new(big.Int).SetString("7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE", 16)
|
||||
p384t1.Gx, _ = new(big.Int).SetString("18DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC", 16)
|
||||
p384t1.Gy, _ = new(big.Int).SetString("25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928", 16)
|
||||
p384t1.BitSize = 384
|
||||
}
|
||||
|
||||
func initP384r1() {
|
||||
twisted := p384t1
|
||||
params := &elliptic.CurveParams{
|
||||
Name: "brainpoolP384r1",
|
||||
P: twisted.P,
|
||||
N: twisted.N,
|
||||
BitSize: twisted.BitSize,
|
||||
}
|
||||
params.Gx, _ = new(big.Int).SetString("1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", 16)
|
||||
params.Gy, _ = new(big.Int).SetString("8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", 16)
|
||||
z, _ := new(big.Int).SetString("41DFE8DD399331F7166A66076734A89CD0D2BCDB7D068E44E1F378F41ECBAE97D2D63DBC87BCCDDCCC5DA39E8589291C", 16)
|
||||
p384r1 = newrcurve(twisted, params, z)
|
||||
}
|
||||
|
||||
func initP512t1() {
|
||||
p512t1 = &elliptic.CurveParams{Name: "brainpoolP512t1"}
|
||||
p512t1.P, _ = new(big.Int).SetString("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", 16)
|
||||
p512t1.N, _ = new(big.Int).SetString("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 16)
|
||||
p512t1.B, _ = new(big.Int).SetString("7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E", 16)
|
||||
p512t1.Gx, _ = new(big.Int).SetString("640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA", 16)
|
||||
p512t1.Gy, _ = new(big.Int).SetString("5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332", 16)
|
||||
p512t1.BitSize = 512
|
||||
}
|
||||
|
||||
func initP512r1() {
|
||||
twisted := p512t1
|
||||
params := &elliptic.CurveParams{
|
||||
Name: "brainpoolP512r1",
|
||||
P: twisted.P,
|
||||
N: twisted.N,
|
||||
BitSize: twisted.BitSize,
|
||||
}
|
||||
params.Gx, _ = new(big.Int).SetString("81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", 16)
|
||||
params.Gy, _ = new(big.Int).SetString("7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", 16)
|
||||
z, _ := new(big.Int).SetString("12EE58E6764838B69782136F0F2D3BA06E27695716054092E60A80BEDB212B64E585D90BCE13761F85C3F1D2A64E3BE8FEA2220F01EBA5EEB0F35DBD29D922AB", 16)
|
||||
p512r1 = newrcurve(twisted, params, z)
|
||||
}
|
||||
|
||||
// P256t1 returns a Curve which implements Brainpool P256t1 (see RFC 5639, section 3.4)
|
||||
func P256t1() elliptic.Curve {
|
||||
once.Do(initAll)
|
||||
return p256t1
|
||||
}
|
||||
|
||||
// P256r1 returns a Curve which implements Brainpool P256r1 (see RFC 5639, section 3.4)
|
||||
func P256r1() elliptic.Curve {
|
||||
once.Do(initAll)
|
||||
return p256r1
|
||||
}
|
||||
|
||||
// P384t1 returns a Curve which implements Brainpool P384t1 (see RFC 5639, section 3.6)
|
||||
func P384t1() elliptic.Curve {
|
||||
once.Do(initAll)
|
||||
return p384t1
|
||||
}
|
||||
|
||||
// P384r1 returns a Curve which implements Brainpool P384r1 (see RFC 5639, section 3.6)
|
||||
func P384r1() elliptic.Curve {
|
||||
once.Do(initAll)
|
||||
return p384r1
|
||||
}
|
||||
|
||||
// P512t1 returns a Curve which implements Brainpool P512t1 (see RFC 5639, section 3.7)
|
||||
func P512t1() elliptic.Curve {
|
||||
once.Do(initAll)
|
||||
return p512t1
|
||||
}
|
||||
|
||||
// P512r1 returns a Curve which implements Brainpool P512r1 (see RFC 5639, section 3.7)
|
||||
func P512r1() elliptic.Curve {
|
||||
once.Do(initAll)
|
||||
return p512r1
|
||||
}
|
83
vendor/github.com/ProtonMail/go-crypto/brainpool/rcurve.go
generated
vendored
Normal file
83
vendor/github.com/ProtonMail/go-crypto/brainpool/rcurve.go
generated
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
package brainpool
|
||||
|
||||
import (
|
||||
"crypto/elliptic"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
var _ elliptic.Curve = (*rcurve)(nil)
|
||||
|
||||
type rcurve struct {
|
||||
twisted elliptic.Curve
|
||||
params *elliptic.CurveParams
|
||||
z *big.Int
|
||||
zinv *big.Int
|
||||
z2 *big.Int
|
||||
z3 *big.Int
|
||||
zinv2 *big.Int
|
||||
zinv3 *big.Int
|
||||
}
|
||||
|
||||
var (
|
||||
two = big.NewInt(2)
|
||||
three = big.NewInt(3)
|
||||
)
|
||||
|
||||
func newrcurve(twisted elliptic.Curve, params *elliptic.CurveParams, z *big.Int) *rcurve {
|
||||
zinv := new(big.Int).ModInverse(z, params.P)
|
||||
return &rcurve{
|
||||
twisted: twisted,
|
||||
params: params,
|
||||
z: z,
|
||||
zinv: zinv,
|
||||
z2: new(big.Int).Exp(z, two, params.P),
|
||||
z3: new(big.Int).Exp(z, three, params.P),
|
||||
zinv2: new(big.Int).Exp(zinv, two, params.P),
|
||||
zinv3: new(big.Int).Exp(zinv, three, params.P),
|
||||
}
|
||||
}
|
||||
|
||||
func (curve *rcurve) toTwisted(x, y *big.Int) (*big.Int, *big.Int) {
|
||||
var tx, ty big.Int
|
||||
tx.Mul(x, curve.z2)
|
||||
tx.Mod(&tx, curve.params.P)
|
||||
ty.Mul(y, curve.z3)
|
||||
ty.Mod(&ty, curve.params.P)
|
||||
return &tx, &ty
|
||||
}
|
||||
|
||||
func (curve *rcurve) fromTwisted(tx, ty *big.Int) (*big.Int, *big.Int) {
|
||||
var x, y big.Int
|
||||
x.Mul(tx, curve.zinv2)
|
||||
x.Mod(&x, curve.params.P)
|
||||
y.Mul(ty, curve.zinv3)
|
||||
y.Mod(&y, curve.params.P)
|
||||
return &x, &y
|
||||
}
|
||||
|
||||
func (curve *rcurve) Params() *elliptic.CurveParams {
|
||||
return curve.params
|
||||
}
|
||||
|
||||
func (curve *rcurve) IsOnCurve(x, y *big.Int) bool {
|
||||
return curve.twisted.IsOnCurve(curve.toTwisted(x, y))
|
||||
}
|
||||
|
||||
func (curve *rcurve) Add(x1, y1, x2, y2 *big.Int) (x, y *big.Int) {
|
||||
tx1, ty1 := curve.toTwisted(x1, y1)
|
||||
tx2, ty2 := curve.toTwisted(x2, y2)
|
||||
return curve.fromTwisted(curve.twisted.Add(tx1, ty1, tx2, ty2))
|
||||
}
|
||||
|
||||
func (curve *rcurve) Double(x1, y1 *big.Int) (x, y *big.Int) {
|
||||
return curve.fromTwisted(curve.twisted.Double(curve.toTwisted(x1, y1)))
|
||||
}
|
||||
|
||||
func (curve *rcurve) ScalarMult(x1, y1 *big.Int, scalar []byte) (x, y *big.Int) {
|
||||
tx1, ty1 := curve.toTwisted(x1, y1)
|
||||
return curve.fromTwisted(curve.twisted.ScalarMult(tx1, ty1, scalar))
|
||||
}
|
||||
|
||||
func (curve *rcurve) ScalarBaseMult(scalar []byte) (x, y *big.Int) {
|
||||
return curve.fromTwisted(curve.twisted.ScalarBaseMult(scalar))
|
||||
}
|
162
vendor/github.com/ProtonMail/go-crypto/eax/eax.go
generated
vendored
Normal file
162
vendor/github.com/ProtonMail/go-crypto/eax/eax.go
generated
vendored
Normal file
|
@ -0,0 +1,162 @@
|
|||
// Copyright (C) 2019 ProtonTech AG
|
||||
|
||||
// Package eax provides an implementation of the EAX
|
||||
// (encrypt-authenticate-translate) mode of operation, as described in
|
||||
// Bellare, Rogaway, and Wagner "THE EAX MODE OF OPERATION: A TWO-PASS
|
||||
// AUTHENTICATED-ENCRYPTION SCHEME OPTIMIZED FOR SIMPLICITY AND EFFICIENCY."
|
||||
// In FSE'04, volume 3017 of LNCS, 2004
|
||||
package eax
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
"github.com/ProtonMail/go-crypto/internal/byteutil"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultTagSize = 16
|
||||
defaultNonceSize = 16
|
||||
)
|
||||
|
||||
type eax struct {
|
||||
block cipher.Block // Only AES-{128, 192, 256} supported
|
||||
tagSize int // At least 12 bytes recommended
|
||||
nonceSize int
|
||||
}
|
||||
|
||||
func (e *eax) NonceSize() int {
|
||||
return e.nonceSize
|
||||
}
|
||||
|
||||
func (e *eax) Overhead() int {
|
||||
return e.tagSize
|
||||
}
|
||||
|
||||
// NewEAX returns an EAX instance with AES-{KEYLENGTH} and default nonce and
|
||||
// tag lengths. Supports {128, 192, 256}- bit key length.
|
||||
func NewEAX(block cipher.Block) (cipher.AEAD, error) {
|
||||
return NewEAXWithNonceAndTagSize(block, defaultNonceSize, defaultTagSize)
|
||||
}
|
||||
|
||||
// NewEAXWithNonceAndTagSize returns an EAX instance with AES-{keyLength} and
|
||||
// given nonce and tag lengths in bytes. Panics on zero nonceSize and
|
||||
// exceedingly long tags.
|
||||
//
|
||||
// It is recommended to use at least 12 bytes as tag length (see, for instance,
|
||||
// NIST SP 800-38D).
|
||||
//
|
||||
// Only to be used for compatibility with existing cryptosystems with
|
||||
// non-standard parameters. For all other cases, prefer NewEAX.
|
||||
func NewEAXWithNonceAndTagSize(
|
||||
block cipher.Block, nonceSize, tagSize int) (cipher.AEAD, error) {
|
||||
if nonceSize < 1 {
|
||||
return nil, eaxError("Cannot initialize EAX with nonceSize = 0")
|
||||
}
|
||||
if tagSize > block.BlockSize() {
|
||||
return nil, eaxError("Custom tag length exceeds blocksize")
|
||||
}
|
||||
return &eax{
|
||||
block: block,
|
||||
tagSize: tagSize,
|
||||
nonceSize: nonceSize,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (e *eax) Seal(dst, nonce, plaintext, adata []byte) []byte {
|
||||
if len(nonce) > e.nonceSize {
|
||||
panic("crypto/eax: Nonce too long for this instance")
|
||||
}
|
||||
ret, out := byteutil.SliceForAppend(dst, len(plaintext) + e.tagSize)
|
||||
omacNonce := e.omacT(0, nonce)
|
||||
omacAdata := e.omacT(1, adata)
|
||||
|
||||
// Encrypt message using CTR mode and omacNonce as IV
|
||||
ctr := cipher.NewCTR(e.block, omacNonce)
|
||||
ciphertextData := out[:len(plaintext)]
|
||||
ctr.XORKeyStream(ciphertextData, plaintext)
|
||||
|
||||
omacCiphertext := e.omacT(2, ciphertextData)
|
||||
|
||||
tag := out[len(plaintext):]
|
||||
for i := 0; i < e.tagSize; i++ {
|
||||
tag[i] = omacCiphertext[i] ^ omacNonce[i] ^ omacAdata[i]
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (e* eax) Open(dst, nonce, ciphertext, adata []byte) ([]byte, error) {
|
||||
if len(nonce) > e.nonceSize {
|
||||
panic("crypto/eax: Nonce too long for this instance")
|
||||
}
|
||||
if len(ciphertext) < e.tagSize {
|
||||
return nil, eaxError("Ciphertext shorter than tag length")
|
||||
}
|
||||
sep := len(ciphertext) - e.tagSize
|
||||
|
||||
// Compute tag
|
||||
omacNonce := e.omacT(0, nonce)
|
||||
omacAdata := e.omacT(1, adata)
|
||||
omacCiphertext := e.omacT(2, ciphertext[:sep])
|
||||
|
||||
tag := make([]byte, e.tagSize)
|
||||
for i := 0; i < e.tagSize; i++ {
|
||||
tag[i] = omacCiphertext[i] ^ omacNonce[i] ^ omacAdata[i]
|
||||
}
|
||||
|
||||
// Compare tags
|
||||
if subtle.ConstantTimeCompare(ciphertext[sep:], tag) != 1 {
|
||||
return nil, eaxError("Tag authentication failed")
|
||||
}
|
||||
|
||||
// Decrypt ciphertext
|
||||
ret, out := byteutil.SliceForAppend(dst, len(ciphertext))
|
||||
ctr := cipher.NewCTR(e.block, omacNonce)
|
||||
ctr.XORKeyStream(out, ciphertext[:sep])
|
||||
|
||||
return ret[:sep], nil
|
||||
}
|
||||
|
||||
// Tweakable OMAC - Calls OMAC_K([t]_n || plaintext)
|
||||
func (e *eax) omacT(t byte, plaintext []byte) []byte {
|
||||
blockSize := e.block.BlockSize()
|
||||
byteT := make([]byte, blockSize)
|
||||
byteT[blockSize-1] = t
|
||||
concat := append(byteT, plaintext...)
|
||||
return e.omac(concat)
|
||||
}
|
||||
|
||||
func (e *eax) omac(plaintext []byte) []byte {
|
||||
blockSize := e.block.BlockSize()
|
||||
// L ← E_K(0^n); B ← 2L; P ← 4L
|
||||
L := make([]byte, blockSize)
|
||||
e.block.Encrypt(L, L)
|
||||
B := byteutil.GfnDouble(L)
|
||||
P := byteutil.GfnDouble(B)
|
||||
|
||||
// CBC with IV = 0
|
||||
cbc := cipher.NewCBCEncrypter(e.block, make([]byte, blockSize))
|
||||
padded := e.pad(plaintext, B, P)
|
||||
cbcCiphertext := make([]byte, len(padded))
|
||||
cbc.CryptBlocks(cbcCiphertext, padded)
|
||||
|
||||
return cbcCiphertext[len(cbcCiphertext)-blockSize:]
|
||||
}
|
||||
|
||||
func (e *eax) pad(plaintext, B, P []byte) []byte {
|
||||
// if |M| in {n, 2n, 3n, ...}
|
||||
blockSize := e.block.BlockSize()
|
||||
if len(plaintext) != 0 && len(plaintext)%blockSize == 0 {
|
||||
return byteutil.RightXor(plaintext, B)
|
||||
}
|
||||
|
||||
// else return (M || 1 || 0^(n−1−(|M| % n))) xor→ P
|
||||
ending := make([]byte, blockSize-len(plaintext)%blockSize)
|
||||
ending[0] = 0x80
|
||||
padded := append(plaintext, ending...)
|
||||
return byteutil.RightXor(padded, P)
|
||||
}
|
||||
|
||||
func eaxError(err string) error {
|
||||
return errors.New("crypto/eax: " + err)
|
||||
}
|
58
vendor/github.com/ProtonMail/go-crypto/eax/eax_test_vectors.go
generated
vendored
Normal file
58
vendor/github.com/ProtonMail/go-crypto/eax/eax_test_vectors.go
generated
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
package eax
|
||||
|
||||
// Test vectors from
|
||||
// https://web.cs.ucdavis.edu/~rogaway/papers/eax.pdf
|
||||
var testVectors = []struct {
|
||||
msg, key, nonce, header, ciphertext string
|
||||
}{
|
||||
{"",
|
||||
"233952DEE4D5ED5F9B9C6D6FF80FF478",
|
||||
"62EC67F9C3A4A407FCB2A8C49031A8B3",
|
||||
"6BFB914FD07EAE6B",
|
||||
"E037830E8389F27B025A2D6527E79D01"},
|
||||
{"F7FB",
|
||||
"91945D3F4DCBEE0BF45EF52255F095A4",
|
||||
"BECAF043B0A23D843194BA972C66DEBD",
|
||||
"FA3BFD4806EB53FA",
|
||||
"19DD5C4C9331049D0BDAB0277408F67967E5"},
|
||||
{"1A47CB4933",
|
||||
"01F74AD64077F2E704C0F60ADA3DD523",
|
||||
"70C3DB4F0D26368400A10ED05D2BFF5E",
|
||||
"234A3463C1264AC6",
|
||||
"D851D5BAE03A59F238A23E39199DC9266626C40F80"},
|
||||
{"481C9E39B1",
|
||||
"D07CF6CBB7F313BDDE66B727AFD3C5E8",
|
||||
"8408DFFF3C1A2B1292DC199E46B7D617",
|
||||
"33CCE2EABFF5A79D",
|
||||
"632A9D131AD4C168A4225D8E1FF755939974A7BEDE"},
|
||||
{"40D0C07DA5E4",
|
||||
"35B6D0580005BBC12B0587124557D2C2",
|
||||
"FDB6B06676EEDC5C61D74276E1F8E816",
|
||||
"AEB96EAEBE2970E9",
|
||||
"071DFE16C675CB0677E536F73AFE6A14B74EE49844DD"},
|
||||
{"4DE3B35C3FC039245BD1FB7D",
|
||||
"BD8E6E11475E60B268784C38C62FEB22",
|
||||
"6EAC5C93072D8E8513F750935E46DA1B",
|
||||
"D4482D1CA78DCE0F",
|
||||
"835BB4F15D743E350E728414ABB8644FD6CCB86947C5E10590210A4F"},
|
||||
{"8B0A79306C9CE7ED99DAE4F87F8DD61636",
|
||||
"7C77D6E813BED5AC98BAA417477A2E7D",
|
||||
"1A8C98DCD73D38393B2BF1569DEEFC19",
|
||||
"65D2017990D62528",
|
||||
"02083E3979DA014812F59F11D52630DA30137327D10649B0AA6E1C181DB617D7F2"},
|
||||
{"1BDA122BCE8A8DBAF1877D962B8592DD2D56",
|
||||
"5FFF20CAFAB119CA2FC73549E20F5B0D",
|
||||
"DDE59B97D722156D4D9AFF2BC7559826",
|
||||
"54B9F04E6A09189A",
|
||||
"2EC47B2C4954A489AFC7BA4897EDCDAE8CC33B60450599BD02C96382902AEF7F832A"},
|
||||
{"6CF36720872B8513F6EAB1A8A44438D5EF11",
|
||||
"A4A4782BCFFD3EC5E7EF6D8C34A56123",
|
||||
"B781FCF2F75FA5A8DE97A9CA48E522EC",
|
||||
"899A175897561D7E",
|
||||
"0DE18FD0FDD91E7AF19F1D8EE8733938B1E8E7F6D2231618102FDB7FE55FF1991700"},
|
||||
{"CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7",
|
||||
"8395FCF1E95BEBD697BD010BC766AAC3",
|
||||
"22E7ADD93CFC6393C57EC0B3C17D6B44",
|
||||
"126735FCC320D25A",
|
||||
"CB8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC253B4652B1AF3795B124AB6E"},
|
||||
}
|
131
vendor/github.com/ProtonMail/go-crypto/eax/random_vectors.go
generated
vendored
Normal file
131
vendor/github.com/ProtonMail/go-crypto/eax/random_vectors.go
generated
vendored
Normal file
|
@ -0,0 +1,131 @@
|
|||
// These vectors include key length in {128, 192, 256}, tag size 128, and
|
||||
// random nonce, header, and plaintext lengths.
|
||||
|
||||
// This file was automatically generated.
|
||||
|
||||
package eax
|
||||
|
||||
var randomVectors = []struct {
|
||||
key, nonce, header, plaintext, ciphertext string
|
||||
}{
|
||||
{"DFDE093F36B0356E5A81F609786982E3",
|
||||
"1D8AC604419001816905BA72B14CED7E",
|
||||
"152A1517A998D7A24163FCDD146DE81AC347C8B97088F502093C1ABB8F6E33D9A219C34D7603A18B1F5ABE02E56661B7D7F67E81EC08C1302EF38D80A859486D450E94A4F26AD9E68EEBBC0C857A0FC5CF9E641D63D565A7E361BC8908F5A8DC8FD6",
|
||||
"1C8EAAB71077FE18B39730A3156ADE29C5EE824C7EE86ED2A253B775603FB237116E654F6FEC588DD27F523A0E01246FE73FE348491F2A8E9ABC6CA58D663F71CDBCF4AD798BE46C42AE6EE8B599DB44A1A48D7BBBBA0F7D2750181E1C5E66967F7D57CBD30AFBDA5727",
|
||||
"79E7E150934BBEBF7013F61C60462A14D8B15AF7A248AFB8A344EF021C1500E16666891D6E973D8BB56B71A371F12CA34660C4410C016982B20F547E3762A58B7BF4F20236CADCF559E2BE7D783B13723B2741FC7CDC8997D839E39A3DDD2BADB96743DD7049F1BDB0516A262869915B3F70498AFB7B191BF960"},
|
||||
{"F10619EF02E5D94D7550EB84ED364A21",
|
||||
"8DC0D4F2F745BBAE835CC5574B942D20",
|
||||
"FE561358F2E8DF7E1024FF1AE9A8D36EBD01352214505CB99D644777A8A1F6027FA2BDBFC529A9B91136D5F2416CFC5F0F4EC3A1AFD32BDDA23CA504C5A5CB451785FABF4DFE4CD50D817491991A60615B30286361C100A95D1712F2A45F8E374461F4CA2B",
|
||||
"D7B5A971FC219631D30EFC3664AE3127D9CF3097DAD9C24AC7905D15E8D9B25B026B31D68CAE00975CDB81EB1FD96FD5E1A12E2BB83FA25F1B1D91363457657FC03875C27F2946C5",
|
||||
"2F336ED42D3CC38FC61660C4CD60BA4BD438B05F5965D8B7B399D2E7167F5D34F792D318F94DB15D67463AC449E13D568CC09BFCE32A35EE3EE96A041927680AE329811811E27F2D1E8E657707AF99BA96D13A478D695D59"},
|
||||
{"429F514EFC64D98A698A9247274CFF45",
|
||||
"976AA5EB072F912D126ACEBC954FEC38",
|
||||
"A71D89DC5B6CEDBB7451A27C3C2CAE09126DB4C421",
|
||||
"5632FE62AB1DC549D54D3BC3FC868ACCEDEFD9ECF5E9F8",
|
||||
"848AE4306CA8C7F416F8707625B7F55881C0AB430353A5C967CDA2DA787F581A70E34DBEBB2385"},
|
||||
{"398138F309085F47F8457CDF53895A63",
|
||||
"F8A8A7F2D28E5FFF7BBC2F24353F7A36",
|
||||
"5D633C21BA7764B8855CAB586F3746E236AD486039C83C6B56EFA9C651D38A41D6B20DAEE3418BFEA44B8BD6",
|
||||
"A3BBAA91920AF5E10659818B1B3B300AC79BFC129C8329E75251F73A66D3AE0128EB91D5031E0A65C329DB7D1E9C0493E268",
|
||||
"D078097267606E5FB07CFB7E2B4B718172A82C6A4CEE65D549A4DFB9838003BD2FBF64A7A66988AC1A632FD88F9E9FBB57C5A78AD2E086EACBA3DB68511D81C2970A"},
|
||||
{"7A4151EBD3901B42CBA45DAFB2E931BA",
|
||||
"0FC88ACEE74DD538040321C330974EB8",
|
||||
"250464FB04733BAB934C59E6AD2D6AE8D662CBCFEFBE61E5A308D4211E58C4C25935B72C69107722E946BFCBF416796600542D76AEB73F2B25BF53BAF97BDEB36ED3A7A51C31E7F170EB897457E7C17571D1BA0A908954E9",
|
||||
"88C41F3EBEC23FAB8A362D969CAC810FAD4F7CA6A7F7D0D44F060F92E37E1183768DD4A8C733F71C96058D362A39876D183B86C103DE",
|
||||
"74A25B2182C51096D48A870D80F18E1CE15867778E34FCBA6BD7BFB3739FDCD42AD0F2D9F4EBA29085285C6048C15BCE5E5166F1F962D3337AA88E6062F05523029D0A7F0BF9"},
|
||||
{"BFB147E1CD5459424F8C0271FC0E0DC5",
|
||||
"EABCC126442BF373969EA3015988CC45",
|
||||
"4C0880E1D71AA2C7",
|
||||
"BE1B5EC78FBF73E7A6682B21BA7E0E5D2D1C7ABE",
|
||||
"5660D7C1380E2F306895B1402CB2D6C37876504276B414D120F4CF92FDDDBB293A238EA0"},
|
||||
{"595DD6F52D18BC2CA8EB4EDAA18D9FA3",
|
||||
"0F84B5D36CF4BC3B863313AF3B4D2E97",
|
||||
"30AE6CC5F99580F12A779D98BD379A60948020C0B6FBD5746B30BA3A15C6CD33DAF376C70A9F15B6C0EB410A93161F7958AE23",
|
||||
"8EF3687A1642B070970B0B91462229D1D76ABC154D18211F7152AA9FF368",
|
||||
"317C1DDB11417E5A9CC4DDE7FDFF6659A5AC4B31DE025212580A05CDAC6024D3E4AE7C2966E52B9129E9ECDBED86"},
|
||||
{"44E6F2DC8FDC778AD007137D11410F50",
|
||||
"270A237AD977F7187AA6C158A0BAB24F",
|
||||
"509B0F0EB12E2AA5C5BA2DE553C07FAF4CE0C9E926531AA709A3D6224FCB783ACCF1559E10B1123EBB7D52E8AB54E6B5352A9ED0D04124BF0E9D9BACFD7E32B817B2E625F5EE94A64EDE9E470DE7FE6886C19B294F9F828209FE257A78",
|
||||
"8B3D7815DF25618A5D0C55A601711881483878F113A12EC36CF64900549A3199555528559DC118F789788A55FAFD944E6E99A9CA3F72F238CD3F4D88223F7A745992B3FAED1848",
|
||||
"1CC00D79F7AD82FDA71B58D286E5F34D0CC4CEF30704E771CC1E50746BDF83E182B078DB27149A42BAE619DF0F85B0B1090AD55D3B4471B0D6F6ECCD09C8F876B30081F0E7537A9624F8AAF29DA85E324122EFB4D68A56"},
|
||||
{"BB7BC352A03044B4428D8DBB4B0701FDEC4649FD17B81452",
|
||||
"8B4BBE26CCD9859DCD84884159D6B0A4",
|
||||
"2212BEB0E78E0F044A86944CF33C8D5C80D9DBE1034BF3BCF73611835C7D3A52F5BD2D81B68FD681B68540A496EE5DA16FD8AC8824E60E1EC2042BE28FB0BFAD4E4B03596446BDD8C37D936D9B3D5295BE19F19CF5ACE1D33A46C952CE4DE5C12F92C1DD051E04AEED",
|
||||
"9037234CC44FFF828FABED3A7084AF40FA7ABFF8E0C0EFB57A1CC361E18FC4FAC1AB54F3ABFE9FF77263ACE16C3A",
|
||||
"A9391B805CCD956081E0B63D282BEA46E7025126F1C1631239C33E92AA6F92CD56E5A4C56F00FF9658E93D48AF4EF0EF81628E34AD4DB0CDAEDCD2A17EE7"},
|
||||
{"99C0AD703196D2F60A74E6B378B838B31F82EA861F06FC4E",
|
||||
"92745C018AA708ECFEB1667E9F3F1B01",
|
||||
"828C69F376C0C0EC651C67749C69577D589EE39E51404D80EBF70C8660A8F5FD375473F4A7C611D59CB546A605D67446CE2AA844135FCD78BB5FBC90222A00D42920BB1D7EEDFB0C4672554F583EF23184F89063CDECBE482367B5F9AF3ACBC3AF61392BD94CBCD9B64677",
|
||||
"A879214658FD0A5B0E09836639BF82E05EC7A5EF71D4701934BDA228435C68AC3D5CEB54997878B06A655EEACEFB1345C15867E7FE6C6423660C8B88DF128EBD6BCD85118DBAE16E9252FFB204324E5C8F38CA97759BDBF3CB0083",
|
||||
"51FE87996F194A2585E438B023B345439EA60D1AEBED4650CDAF48A4D4EEC4FC77DC71CC4B09D3BEEF8B7B7AF716CE2B4EFFB3AC9E6323C18AC35E0AA6E2BBBC8889490EB6226C896B0D105EAB42BFE7053CCF00ED66BA94C1BA09A792AA873F0C3B26C5C5F9A936E57B25"},
|
||||
{"7086816D00D648FB8304AA8C9E552E1B69A9955FB59B25D1",
|
||||
"0F45CF7F0BF31CCEB85D9DA10F4D749F",
|
||||
"93F27C60A417D9F0669E86ACC784FC8917B502DAF30A6338F11B30B94D74FEFE2F8BE1BBE2EAD10FAB7EED3C6F72B7C3ECEE1937C32ED4970A6404E139209C05",
|
||||
"877F046601F3CBE4FB1491943FA29487E738F94B99AF206262A1D6FF856C9AA0B8D4D08A54370C98F8E88FA3DCC2B14C1F76D71B2A4C7963AEE8AF960464C5BEC8357AD00DC8",
|
||||
"FE96906B895CE6A8E72BC72344E2C8BB3C63113D70EAFA26C299BAFE77A8A6568172EB447FB3E86648A0AF3512DEB1AAC0819F3EC553903BF28A9FB0F43411237A774BF9EE03E445D280FBB9CD12B9BAAB6EF5E52691"},
|
||||
{"062F65A896D5BF1401BADFF70E91B458E1F9BD4888CB2E4D",
|
||||
"5B11EA1D6008EBB41CF892FCA5B943D1",
|
||||
"BAF4FF5C8242",
|
||||
"A8870E091238355984EB2F7D61A865B9170F440BFF999A5993DD41A10F4440D21FF948DDA2BF663B2E03AC3324492DC5E40262ECC6A65C07672353BE23E7FB3A9D79FF6AA38D97960905A38DECC312CB6A59E5467ECF06C311CD43ADC0B543EDF34FE8BE611F176460D5627CA51F8F8D9FED71F55C",
|
||||
"B10E127A632172CF8AA7539B140D2C9C2590E6F28C3CB892FC498FCE56A34F732FBFF32E79C7B9747D9094E8635A0C084D6F0247F9768FB5FF83493799A9BEC6C39572120C40E9292C8C947AE8573462A9108C36D9D7112E6995AE5867E6C8BB387D1C5D4BEF524F391B9FD9F0A3B4BFA079E915BCD920185CFD38D114C558928BD7D47877"},
|
||||
{"38A8E45D6D705A11AF58AED5A1344896998EACF359F2E26A",
|
||||
"FD82B5B31804FF47D44199B533D0CF84",
|
||||
"DE454D4E62FE879F2050EE3E25853623D3E9AC52EEC1A1779A48CFAF5ECA0BFDE44749391866D1",
|
||||
"B804",
|
||||
"164BB965C05EBE0931A1A63293EDF9C38C27"},
|
||||
{"34C33C97C6D7A0850DA94D78A58DC61EC717CD7574833068",
|
||||
"343BE00DA9483F05C14F2E9EB8EA6AE8",
|
||||
"78312A43EFDE3CAE34A65796FF059A3FE15304EEA5CF1D9306949FE5BF3349D4977D4EBE76C040FE894C5949E4E4D6681153DA87FB9AC5062063CA2EA183566343362370944CE0362D25FC195E124FD60E8682E665D13F2229DDA3E4B2CB1DCA",
|
||||
"CC11BB284B1153578E4A5ED9D937B869DAF00F5B1960C23455CA9CC43F486A3BE0B66254F1041F04FDF459C8640465B6E1D2CF899A381451E8E7FCB50CF87823BE77E24B132BBEEDC72E53369B275E1D8F49ECE59F4F215230AC4FE133FC80E4F634EE80BA4682B62C86",
|
||||
"E7F703DC31A95E3A4919FF957836CB76C063D81702AEA4703E1C2BF30831E58C4609D626EC6810E12EAA5B930F049FF9EFC22C3E3F1EBD4A1FB285CB02A1AC5AD46B425199FC0A85670A5C4E3DAA9636C8F64C199F42F18AAC8EA7457FD377F322DD7752D7D01B946C8F0A97E6113F0D50106F319AFD291AAACE"},
|
||||
{"C6ECF7F053573E403E61B83052A343D93CBCC179D1E835BE",
|
||||
"E280E13D7367042E3AA09A80111B6184",
|
||||
"21486C9D7A9647",
|
||||
"5F2639AFA6F17931853791CD8C92382BBB677FD72D0AB1A080D0E49BFAA21810E963E4FACD422E92F65CBFAD5884A60CD94740DF31AF02F95AA57DA0C4401B0ED906",
|
||||
"5C51DB20755302070C45F52E50128A67C8B2E4ED0EACB7E29998CCE2E8C289DD5655913EC1A51CC3AABE5CDC2402B2BE7D6D4BF6945F266FBD70BA9F37109067157AE7530678B45F64475D4EBFCB5FFF46A5"},
|
||||
{"5EC6CF7401BC57B18EF154E8C38ACCA8959E57D2F3975FF5",
|
||||
"656B41CB3F9CF8C08BAD7EBFC80BD225",
|
||||
"6B817C2906E2AF425861A7EF59BA5801F143EE2A139EE72697CDE168B4",
|
||||
"2C0E1DDC9B1E5389BA63845B18B1F8A1DB062037151BCC56EF7C21C0BB4DAE366636BBA975685D7CC5A94AFBE89C769016388C56FB7B57CE750A12B718A8BDCF70E80E8659A8330EFC8F86640F21735E8C80E23FE43ABF23507CE3F964AE4EC99D",
|
||||
"ED780CF911E6D1AA8C979B889B0B9DC1ABE261832980BDBFB576901D9EF5AB8048998E31A15BE54B3E5845A4D136AD24D0BDA1C3006168DF2F8AC06729CB0818867398150020131D8F04EDF1923758C9EABB5F735DE5EA1758D4BC0ACFCA98AFD202E9839B8720253693B874C65586C6F0"},
|
||||
{"C92F678EB2208662F5BCF3403EC05F5961E957908A3E79421E1D25FC19054153",
|
||||
"DA0F3A40983D92F2D4C01FED33C7A192",
|
||||
"2B6E9D26DB406A0FAB47608657AA10EFC2B4AA5F459B29FF85AC9A40BFFE7AEB04F77E9A11FAAA116D7F6D4DA417671A9AB02C588E0EF59CB1BFB4B1CC931B63A3B3A159FCEC97A04D1E6F0C7E6A9CEF6B0ABB04758A69F1FE754DF4C2610E8C46B6CF413BDB31351D55BEDCB7B4A13A1C98E10984475E0F2F957853",
|
||||
"F37326A80E08",
|
||||
"83519E53E321D334F7C10B568183775C0E9AAE55F806"},
|
||||
{"6847E0491BE57E72995D186D50094B0B3593957A5146798FCE68B287B2FB37B5",
|
||||
"3EE1182AEBB19A02B128F28E1D5F7F99",
|
||||
"D9F35ABB16D776CE",
|
||||
"DB7566ED8EA95BDF837F23DB277BAFBC5E70D1105ADFD0D9EF15475051B1EF94709C67DCA9F8D5",
|
||||
"2CDCED0C9EBD6E2A508822A685F7DCD1CDD99E7A5FCA786C234E7F7F1D27EC49751AD5DCFA30C5EDA87C43CAE3B919B6BBCFE34C8EDA59"},
|
||||
{"82B019673642C08388D3E42075A4D5D587558C229E4AB8F660E37650C4C41A0A",
|
||||
"336F5D681E0410FAE7B607246092C6DC",
|
||||
"D430CBD8FE435B64214E9E9CDC5DE99D31CFCFB8C10AA0587A49DF276611",
|
||||
"998404153AD77003E1737EDE93ED79859EE6DCCA93CB40C4363AA817ABF2DBBD46E42A14A7183B6CC01E12A577888141363D0AE011EB6E8D28C0B235",
|
||||
"9BEF69EEB60BD3D6065707B7557F25292A8872857CFBD24F2F3C088E4450995333088DA50FD9121221C504DF1D0CD5EFE6A12666C5D5BB12282CF4C19906E9CFAB97E9BDF7F49DC17CFC384B"},
|
||||
{"747B2E269B1859F0622C15C8BAD6A725028B1F94B8DB7326948D1E6ED663A8BC",
|
||||
"AB91F7245DDCE3F1C747872D47BE0A8A",
|
||||
"3B03F786EF1DDD76E1D42646DA4CD2A5165DC5383CE86D1A0B5F13F910DC278A4E451EE0192CBA178E13B3BA27FDC7840DF73D2E104B",
|
||||
"6B803F4701114F3E5FE21718845F8416F70F626303F545BE197189E0A2BA396F37CE06D389EB2658BC7D56D67868708F6D0D32",
|
||||
"1570DDB0BCE75AA25D1957A287A2C36B1A5F2270186DA81BA6112B7F43B0F3D1D0ED072591DCF1F1C99BBB25621FC39B896FF9BD9413A2845363A9DCD310C32CF98E57"},
|
||||
{"02E59853FB29AEDA0FE1C5F19180AD99A12FF2F144670BB2B8BADF09AD812E0A",
|
||||
"C691294EF67CD04D1B9242AF83DD1421",
|
||||
"879334DAE3",
|
||||
"1E17F46A98FEF5CBB40759D95354",
|
||||
"FED8C3FF27DDF6313AED444A2985B36CBA268AAD6AAC563C0BA28F6DB5DB"},
|
||||
{"F6C1FB9B4188F2288FF03BD716023198C3582CF2A037FC2F29760916C2B7FCDB",
|
||||
"4228DA0678CA3534588859E77DFF014C",
|
||||
"D8153CAF35539A61DD8D05B3C9B44F01E564FB9348BCD09A1C23B84195171308861058F0A3CD2A55B912A3AAEE06FF4D356C77275828F2157C2FC7C115DA39E443210CCC56BEDB0CC99BBFB227ABD5CC454F4E7F547C7378A659EEB6A7E809101A84F866503CB18D4484E1FA09B3EC7FC75EB2E35270800AA7",
|
||||
"23B660A779AD285704B12EC1C580387A47BEC7B00D452C6570",
|
||||
"5AA642BBABA8E49849002A2FAF31DB8FC7773EFDD656E469CEC19B3206D4174C9A263D0A05484261F6"},
|
||||
{"8FF6086F1FADB9A3FBE245EAC52640C43B39D43F89526BB5A6EBA47710931446",
|
||||
"943188480C99437495958B0AE4831AA9",
|
||||
"AD5CD0BDA426F6EBA23C8EB23DC73FF9FEC173355EDBD6C9344C4C4383F211888F7CE6B29899A6801DF6B38651A7C77150941A",
|
||||
"80CD5EA8D7F81DDF5070B934937912E8F541A5301877528EB41AB60C020968D459960ED8FB73083329841A",
|
||||
"ABAE8EB7F36FCA2362551E72DAC890BA1BB6794797E0FC3B67426EC9372726ED4725D379EA0AC9147E48DCD0005C502863C2C5358A38817C8264B5"},
|
||||
{"A083B54E6B1FE01B65D42FCD248F97BB477A41462BBFE6FD591006C022C8FD84",
|
||||
"B0490F5BD68A52459556B3749ACDF40E",
|
||||
"8892E047DA5CFBBDF7F3CFCBD1BD21C6D4C80774B1826999234394BD3E513CC7C222BB40E1E3140A152F19B3802F0D036C24A590512AD0E8",
|
||||
"D7B15752789DC94ED0F36778A5C7BBB207BEC32BAC66E702B39966F06E381E090C6757653C3D26A81EC6AD6C364D66867A334C91BB0B8A8A4B6EACDF0783D09010AEBA2DD2062308FE99CC1F",
|
||||
"C071280A732ADC93DF272BF1E613B2BB7D46FC6665EF2DC1671F3E211D6BDE1D6ADDD28DF3AA2E47053FC8BB8AE9271EC8BC8B2CFFA320D225B451685B6D23ACEFDD241FE284F8ADC8DB07F456985B14330BBB66E0FB212213E05B3E"},
|
||||
}
|
92
vendor/github.com/ProtonMail/go-crypto/internal/byteutil/byteutil.go
generated
vendored
Normal file
92
vendor/github.com/ProtonMail/go-crypto/internal/byteutil/byteutil.go
generated
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
// Copyright (C) 2019 ProtonTech AG
|
||||
// This file contains necessary tools for the aex and ocb packages.
|
||||
//
|
||||
// These functions SHOULD NOT be used elsewhere, since they are optimized for
|
||||
// specific input nature in the EAX and OCB modes of operation.
|
||||
|
||||
package byteutil
|
||||
|
||||
// GfnDouble computes 2 * input in the field of 2^n elements.
|
||||
// The irreducible polynomial in the finite field for n=128 is
|
||||
// x^128 + x^7 + x^2 + x + 1 (equals 0x87)
|
||||
// Constant-time execution in order to avoid side-channel attacks
|
||||
func GfnDouble(input []byte) []byte {
|
||||
if len(input) != 16 {
|
||||
panic("Doubling in GFn only implemented for n = 128")
|
||||
}
|
||||
// If the first bit is zero, return 2L = L << 1
|
||||
// Else return (L << 1) xor 0^120 10000111
|
||||
shifted := ShiftBytesLeft(input)
|
||||
shifted[15] ^= ((input[0] >> 7) * 0x87)
|
||||
return shifted
|
||||
}
|
||||
|
||||
// ShiftBytesLeft outputs the byte array corresponding to x << 1 in binary.
|
||||
func ShiftBytesLeft(x []byte) []byte {
|
||||
l := len(x)
|
||||
dst := make([]byte, l)
|
||||
for i := 0; i < l-1; i++ {
|
||||
dst[i] = (x[i] << 1) | (x[i+1] >> 7)
|
||||
}
|
||||
dst[l-1] = x[l-1] << 1
|
||||
return dst
|
||||
}
|
||||
|
||||
// ShiftNBytesLeft puts in dst the byte array corresponding to x << n in binary.
|
||||
func ShiftNBytesLeft(dst, x []byte, n int) {
|
||||
// Erase first n / 8 bytes
|
||||
copy(dst, x[n/8:])
|
||||
|
||||
// Shift the remaining n % 8 bits
|
||||
bits := uint(n % 8)
|
||||
l := len(dst)
|
||||
for i := 0; i < l-1; i++ {
|
||||
dst[i] = (dst[i] << bits) | (dst[i+1] >> uint(8 - bits))
|
||||
}
|
||||
dst[l-1] = dst[l-1] << bits
|
||||
|
||||
// Append trailing zeroes
|
||||
dst = append(dst, make([]byte, n/8)...)
|
||||
}
|
||||
|
||||
// XorBytesMut assumes equal input length, replaces X with X XOR Y
|
||||
func XorBytesMut(X, Y []byte) {
|
||||
for i := 0; i < len(X); i++ {
|
||||
X[i] ^= Y[i]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// XorBytes assumes equal input length, puts X XOR Y into Z
|
||||
func XorBytes(Z, X, Y []byte) {
|
||||
for i := 0; i < len(X); i++ {
|
||||
Z[i] = X[i] ^ Y[i]
|
||||
}
|
||||
}
|
||||
|
||||
// RightXor XORs smaller input (assumed Y) at the right of the larger input (assumed X)
|
||||
func RightXor(X, Y []byte) []byte {
|
||||
offset := len(X) - len(Y)
|
||||
xored := make([]byte, len(X));
|
||||
copy(xored, X)
|
||||
for i := 0; i < len(Y); i++ {
|
||||
xored[offset + i] ^= Y[i]
|
||||
}
|
||||
return xored
|
||||
}
|
||||
|
||||
// SliceForAppend takes a slice and a requested number of bytes. It returns a
|
||||
// slice with the contents of the given slice followed by that many bytes and a
|
||||
// second slice that aliases into it and contains only the extra bytes. If the
|
||||
// original slice has sufficient capacity then no allocation is performed.
|
||||
func SliceForAppend(in []byte, n int) (head, tail []byte) {
|
||||
if total := len(in) + n; cap(in) >= total {
|
||||
head = in[:total]
|
||||
} else {
|
||||
head = make([]byte, total)
|
||||
copy(head, in)
|
||||
}
|
||||
tail = head[len(in):]
|
||||
return
|
||||
}
|
||||
|
317
vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go
generated
vendored
Normal file
317
vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go
generated
vendored
Normal file
|
@ -0,0 +1,317 @@
|
|||
// Copyright (C) 2019 ProtonTech AG
|
||||
|
||||
// Package ocb provides an implementation of the OCB (offset codebook) mode of
|
||||
// operation, as described in RFC-7253 of the IRTF and in Rogaway, Bellare,
|
||||
// Black and Krovetz - OCB: A BLOCK-CIPHER MODE OF OPERATION FOR EFFICIENT
|
||||
// AUTHENTICATED ENCRYPTION (2003).
|
||||
// Security considerations (from RFC-7253): A private key MUST NOT be used to
|
||||
// encrypt more than 2^48 blocks. Tag length should be at least 12 bytes (a
|
||||
// brute-force forging adversary succeeds after 2^{tag length} attempts). A
|
||||
// single key SHOULD NOT be used to decrypt ciphertext with different tag
|
||||
// lengths. Nonces need not be secret, but MUST NOT be reused.
|
||||
// This package only supports underlying block ciphers with 128-bit blocks,
|
||||
// such as AES-{128, 192, 256}, but may be extended to other sizes.
|
||||
package ocb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/cipher"
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
"github.com/ProtonMail/go-crypto/internal/byteutil"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
type ocb struct {
|
||||
block cipher.Block
|
||||
tagSize int
|
||||
nonceSize int
|
||||
mask mask
|
||||
// Optimized en/decrypt: For each nonce N used to en/decrypt, the 'Ktop'
|
||||
// internal variable can be reused for en/decrypting with nonces sharing
|
||||
// all but the last 6 bits with N. The prefix of the first nonce used to
|
||||
// compute the new Ktop, and the Ktop value itself, are stored in
|
||||
// reusableKtop. If using incremental nonces, this saves one block cipher
|
||||
// call every 63 out of 64 OCB encryptions, and stores one nonce and one
|
||||
// output of the block cipher in memory only.
|
||||
reusableKtop reusableKtop
|
||||
}
|
||||
|
||||
type mask struct {
|
||||
// L_*, L_$, (L_i)_{i ∈ N}
|
||||
lAst []byte
|
||||
lDol []byte
|
||||
L [][]byte
|
||||
}
|
||||
|
||||
type reusableKtop struct {
|
||||
noncePrefix []byte
|
||||
Ktop []byte
|
||||
}
|
||||
|
||||
const (
|
||||
defaultTagSize = 16
|
||||
defaultNonceSize = 15
|
||||
)
|
||||
|
||||
const (
|
||||
enc = iota
|
||||
dec
|
||||
)
|
||||
|
||||
func (o *ocb) NonceSize() int {
|
||||
return o.nonceSize
|
||||
}
|
||||
|
||||
func (o *ocb) Overhead() int {
|
||||
return o.tagSize
|
||||
}
|
||||
|
||||
// NewOCB returns an OCB instance with the given block cipher and default
|
||||
// tag and nonce sizes.
|
||||
func NewOCB(block cipher.Block) (cipher.AEAD, error) {
|
||||
return NewOCBWithNonceAndTagSize(block, defaultNonceSize, defaultTagSize)
|
||||
}
|
||||
|
||||
// NewOCBWithNonceAndTagSize returns an OCB instance with the given block
|
||||
// cipher, nonce length, and tag length. Panics on zero nonceSize and
|
||||
// exceedingly long tag size.
|
||||
//
|
||||
// It is recommended to use at least 12 bytes as tag length.
|
||||
func NewOCBWithNonceAndTagSize(
|
||||
block cipher.Block, nonceSize, tagSize int) (cipher.AEAD, error) {
|
||||
if block.BlockSize() != 16 {
|
||||
return nil, ocbError("Block cipher must have 128-bit blocks")
|
||||
}
|
||||
if nonceSize < 1 {
|
||||
return nil, ocbError("Incorrect nonce length")
|
||||
}
|
||||
if nonceSize >= block.BlockSize() {
|
||||
return nil, ocbError("Nonce length exceeds blocksize - 1")
|
||||
}
|
||||
if tagSize > block.BlockSize() {
|
||||
return nil, ocbError("Custom tag length exceeds blocksize")
|
||||
}
|
||||
return &ocb{
|
||||
block: block,
|
||||
tagSize: tagSize,
|
||||
nonceSize: nonceSize,
|
||||
mask: initializeMaskTable(block),
|
||||
reusableKtop: reusableKtop{
|
||||
noncePrefix: nil,
|
||||
Ktop: nil,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (o *ocb) Seal(dst, nonce, plaintext, adata []byte) []byte {
|
||||
if len(nonce) > o.nonceSize {
|
||||
panic("crypto/ocb: Incorrect nonce length given to OCB")
|
||||
}
|
||||
ret, out := byteutil.SliceForAppend(dst, len(plaintext)+o.tagSize)
|
||||
o.crypt(enc, out, nonce, adata, plaintext)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (o *ocb) Open(dst, nonce, ciphertext, adata []byte) ([]byte, error) {
|
||||
if len(nonce) > o.nonceSize {
|
||||
panic("Nonce too long for this instance")
|
||||
}
|
||||
if len(ciphertext) < o.tagSize {
|
||||
return nil, ocbError("Ciphertext shorter than tag length")
|
||||
}
|
||||
sep := len(ciphertext) - o.tagSize
|
||||
ret, out := byteutil.SliceForAppend(dst, len(ciphertext))
|
||||
ciphertextData := ciphertext[:sep]
|
||||
tag := ciphertext[sep:]
|
||||
o.crypt(dec, out, nonce, adata, ciphertextData)
|
||||
if subtle.ConstantTimeCompare(ret[sep:], tag) == 1 {
|
||||
ret = ret[:sep]
|
||||
return ret, nil
|
||||
}
|
||||
for i := range out {
|
||||
out[i] = 0
|
||||
}
|
||||
return nil, ocbError("Tag authentication failed")
|
||||
}
|
||||
|
||||
// On instruction enc (resp. dec), crypt is the encrypt (resp. decrypt)
|
||||
// function. It returns the resulting plain/ciphertext with the tag appended.
|
||||
func (o *ocb) crypt(instruction int, Y, nonce, adata, X []byte) []byte {
|
||||
//
|
||||
// Consider X as a sequence of 128-bit blocks
|
||||
//
|
||||
// Note: For encryption (resp. decryption), X is the plaintext (resp., the
|
||||
// ciphertext without the tag).
|
||||
blockSize := o.block.BlockSize()
|
||||
|
||||
//
|
||||
// Nonce-dependent and per-encryption variables
|
||||
//
|
||||
// Zero out the last 6 bits of the nonce into truncatedNonce to see if Ktop
|
||||
// is already computed.
|
||||
truncatedNonce := make([]byte, len(nonce))
|
||||
copy(truncatedNonce, nonce)
|
||||
truncatedNonce[len(truncatedNonce)-1] &= 192
|
||||
Ktop := make([]byte, blockSize)
|
||||
if bytes.Equal(truncatedNonce, o.reusableKtop.noncePrefix) {
|
||||
Ktop = o.reusableKtop.Ktop
|
||||
} else {
|
||||
// Nonce = num2str(TAGLEN mod 128, 7) || zeros(120 - bitlen(N)) || 1 || N
|
||||
paddedNonce := append(make([]byte, blockSize-1-len(nonce)), 1)
|
||||
paddedNonce = append(paddedNonce, truncatedNonce...)
|
||||
paddedNonce[0] |= byte(((8 * o.tagSize) % (8 * blockSize)) << 1)
|
||||
// Last 6 bits of paddedNonce are already zero. Encrypt into Ktop
|
||||
paddedNonce[blockSize-1] &= 192
|
||||
Ktop = paddedNonce
|
||||
o.block.Encrypt(Ktop, Ktop)
|
||||
o.reusableKtop.noncePrefix = truncatedNonce
|
||||
o.reusableKtop.Ktop = Ktop
|
||||
}
|
||||
|
||||
// Stretch = Ktop || ((lower half of Ktop) XOR (lower half of Ktop << 8))
|
||||
xorHalves := make([]byte, blockSize/2)
|
||||
byteutil.XorBytes(xorHalves, Ktop[:blockSize/2], Ktop[1:1+blockSize/2])
|
||||
stretch := append(Ktop, xorHalves...)
|
||||
bottom := int(nonce[len(nonce)-1] & 63)
|
||||
offset := make([]byte, len(stretch))
|
||||
byteutil.ShiftNBytesLeft(offset, stretch, bottom)
|
||||
offset = offset[:blockSize]
|
||||
|
||||
//
|
||||
// Process any whole blocks
|
||||
//
|
||||
// Note: For encryption Y is ciphertext || tag, for decryption Y is
|
||||
// plaintext || tag.
|
||||
checksum := make([]byte, blockSize)
|
||||
m := len(X) / blockSize
|
||||
for i := 0; i < m; i++ {
|
||||
index := bits.TrailingZeros(uint(i + 1))
|
||||
if len(o.mask.L)-1 < index {
|
||||
o.mask.extendTable(index)
|
||||
}
|
||||
byteutil.XorBytesMut(offset, o.mask.L[bits.TrailingZeros(uint(i+1))])
|
||||
blockX := X[i*blockSize : (i+1)*blockSize]
|
||||
blockY := Y[i*blockSize : (i+1)*blockSize]
|
||||
byteutil.XorBytes(blockY, blockX, offset)
|
||||
switch instruction {
|
||||
case enc:
|
||||
o.block.Encrypt(blockY, blockY)
|
||||
byteutil.XorBytesMut(blockY, offset)
|
||||
byteutil.XorBytesMut(checksum, blockX)
|
||||
case dec:
|
||||
o.block.Decrypt(blockY, blockY)
|
||||
byteutil.XorBytesMut(blockY, offset)
|
||||
byteutil.XorBytesMut(checksum, blockY)
|
||||
}
|
||||
}
|
||||
//
|
||||
// Process any final partial block and compute raw tag
|
||||
//
|
||||
tag := make([]byte, blockSize)
|
||||
if len(X)%blockSize != 0 {
|
||||
byteutil.XorBytesMut(offset, o.mask.lAst)
|
||||
pad := make([]byte, blockSize)
|
||||
o.block.Encrypt(pad, offset)
|
||||
chunkX := X[blockSize*m:]
|
||||
chunkY := Y[blockSize*m : len(X)]
|
||||
byteutil.XorBytes(chunkY, chunkX, pad[:len(chunkX)])
|
||||
// P_* || bit(1) || zeroes(127) - len(P_*)
|
||||
switch instruction {
|
||||
case enc:
|
||||
paddedY := append(chunkX, byte(128))
|
||||
paddedY = append(paddedY, make([]byte, blockSize-len(chunkX)-1)...)
|
||||
byteutil.XorBytesMut(checksum, paddedY)
|
||||
case dec:
|
||||
paddedX := append(chunkY, byte(128))
|
||||
paddedX = append(paddedX, make([]byte, blockSize-len(chunkY)-1)...)
|
||||
byteutil.XorBytesMut(checksum, paddedX)
|
||||
}
|
||||
byteutil.XorBytes(tag, checksum, offset)
|
||||
byteutil.XorBytesMut(tag, o.mask.lDol)
|
||||
o.block.Encrypt(tag, tag)
|
||||
byteutil.XorBytesMut(tag, o.hash(adata))
|
||||
copy(Y[blockSize*m+len(chunkY):], tag[:o.tagSize])
|
||||
} else {
|
||||
byteutil.XorBytes(tag, checksum, offset)
|
||||
byteutil.XorBytesMut(tag, o.mask.lDol)
|
||||
o.block.Encrypt(tag, tag)
|
||||
byteutil.XorBytesMut(tag, o.hash(adata))
|
||||
copy(Y[blockSize*m:], tag[:o.tagSize])
|
||||
}
|
||||
return Y
|
||||
}
|
||||
|
||||
// This hash function is used to compute the tag. Per design, on empty input it
|
||||
// returns a slice of zeros, of the same length as the underlying block cipher
|
||||
// block size.
|
||||
func (o *ocb) hash(adata []byte) []byte {
|
||||
//
|
||||
// Consider A as a sequence of 128-bit blocks
|
||||
//
|
||||
A := make([]byte, len(adata))
|
||||
copy(A, adata)
|
||||
blockSize := o.block.BlockSize()
|
||||
|
||||
//
|
||||
// Process any whole blocks
|
||||
//
|
||||
sum := make([]byte, blockSize)
|
||||
offset := make([]byte, blockSize)
|
||||
m := len(A) / blockSize
|
||||
for i := 0; i < m; i++ {
|
||||
chunk := A[blockSize*i : blockSize*(i+1)]
|
||||
index := bits.TrailingZeros(uint(i + 1))
|
||||
// If the mask table is too short
|
||||
if len(o.mask.L)-1 < index {
|
||||
o.mask.extendTable(index)
|
||||
}
|
||||
byteutil.XorBytesMut(offset, o.mask.L[index])
|
||||
byteutil.XorBytesMut(chunk, offset)
|
||||
o.block.Encrypt(chunk, chunk)
|
||||
byteutil.XorBytesMut(sum, chunk)
|
||||
}
|
||||
|
||||
//
|
||||
// Process any final partial block; compute final hash value
|
||||
//
|
||||
if len(A)%blockSize != 0 {
|
||||
byteutil.XorBytesMut(offset, o.mask.lAst)
|
||||
// Pad block with 1 || 0 ^ 127 - bitlength(a)
|
||||
ending := make([]byte, blockSize-len(A)%blockSize)
|
||||
ending[0] = 0x80
|
||||
encrypted := append(A[blockSize*m:], ending...)
|
||||
byteutil.XorBytesMut(encrypted, offset)
|
||||
o.block.Encrypt(encrypted, encrypted)
|
||||
byteutil.XorBytesMut(sum, encrypted)
|
||||
}
|
||||
return sum
|
||||
}
|
||||
|
||||
func initializeMaskTable(block cipher.Block) mask {
|
||||
//
|
||||
// Key-dependent variables
|
||||
//
|
||||
lAst := make([]byte, block.BlockSize())
|
||||
block.Encrypt(lAst, lAst)
|
||||
lDol := byteutil.GfnDouble(lAst)
|
||||
L := make([][]byte, 1)
|
||||
L[0] = byteutil.GfnDouble(lDol)
|
||||
|
||||
return mask{
|
||||
lAst: lAst,
|
||||
lDol: lDol,
|
||||
L: L,
|
||||
}
|
||||
}
|
||||
|
||||
// Extends the L array of mask m up to L[limit], with L[i] = GfnDouble(L[i-1])
|
||||
func (m *mask) extendTable(limit int) {
|
||||
for i := len(m.L); i <= limit; i++ {
|
||||
m.L = append(m.L, byteutil.GfnDouble(m.L[i-1]))
|
||||
}
|
||||
}
|
||||
|
||||
func ocbError(err string) error {
|
||||
return errors.New("crypto/ocb: " + err)
|
||||
}
|
136
vendor/github.com/ProtonMail/go-crypto/ocb/random_vectors.go
generated
vendored
Normal file
136
vendor/github.com/ProtonMail/go-crypto/ocb/random_vectors.go
generated
vendored
Normal file
|
@ -0,0 +1,136 @@
|
|||
// In the test vectors provided by RFC 7253, the "bottom"
|
||||
// internal variable, which defines "offset" for the first time, does not
|
||||
// exceed 15. However, it can attain values up to 63.
|
||||
|
||||
// These vectors include key length in {128, 192, 256}, tag size 128, and
|
||||
// random nonce, header, and plaintext lengths.
|
||||
|
||||
// This file was automatically generated.
|
||||
|
||||
package ocb
|
||||
|
||||
var randomVectors = []struct {
|
||||
key, nonce, header, plaintext, ciphertext string
|
||||
}{
|
||||
|
||||
{"9438C5D599308EAF13F800D2D31EA7F0",
|
||||
"C38EE4801BEBFFA1CD8635BE",
|
||||
"0E507B7DADD8A98CDFE272D3CB6B3E8332B56AE583FB049C0874D4200BED16BD1A044182434E9DA0E841F182DFD5B3016B34641CED0784F1745F63AB3D0DA22D3351C9EF9A658B8081E24498EBF61FCE40DA6D8E184536",
|
||||
"962D227786FB8913A8BAD5DC3250",
|
||||
"EEDEF5FFA5986D1E3BF86DDD33EF9ADC79DCA06E215FA772CCBA814F63AD"},
|
||||
{"BA7DE631C7D6712167C6724F5B9A2B1D",
|
||||
"35263EBDA05765DC0E71F1F5",
|
||||
"0103257B4224507C0242FEFE821EA7FA42E0A82863E5F8B68F7D881B4B44FA428A2B6B21D2F591260802D8AB6D83",
|
||||
"9D6D1FC93AE8A64E7889B7B2E3521EFA9B920A8DDB692E6F833DDC4A38AFA535E5E2A3ED82CB7E26404AB86C54D01C4668F28398C2DF33D5D561CBA1C8DCFA7A912F5048E545B59483C0E3221F54B14DAA2E4EB657B3BEF9554F34CAD69B2724AE962D3D8A",
|
||||
"E93852D1985C5E775655E937FA79CE5BF28A585F2AF53A5018853B9634BE3C84499AC0081918FDCE0624494D60E25F76ACD6853AC7576E3C350F332249BFCABD4E73CEABC36BE4EDDA40914E598AE74174A0D7442149B26990899491BDDFE8FC54D6C18E83AE9E9A6FFBF5D376565633862EEAD88D"},
|
||||
{"2E74B25289F6FD3E578C24866E9C72A5",
|
||||
"FD912F15025AF8414642BA1D1D",
|
||||
"FB5FB8C26F365EEDAB5FE260C6E3CCD27806729C8335F146063A7F9EA93290E56CF84576EB446350D22AD730547C267B1F0BBB97EB34E1E2C41A",
|
||||
"6C092EBF78F76EE8C1C6E592277D9545BA16EDB67BC7D8480B9827702DC2F8A129E2B08A2CE710CA7E1DA45CE162BB6CD4B512E632116E2211D3C90871EFB06B8D4B902681C7FB",
|
||||
"6AC0A77F26531BF4F354A1737F99E49BE32ECD909A7A71AD69352906F54B08A9CE9B8CA5D724CBFFC5673437F23F630697F3B84117A1431D6FA8CC13A974FB4AD360300522E09511B99E71065D5AC4BBCB1D791E864EF4"},
|
||||
{"E7EC507C802528F790AFF5303A017B17",
|
||||
"4B97A7A568940A9E3CE7A99E93031E",
|
||||
"28349BDC5A09390C480F9B8AA3EDEA3DDB8B9D64BCA322C570B8225DF0E31190DAB25A4014BA39519E02ABFB12B89AA28BBFD29E486E7FB28734258C817B63CED9912DBAFEBB93E2798AB2890DE3B0ACFCFF906AB15563EF7823CE83D27CDB251195E22BD1337BCBDE65E7C2C427321C463C2777BFE5AEAA",
|
||||
"9455B3EA706B74",
|
||||
"7F33BA3EA848D48A96B9530E26888F43EBD4463C9399B6"},
|
||||
{"6C928AA3224736F28EE7378DE0090191",
|
||||
"8936138E2E4C6A13280017A1622D",
|
||||
"6202717F2631565BDCDC57C6584543E72A7C8BD444D0D108ED35069819633C",
|
||||
"DA0691439E5F035F3E455269D14FE5C201C8C9B0A3FE2D3F86BCC59387C868FE65733D388360B31E3CE28B4BF6A8BE636706B536D5720DB66B47CF1C7A5AFD6F61E0EF90F1726D6B0E169F9A768B2B7AE4EE00A17F630AC905FCAAA1B707FFF25B3A1AAE83B504837C64A5639B2A34002B300EC035C9B43654DA55",
|
||||
"B8804D182AB0F0EEB464FA7BD1329AD6154F982013F3765FEDFE09E26DAC078C9C1439BFC1159D6C02A25E3FF83EF852570117B315852AD5EE20E0FA3AA0A626B0E43BC0CEA38B44579DD36803455FB46989B90E6D229F513FD727AF8372517E9488384C515D6067704119C931299A0982EDDFB9C2E86A90C450C077EB222511EC9CCABC9FCFDB19F70088"},
|
||||
{"ECEA315CA4B3F425B0C9957A17805EA4",
|
||||
"664CDAE18403F4F9BA13015A44FC",
|
||||
"642AFB090D6C6DB46783F08B01A3EF2A8FEB5736B531EAC226E7888FCC8505F396818F83105065FACB3267485B9E5E4A0261F621041C08FCCB2A809A49AB5252A91D0971BCC620B9D614BD77E57A0EED2FA5",
|
||||
"6852C31F8083E20E364CEA21BB7854D67CEE812FE1C9ED2425C0932A90D3780728D1BB",
|
||||
"2ECEF962A9695A463ADABB275BDA9FF8B2BA57AEC2F52EFFB700CD9271A74D2A011C24AEA946051BD6291776429B7E681BA33E"},
|
||||
{"4EE616C4A58AAA380878F71A373461F6",
|
||||
"91B8C9C176D9C385E9C47E52",
|
||||
"CDA440B7F9762C572A718AC754EDEECC119E5EE0CCB9FEA4FFB22EEE75087C032EBF3DA9CDD8A28CC010B99ED45143B41A4BA50EA2A005473F89639237838867A57F23B0F0ED3BF22490E4501DAC9C658A9B9F",
|
||||
"D6E645FA9AE410D15B8123FD757FA356A8DBE9258DDB5BE88832E615910993F497EC",
|
||||
"B70ED7BF959FB2AAED4F36174A2A99BFB16992C8CDF369C782C4DB9C73DE78C5DB8E0615F647243B97ACDB24503BC9CADC48"},
|
||||
{"DCD475773136C830D5E3D0C5FE05B7FF",
|
||||
"BB8E1FBB483BE7616A922C4A",
|
||||
"36FEF2E1CB29E76A6EA663FC3AF66ECD7404F466382F7B040AABED62293302B56E8783EF7EBC21B4A16C3E78A7483A0A403F253A2CDC5BBF79DC3DAE6C73F39A961D8FBBE8D41B",
|
||||
"441E886EA38322B2437ECA7DEB5282518865A66780A454E510878E61BFEC3106A3CD93D2A02052E6F9E1832F9791053E3B76BF4C07EFDD6D4106E3027FABB752E60C1AA425416A87D53938163817A1051EBA1D1DEEB4B9B25C7E97368B52E5911A31810B0EC5AF547559B6142D9F4C4A6EF24A4CF75271BF9D48F62B",
|
||||
"1BE4DD2F4E25A6512C2CC71D24BBB07368589A94C2714962CD0ACE5605688F06342587521E75F0ACAFFD86212FB5C34327D238DB36CF2B787794B9A4412E7CD1410EA5DDD2450C265F29CF96013CD213FD2880657694D718558964BC189B4A84AFCF47EB012935483052399DBA5B088B0A0477F20DFE0E85DCB735E21F22A439FB837DD365A93116D063E607"},
|
||||
{"3FBA2B3D30177FFE15C1C59ED2148BB2C091F5615FBA7C07",
|
||||
"FACF804A4BEBF998505FF9DE",
|
||||
"8213B9263B2971A5BDA18DBD02208EE1",
|
||||
"15B323926993B326EA19F892D704439FC478828322AF72118748284A1FD8A6D814E641F70512FD706980337379F31DC63355974738D7FEA87AD2858C0C2EBBFBE74371C21450072373C7B651B334D7C4D43260B9D7CCD3AF9EDB",
|
||||
"6D35DC1469B26E6AAB26272A41B46916397C24C485B61162E640A062D9275BC33DDCFD3D9E1A53B6C8F51AC89B66A41D59B3574197A40D9B6DCF8A4E2A001409C8112F16B9C389E0096179DB914E05D6D11ED0005AD17E1CE105A2F0BAB8F6B1540DEB968B7A5428FF44"},
|
||||
{"53B52B8D4D748BCDF1DDE68857832FA46227FA6E2F32EFA1",
|
||||
"0B0EF53D4606B28D1398355F",
|
||||
"F23882436349094AF98BCACA8218E81581A043B19009E28EFBF2DE37883E04864148CC01D240552CA8844EC1456F42034653067DA67E80F87105FD06E14FF771246C9612867BE4D215F6D761",
|
||||
"F15030679BD4088D42CAC9BF2E9606EAD4798782FA3ED8C57EBE7F84A53236F51B25967C6489D0CD20C9EEA752F9BC",
|
||||
"67B96E2D67C3729C96DAEAEDF821D61C17E648643A2134C5621FEC621186915AD80864BFD1EB5B238BF526A679385E012A457F583AFA78134242E9D9C1B4E4"},
|
||||
{"0272DD80F23399F49BFC320381A5CD8225867245A49A7D41",
|
||||
"5C83F4896D0738E1366B1836",
|
||||
"69B0337289B19F73A12BAEEA857CCAF396C11113715D9500CCCF48BA08CFF12BC8B4BADB3084E63B85719DB5058FA7C2C11DEB096D7943CFA7CAF5",
|
||||
"C01AD10FC8B562CD17C7BC2FAB3E26CBDFF8D7F4DEA816794BBCC12336991712972F52816AABAB244EB43B0137E2BAC1DD413CE79531E78BEF782E6B439612BB3AEF154DE3502784F287958EBC159419F9EBA27916A28D6307324129F506B1DE80C1755A929F87",
|
||||
"FEFE52DD7159C8DD6E8EC2D3D3C0F37AB6CB471A75A071D17EC4ACDD8F3AA4D7D4F7BB559F3C09099E3D9003E5E8AA1F556B79CECDE66F85B08FA5955E6976BF2695EA076388A62D2AD5BAB7CBF1A7F3F4C8D5CDF37CDE99BD3E30B685D9E5EEE48C7C89118EF4878EB89747F28271FA2CC45F8E9E7601"},
|
||||
{"3EEAED04A455D6E5E5AB53CFD5AFD2F2BC625C7BF4BE49A5",
|
||||
"36B88F63ADBB5668588181D774",
|
||||
"D367E3CB3703E762D23C6533188EF7028EFF9D935A3977150361997EC9DEAF1E4794BDE26AA8B53C124980B1362EC86FCDDFC7A90073171C1BAEE351A53234B86C66E8AB92FAE99EC6967A6D3428892D80",
|
||||
"573454C719A9A55E04437BF7CBAAF27563CCCD92ADD5E515CD63305DFF0687E5EEF790C5DCA5C0033E9AB129505E2775438D92B38F08F3B0356BA142C6F694",
|
||||
"E9F79A5B432D9E682C9AAA5661CFC2E49A0FCB81A431E54B42EB73DD3BED3F377FEC556ABA81624BA64A5D739AD41467460088F8D4F442180A9382CA635745473794C382FCDDC49BA4EB6D8A44AE3C"},
|
||||
{"B695C691538F8CBD60F039D0E28894E3693CC7C36D92D79D",
|
||||
"BC099AEB637361BAC536B57618",
|
||||
"BFFF1A65AE38D1DC142C71637319F5F6508E2CB33C9DCB94202B359ED5A5ED8042E7F4F09231D32A7242976677E6F4C549BF65FADC99E5AF43F7A46FD95E16C2",
|
||||
"081DF3FD85B415D803F0BE5AC58CFF0023FDDED99788296C3731D8",
|
||||
"E50C64E3614D94FE69C47092E46ACC9957C6FEA2CCBF96BC62FBABE7424753C75F9C147C42AE26FE171531"},
|
||||
{"C9ACBD2718F0689A1BE9802A551B6B8D9CF5614DAF5E65ED",
|
||||
"B1B0AAF373B8B026EB80422051D8",
|
||||
"6648C0E61AC733C76119D23FB24548D637751387AA2EAE9D80E912B7BD486CAAD9EAF4D7A5FE2B54AAD481E8EC94BB4D558000896E2010462B70C9FED1E7273080D1",
|
||||
"189F591F6CB6D59AFEDD14C341741A8F1037DC0DF00FC57CE65C30F49E860255CEA5DC6019380CC0FE8880BC1A9E685F41C239C38F36E3F2A1388865C5C311059C0A",
|
||||
"922A5E949B61D03BE34AB5F4E58607D4504EA14017BB363DAE3C873059EA7A1C77A746FB78981671D26C2CF6D9F24952D510044CE02A10177E9DB42D0145211DFE6E84369C5E3BC2669EAB4147B2822895F9"},
|
||||
{"7A832BD2CF5BF4919F353CE2A8C86A5E406DA2D52BE16A72",
|
||||
"2F2F17CECF7E5A756D10785A3CB9DB",
|
||||
"61DA05E3788CC2D8405DBA70C7A28E5AF699863C9F72E6C6770126929F5D6FA267F005EBCF49495CB46400958A3AE80D1289D1C671",
|
||||
"44E91121195A41AF14E8CFDBD39A4B517BE0DF1A72977ED8A3EEF8EEDA1166B2EB6DB2C4AE2E74FA0F0C74537F659BFBD141E5DDEC67E64EDA85AABD3F52C85A785B9FB3CECD70E7DF",
|
||||
"BEDF596EA21288D2B84901E188F6EE1468B14D5161D3802DBFE00D60203A24E2AB62714BF272A45551489838C3A7FEAADC177B591836E73684867CCF4E12901DCF2064058726BBA554E84ADC5136F507E961188D4AF06943D3"},
|
||||
{"1508E8AE9079AA15F1CEC4F776B4D11BCCB061B58AA56C18",
|
||||
"BCA625674F41D1E3AB47672DC0C3",
|
||||
"8B12CF84F16360F0EAD2A41BC021530FFCEC7F3579CAE658E10E2D3D81870F65AFCED0C77C6C4C6E6BA424FF23088C796BA6195ABA35094BF1829E089662E7A95FC90750AE16D0C8AFA55DAC789D7735B970B58D4BE7CEC7341DA82A0179A01929C27A59C5063215B859EA43",
|
||||
"E525422519ECE070E82C",
|
||||
"B47BC07C3ED1C0A43BA52C43CBACBCDBB29CAF1001E09FDF7107"},
|
||||
{"7550C2761644E911FE9ADD119BAC07376BEA442845FEAD876D7E7AC1B713E464",
|
||||
"36D2EC25ADD33CDEDF495205BBC923",
|
||||
"7FCFE81A3790DE97FFC3DE160C470847EA7E841177C2F759571CBD837EA004A6CA8C6F4AEBFF2E9FD552D73EB8A30705D58D70C0B67AEEA280CBBF0A477358ACEF1E7508F2735CD9A0E4F9AC92B8C008F575D3B6278F1C18BD01227E3502E5255F3AB1893632AD00C717C588EF652A51A43209E7EE90",
|
||||
"2B1A62F8FDFAA3C16470A21AD307C9A7D03ADE8EF72C69B06F8D738CDE578D7AEFD0D40BD9C022FB9F580DF5394C998ACCCEFC5471A3996FB8F1045A81FDC6F32D13502EA65A211390C8D882B8E0BEFD8DD8CBEF51D1597B124E9F7F",
|
||||
"C873E02A22DB89EB0787DB6A60B99F7E4A0A085D5C4232A81ADCE2D60AA36F92DDC33F93DD8640AC0E08416B187FB382B3EC3EE85A64B0E6EE41C1366A5AD2A282F66605E87031CCBA2FA7B2DA201D975994AADE3DD1EE122AE09604AD489B84BF0C1AB7129EE16C6934850E"},
|
||||
{"A51300285E554FDBDE7F771A9A9A80955639DD87129FAEF74987C91FB9687C71",
|
||||
"81691D5D20EC818FCFF24B33DECC",
|
||||
"C948093218AA9EB2A8E44A87EEA73FC8B6B75A196819A14BD83709EA323E8DF8B491045220E1D88729A38DBCFFB60D3056DAD4564498FD6574F74512945DEB34B69329ACED9FFC05D5D59DFCD5B973E2ACAFE6AD1EF8BBBC49351A2DD12508ED89ED",
|
||||
"EB861165DAF7625F827C6B574ED703F03215",
|
||||
"C6CD1CE76D2B3679C1B5AA1CFD67CCB55444B6BFD3E22C81CBC9BB738796B83E54E3"},
|
||||
{"8CE0156D26FAEB7E0B9B800BBB2E9D4075B5EAC5C62358B0E7F6FCE610223282",
|
||||
"D2A7B94DD12CDACA909D3AD7",
|
||||
"E021A78F374FC271389AB9A3E97077D755",
|
||||
"7C26000B58929F5095E1CEE154F76C2A299248E299F9B5ADE6C403AA1FD4A67FD4E0232F214CE7B919EE7A1027D2B76C57475715CD078461",
|
||||
"C556FB38DF069B56F337B5FF5775CE6EAA16824DFA754F20B78819028EA635C3BB7AA731DE8776B2DCB67DCA2D33EEDF3C7E52EA450013722A41755A0752433ED17BDD5991AAE77A"},
|
||||
{"1E8000A2CE00A561C9920A30BF0D7B983FEF8A1014C8F04C35CA6970E6BA02BD",
|
||||
"65ED3D63F79F90BBFD19775E",
|
||||
"336A8C0B7243582A46B221AA677647FCAE91",
|
||||
"134A8B34824A290E7B",
|
||||
"914FBEF80D0E6E17F8BDBB6097EBF5FBB0554952DC2B9E5151"},
|
||||
{"53D5607BBE690B6E8D8F6D97F3DF2BA853B682597A214B8AA0EA6E598650AF15",
|
||||
"C391A856B9FE234E14BA1AC7BB40FF",
|
||||
"479682BC21349C4BE1641D5E78FE2C79EC1B9CF5470936DCAD9967A4DCD7C4EFADA593BC9EDE71E6A08829B8580901B61E274227E9D918502DE3",
|
||||
"EAD154DC09C5E26C5D26FF33ED148B27120C7F2C23225CC0D0631B03E1F6C6D96FEB88C1A4052ACB4CE746B884B6502931F407021126C6AAB8C514C077A5A38438AE88EE",
|
||||
"938821286EBB671D999B87C032E1D6055392EB564E57970D55E545FC5E8BAB90E6E3E3C0913F6320995FC636D72CD9919657CC38BD51552F4A502D8D1FE56DB33EBAC5092630E69EBB986F0E15CEE9FC8C052501"},
|
||||
{"294362FCC984F440CEA3E9F7D2C06AF20C53AAC1B3738CA2186C914A6E193ABB",
|
||||
"B15B61C8BB39261A8F55AB178EC3",
|
||||
"D0729B6B75BB",
|
||||
"2BD089ADCE9F334BAE3B065996C7D616DD0C27DF4218DCEEA0FBCA0F968837CE26B0876083327E25681FDDD620A32EC0DA12F73FAE826CC94BFF2B90A54D2651",
|
||||
"AC94B25E4E21DE2437B806966CCD5D9385EF0CD4A51AB9FA6DE675C7B8952D67802E9FEC1FDE9F5D1EAB06057498BC0EEA454804FC9D2068982A3E24182D9AC2E7AB9994DDC899A604264583F63D066B"},
|
||||
{"959DBFEB039B1A5B8CE6A44649B602AAA5F98A906DB96143D202CD2024F749D9",
|
||||
"01D7BDB1133E9C347486C1EFA6",
|
||||
"F3843955BD741F379DD750585EDC55E2CDA05CCBA8C1F4622AC2FE35214BC3A019B8BD12C4CC42D9213D1E1556941E8D8450830287FFB3B763A13722DD4140ED9846FB5FFF745D7B0B967D810A068222E10B259AF1D392035B0D83DC1498A6830B11B2418A840212599171E0258A1C203B05362978",
|
||||
"A21811232C950FA8B12237C2EBD6A7CD2C3A155905E9E0C7C120",
|
||||
"63C1CE397B22F1A03F1FA549B43178BC405B152D3C95E977426D519B3DFCA28498823240592B6EEE7A14"},
|
||||
{"096AE499F5294173F34FF2B375F0E5D5AB79D0D03B33B1A74D7D576826345DF4",
|
||||
"0C52B3D11D636E5910A4DD76D32C",
|
||||
"229E9ECA3053789E937447BC719467075B6138A142DA528DA8F0CF8DDF022FD9AF8E74779BA3AC306609",
|
||||
"8B7A00038783E8BAF6EDEAE0C4EAB48FC8FD501A588C7E4A4DB71E3604F2155A97687D3D2FFF8569261375A513CF4398CE0F87CA1658A1050F6EF6C4EA3E25",
|
||||
"C20B6CF8D3C8241825FD90B2EDAC7593600646E579A8D8DAAE9E2E40C3835FE801B2BE4379131452BC5182C90307B176DFBE2049544222FE7783147B690774F6D9D7CEF52A91E61E298E9AA15464AC"},
|
||||
}
|
78
vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_a.go
generated
vendored
Normal file
78
vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_a.go
generated
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
package ocb
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
// Test vectors from https://tools.ietf.org/html/rfc7253. Note that key is
|
||||
// shared accross tests.
|
||||
var testKey, _ = hex.DecodeString("000102030405060708090A0B0C0D0E0F")
|
||||
|
||||
var rfc7253testVectors = []struct {
|
||||
nonce, header, plaintext, ciphertext string
|
||||
}{
|
||||
{"BBAA99887766554433221100",
|
||||
"",
|
||||
"",
|
||||
"785407BFFFC8AD9EDCC5520AC9111EE6"},
|
||||
{"BBAA99887766554433221101",
|
||||
"0001020304050607",
|
||||
"0001020304050607",
|
||||
"6820B3657B6F615A5725BDA0D3B4EB3A257C9AF1F8F03009"},
|
||||
{"BBAA99887766554433221102",
|
||||
"0001020304050607",
|
||||
"",
|
||||
"81017F8203F081277152FADE694A0A00"},
|
||||
{"BBAA99887766554433221103",
|
||||
"",
|
||||
"0001020304050607",
|
||||
"45DD69F8F5AAE72414054CD1F35D82760B2CD00D2F99BFA9"},
|
||||
{"BBAA99887766554433221104",
|
||||
"000102030405060708090A0B0C0D0E0F",
|
||||
"000102030405060708090A0B0C0D0E0F",
|
||||
"571D535B60B277188BE5147170A9A22C3AD7A4FF3835B8C5701C1CCEC8FC3358"},
|
||||
{"BBAA99887766554433221105",
|
||||
"000102030405060708090A0B0C0D0E0F",
|
||||
"",
|
||||
"8CF761B6902EF764462AD86498CA6B97"},
|
||||
{"BBAA99887766554433221106",
|
||||
"",
|
||||
"000102030405060708090A0B0C0D0E0F",
|
||||
"5CE88EC2E0692706A915C00AEB8B2396F40E1C743F52436BDF06D8FA1ECA343D"},
|
||||
{"BBAA99887766554433221107",
|
||||
"000102030405060708090A0B0C0D0E0F1011121314151617",
|
||||
"000102030405060708090A0B0C0D0E0F1011121314151617",
|
||||
"1CA2207308C87C010756104D8840CE1952F09673A448A122C92C62241051F57356D7F3C90BB0E07F"},
|
||||
{"BBAA99887766554433221108",
|
||||
"000102030405060708090A0B0C0D0E0F1011121314151617",
|
||||
"",
|
||||
"6DC225A071FC1B9F7C69F93B0F1E10DE"},
|
||||
{"BBAA99887766554433221109",
|
||||
"",
|
||||
"000102030405060708090A0B0C0D0E0F1011121314151617",
|
||||
"221BD0DE7FA6FE993ECCD769460A0AF2D6CDED0C395B1C3CE725F32494B9F914D85C0B1EB38357FF"},
|
||||
{"BBAA9988776655443322110A",
|
||||
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
|
||||
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
|
||||
"BD6F6C496201C69296C11EFD138A467ABD3C707924B964DEAFFC40319AF5A48540FBBA186C5553C68AD9F592A79A4240"},
|
||||
{"BBAA9988776655443322110B",
|
||||
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
|
||||
"",
|
||||
"FE80690BEE8A485D11F32965BC9D2A32"},
|
||||
{"BBAA9988776655443322110C",
|
||||
"",
|
||||
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
|
||||
"2942BFC773BDA23CABC6ACFD9BFD5835BD300F0973792EF46040C53F1432BCDFB5E1DDE3BC18A5F840B52E653444D5DF"},
|
||||
{"BBAA9988776655443322110D",
|
||||
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
|
||||
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
|
||||
"D5CA91748410C1751FF8A2F618255B68A0A12E093FF454606E59F9C1D0DDC54B65E8628E568BAD7AED07BA06A4A69483A7035490C5769E60"},
|
||||
{"BBAA9988776655443322110E",
|
||||
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
|
||||
"",
|
||||
"C5CD9D1850C141E358649994EE701B68"},
|
||||
{"BBAA9988776655443322110F",
|
||||
"",
|
||||
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
|
||||
"4412923493C57D5DE0D700F753CCE0D1D2D95060122E9F15A5DDBFC5787E50B5CC55EE507BCB084E479AD363AC366B95A98CA5F3000B1479"},
|
||||
}
|
24
vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_b.go
generated
vendored
Normal file
24
vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_b.go
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
package ocb
|
||||
|
||||
// Second set of test vectors from https://tools.ietf.org/html/rfc7253
|
||||
var rfc7253TestVectorTaglen96 = struct {
|
||||
key, nonce, header, plaintext, ciphertext string
|
||||
}{"0F0E0D0C0B0A09080706050403020100",
|
||||
"BBAA9988776655443322110D",
|
||||
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
|
||||
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
|
||||
"1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FDAC4F02AA"}
|
||||
|
||||
var rfc7253AlgorithmTest = []struct {
|
||||
KEYLEN, TAGLEN int
|
||||
OUTPUT string }{
|
||||
{128, 128, "67E944D23256C5E0B6C61FA22FDF1EA2"},
|
||||
{192, 128, "F673F2C3E7174AAE7BAE986CA9F29E17"},
|
||||
{256, 128, "D90EB8E9C977C88B79DD793D7FFA161C"},
|
||||
{128, 96, "77A3D8E73589158D25D01209"},
|
||||
{192, 96, "05D56EAD2752C86BE6932C5E"},
|
||||
{256, 96, "5458359AC23B0CBA9E6330DD"},
|
||||
{128, 64, "192C9B7BD90BA06A"},
|
||||
{192, 64, "0066BC6E0EF34E24"},
|
||||
{256, 64, "7D4EA5D445501CBE"},
|
||||
}
|
153
vendor/github.com/ProtonMail/go-crypto/openpgp/aes/keywrap/keywrap.go
generated
vendored
Normal file
153
vendor/github.com/ProtonMail/go-crypto/openpgp/aes/keywrap/keywrap.go
generated
vendored
Normal file
|
@ -0,0 +1,153 @@
|
|||
// Copyright 2014 Matthew Endsley
|
||||
// All rights reserved
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted providing that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Package keywrap is an implementation of the RFC 3394 AES key wrapping
|
||||
// algorithm. This is used in OpenPGP with elliptic curve keys.
|
||||
package keywrap
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrWrapPlaintext is returned if the plaintext is not a multiple
|
||||
// of 64 bits.
|
||||
ErrWrapPlaintext = errors.New("keywrap: plainText must be a multiple of 64 bits")
|
||||
|
||||
// ErrUnwrapCiphertext is returned if the ciphertext is not a
|
||||
// multiple of 64 bits.
|
||||
ErrUnwrapCiphertext = errors.New("keywrap: cipherText must by a multiple of 64 bits")
|
||||
|
||||
// ErrUnwrapFailed is returned if unwrapping a key fails.
|
||||
ErrUnwrapFailed = errors.New("keywrap: failed to unwrap key")
|
||||
|
||||
// NB: the AES NewCipher call only fails if the key is an invalid length.
|
||||
|
||||
// ErrInvalidKey is returned when the AES key is invalid.
|
||||
ErrInvalidKey = errors.New("keywrap: invalid AES key")
|
||||
)
|
||||
|
||||
// Wrap a key using the RFC 3394 AES Key Wrap Algorithm.
|
||||
func Wrap(key, plainText []byte) ([]byte, error) {
|
||||
if len(plainText)%8 != 0 {
|
||||
return nil, ErrWrapPlaintext
|
||||
}
|
||||
|
||||
c, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, ErrInvalidKey
|
||||
}
|
||||
|
||||
nblocks := len(plainText) / 8
|
||||
|
||||
// 1) Initialize variables.
|
||||
var block [aes.BlockSize]byte
|
||||
// - Set A = IV, an initial value (see 2.2.3)
|
||||
for ii := 0; ii < 8; ii++ {
|
||||
block[ii] = 0xA6
|
||||
}
|
||||
|
||||
// - For i = 1 to n
|
||||
// - Set R[i] = P[i]
|
||||
intermediate := make([]byte, len(plainText))
|
||||
copy(intermediate, plainText)
|
||||
|
||||
// 2) Calculate intermediate values.
|
||||
for ii := 0; ii < 6; ii++ {
|
||||
for jj := 0; jj < nblocks; jj++ {
|
||||
// - B = AES(K, A | R[i])
|
||||
copy(block[8:], intermediate[jj*8:jj*8+8])
|
||||
c.Encrypt(block[:], block[:])
|
||||
|
||||
// - A = MSB(64, B) ^ t where t = (n*j)+1
|
||||
t := uint64(ii*nblocks + jj + 1)
|
||||
val := binary.BigEndian.Uint64(block[:8]) ^ t
|
||||
binary.BigEndian.PutUint64(block[:8], val)
|
||||
|
||||
// - R[i] = LSB(64, B)
|
||||
copy(intermediate[jj*8:jj*8+8], block[8:])
|
||||
}
|
||||
}
|
||||
|
||||
// 3) Output results.
|
||||
// - Set C[0] = A
|
||||
// - For i = 1 to n
|
||||
// - C[i] = R[i]
|
||||
return append(block[:8], intermediate...), nil
|
||||
}
|
||||
|
||||
// Unwrap a key using the RFC 3394 AES Key Wrap Algorithm.
|
||||
func Unwrap(key, cipherText []byte) ([]byte, error) {
|
||||
if len(cipherText)%8 != 0 {
|
||||
return nil, ErrUnwrapCiphertext
|
||||
}
|
||||
|
||||
c, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, ErrInvalidKey
|
||||
}
|
||||
|
||||
nblocks := len(cipherText)/8 - 1
|
||||
|
||||
// 1) Initialize variables.
|
||||
var block [aes.BlockSize]byte
|
||||
// - Set A = C[0]
|
||||
copy(block[:8], cipherText[:8])
|
||||
|
||||
// - For i = 1 to n
|
||||
// - Set R[i] = C[i]
|
||||
intermediate := make([]byte, len(cipherText)-8)
|
||||
copy(intermediate, cipherText[8:])
|
||||
|
||||
// 2) Compute intermediate values.
|
||||
for jj := 5; jj >= 0; jj-- {
|
||||
for ii := nblocks - 1; ii >= 0; ii-- {
|
||||
// - B = AES-1(K, (A ^ t) | R[i]) where t = n*j+1
|
||||
// - A = MSB(64, B)
|
||||
t := uint64(jj*nblocks + ii + 1)
|
||||
val := binary.BigEndian.Uint64(block[:8]) ^ t
|
||||
binary.BigEndian.PutUint64(block[:8], val)
|
||||
|
||||
copy(block[8:], intermediate[ii*8:ii*8+8])
|
||||
c.Decrypt(block[:], block[:])
|
||||
|
||||
// - R[i] = LSB(B, 64)
|
||||
copy(intermediate[ii*8:ii*8+8], block[8:])
|
||||
}
|
||||
}
|
||||
|
||||
// 3) Output results.
|
||||
// - If A is an appropriate initial value (see 2.2.3),
|
||||
for ii := 0; ii < 8; ii++ {
|
||||
if block[ii] != 0xA6 {
|
||||
return nil, ErrUnwrapFailed
|
||||
}
|
||||
}
|
||||
|
||||
// - For i = 1 to n
|
||||
// - P[i] = R[i]
|
||||
return intermediate, nil
|
||||
}
|
|
@ -4,13 +4,13 @@
|
|||
|
||||
// Package armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is
|
||||
// very similar to PEM except that it has an additional CRC checksum.
|
||||
package armor // import "golang.org/x/crypto/openpgp/armor"
|
||||
package armor // import "github.com/ProtonMail/go-crypto/openpgp/armor"
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"golang.org/x/crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"io"
|
||||
)
|
||||
|
|
@ -4,7 +4,10 @@
|
|||
|
||||
package openpgp
|
||||
|
||||
import "hash"
|
||||
import (
|
||||
"hash"
|
||||
"io"
|
||||
)
|
||||
|
||||
// NewCanonicalTextHash reformats text written to it into the canonical
|
||||
// form and then applies the hash h. See RFC 4880, section 5.2.1.
|
||||
|
@ -19,28 +22,31 @@ type canonicalTextHash struct {
|
|||
|
||||
var newline = []byte{'\r', '\n'}
|
||||
|
||||
func (cth *canonicalTextHash) Write(buf []byte) (int, error) {
|
||||
func writeCanonical(cw io.Writer, buf []byte, s *int) (int, error) {
|
||||
start := 0
|
||||
|
||||
for i, c := range buf {
|
||||
switch cth.s {
|
||||
switch *s {
|
||||
case 0:
|
||||
if c == '\r' {
|
||||
cth.s = 1
|
||||
*s = 1
|
||||
} else if c == '\n' {
|
||||
cth.h.Write(buf[start:i])
|
||||
cth.h.Write(newline)
|
||||
cw.Write(buf[start:i])
|
||||
cw.Write(newline)
|
||||
start = i + 1
|
||||
}
|
||||
case 1:
|
||||
cth.s = 0
|
||||
*s = 0
|
||||
}
|
||||
}
|
||||
|
||||
cth.h.Write(buf[start:])
|
||||
cw.Write(buf[start:])
|
||||
return len(buf), nil
|
||||
}
|
||||
|
||||
func (cth *canonicalTextHash) Write(buf []byte) (int, error) {
|
||||
return writeCanonical(cth.h, buf, &cth.s)
|
||||
}
|
||||
|
||||
func (cth *canonicalTextHash) Sum(in []byte) []byte {
|
||||
return cth.h.Sum(in)
|
||||
}
|
165
vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/ecdh.go
generated
vendored
Normal file
165
vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/ecdh.go
generated
vendored
Normal file
|
@ -0,0 +1,165 @@
|
|||
// Copyright 2017 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 ecdh implements ECDH encryption, suitable for OpenPGP,
|
||||
// as specified in RFC 6637, section 8.
|
||||
package ecdh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/elliptic"
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/aes/keywrap"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
|
||||
)
|
||||
|
||||
type KDF struct {
|
||||
Hash algorithm.Hash
|
||||
Cipher algorithm.Cipher
|
||||
}
|
||||
|
||||
type PublicKey struct {
|
||||
ecc.CurveType
|
||||
elliptic.Curve
|
||||
X, Y *big.Int
|
||||
KDF
|
||||
}
|
||||
|
||||
type PrivateKey struct {
|
||||
PublicKey
|
||||
D []byte
|
||||
}
|
||||
|
||||
func GenerateKey(c elliptic.Curve, kdf KDF, rand io.Reader) (priv *PrivateKey, err error) {
|
||||
priv = new(PrivateKey)
|
||||
priv.PublicKey.Curve = c
|
||||
priv.PublicKey.KDF = kdf
|
||||
priv.D, priv.PublicKey.X, priv.PublicKey.Y, err = elliptic.GenerateKey(c, rand)
|
||||
return
|
||||
}
|
||||
|
||||
func Encrypt(random io.Reader, pub *PublicKey, msg, curveOID, fingerprint []byte) (vsG, c []byte, err error) {
|
||||
if len(msg) > 40 {
|
||||
return nil, nil, errors.New("ecdh: message too long")
|
||||
}
|
||||
// the sender MAY use 21, 13, and 5 bytes of padding for AES-128,
|
||||
// AES-192, and AES-256, respectively, to provide the same number of
|
||||
// octets, 40 total, as an input to the key wrapping method.
|
||||
padding := make([]byte, 40-len(msg))
|
||||
for i := range padding {
|
||||
padding[i] = byte(40 - len(msg))
|
||||
}
|
||||
m := append(msg, padding...)
|
||||
|
||||
if pub.CurveType == ecc.Curve25519 {
|
||||
return X25519Encrypt(random, pub, m, curveOID, fingerprint)
|
||||
}
|
||||
|
||||
d, x, y, err := elliptic.GenerateKey(pub.Curve, random)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
vsG = elliptic.Marshal(pub.Curve, x, y)
|
||||
zbBig, _ := pub.Curve.ScalarMult(pub.X, pub.Y, d)
|
||||
|
||||
byteLen := (pub.Curve.Params().BitSize + 7) >> 3
|
||||
zb := make([]byte, byteLen)
|
||||
zbBytes := zbBig.Bytes()
|
||||
copy(zb[byteLen-len(zbBytes):], zbBytes)
|
||||
|
||||
z, err := buildKey(pub, zb, curveOID, fingerprint, false, false)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if c, err = keywrap.Wrap(z, m); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return vsG, c, nil
|
||||
|
||||
}
|
||||
|
||||
func Decrypt(priv *PrivateKey, vsG, m, curveOID, fingerprint []byte) (msg []byte, err error) {
|
||||
if priv.PublicKey.CurveType == ecc.Curve25519 {
|
||||
return X25519Decrypt(priv, vsG, m, curveOID, fingerprint)
|
||||
}
|
||||
x, y := elliptic.Unmarshal(priv.Curve, vsG)
|
||||
zbBig, _ := priv.Curve.ScalarMult(x, y, priv.D)
|
||||
|
||||
byteLen := (priv.Curve.Params().BitSize + 7) >> 3
|
||||
zb := make([]byte, byteLen)
|
||||
zbBytes := zbBig.Bytes()
|
||||
copy(zb[byteLen-len(zbBytes):], zbBytes)
|
||||
|
||||
z, err := buildKey(&priv.PublicKey, zb, curveOID, fingerprint, false, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c, err := keywrap.Unwrap(z, m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c[:len(c)-int(c[len(c)-1])], nil
|
||||
}
|
||||
|
||||
func buildKey(pub *PublicKey, zb []byte, curveOID, fingerprint []byte, stripLeading, stripTrailing bool) ([]byte, error) {
|
||||
// Param = curve_OID_len || curve_OID || public_key_alg_ID || 03
|
||||
// || 01 || KDF_hash_ID || KEK_alg_ID for AESKeyWrap
|
||||
// || "Anonymous Sender " || recipient_fingerprint;
|
||||
param := new(bytes.Buffer)
|
||||
if _, err := param.Write(curveOID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
algKDF := []byte{18, 3, 1, pub.KDF.Hash.Id(), pub.KDF.Cipher.Id()}
|
||||
if _, err := param.Write(algKDF); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := param.Write([]byte("Anonymous Sender ")); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// For v5 keys, the 20 leftmost octets of the fingerprint are used.
|
||||
if _, err := param.Write(fingerprint[:20]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if param.Len() - len(curveOID) != 45 {
|
||||
return nil, errors.New("ecdh: malformed KDF Param")
|
||||
}
|
||||
|
||||
// MB = Hash ( 00 || 00 || 00 || 01 || ZB || Param );
|
||||
h := pub.KDF.Hash.New()
|
||||
if _, err := h.Write([]byte{0x0, 0x0, 0x0, 0x1}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
zbLen := len(zb)
|
||||
i := 0
|
||||
j := zbLen - 1
|
||||
if stripLeading {
|
||||
// Work around old go crypto bug where the leading zeros are missing.
|
||||
for ; i < zbLen && zb[i] == 0; i++ {}
|
||||
}
|
||||
if stripTrailing {
|
||||
// Work around old OpenPGP.js bug where insignificant trailing zeros in
|
||||
// this little-endian number are missing.
|
||||
// (See https://github.com/openpgpjs/openpgpjs/pull/853.)
|
||||
for ; j >= 0 && zb[j] == 0; j-- {}
|
||||
}
|
||||
if _, err := h.Write(zb[i:j+1]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := h.Write(param.Bytes()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mb := h.Sum(nil)
|
||||
|
||||
return mb[:pub.KDF.Cipher.KeySize()], nil // return oBits leftmost bits of MB.
|
||||
|
||||
}
|
157
vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/x25519.go
generated
vendored
Normal file
157
vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/x25519.go
generated
vendored
Normal file
|
@ -0,0 +1,157 @@
|
|||
// Copyright 2017 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 ecdh implements ECDH encryption, suitable for OpenPGP,
|
||||
// as specified in RFC 6637, section 8.
|
||||
package ecdh
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/aes/keywrap"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
|
||||
"golang.org/x/crypto/curve25519"
|
||||
)
|
||||
|
||||
// Generates a private-public key-pair.
|
||||
// 'priv' is a private key; a scalar belonging to the set
|
||||
// 2^{254} + 8 * [0, 2^{251}), in order to avoid the small subgroup of the
|
||||
// curve. 'pub' is simply 'priv' * G where G is the base point.
|
||||
// See https://cr.yp.to/ecdh.html and RFC7748, sec 5.
|
||||
func x25519GenerateKeyPairBytes(rand io.Reader) (priv [32]byte, pub [32]byte, err error) {
|
||||
var n, helper = new(big.Int), new(big.Int)
|
||||
n.SetUint64(1)
|
||||
n.Lsh(n, 252)
|
||||
helper.SetString("27742317777372353535851937790883648493", 10)
|
||||
n.Add(n, helper)
|
||||
|
||||
for true {
|
||||
_, err = io.ReadFull(rand, priv[:])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// The following ensures that the private key is a number of the form
|
||||
// 2^{254} + 8 * [0, 2^{251}), in order to avoid the small subgroup of
|
||||
// of the curve.
|
||||
priv[0] &= 248
|
||||
priv[31] &= 127
|
||||
priv[31] |= 64
|
||||
|
||||
// If the scalar is out of range, sample another random number.
|
||||
if new(big.Int).SetBytes(priv[:]).Cmp(n) >= 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
curve25519.ScalarBaseMult(&pub, &priv)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// X25519GenerateKey samples the key pair according to the correct distribution.
|
||||
// It also sets the given key-derivation function and returns the *PrivateKey
|
||||
// object along with an error.
|
||||
func X25519GenerateKey(rand io.Reader, kdf KDF) (priv *PrivateKey, err error) {
|
||||
ci := ecc.FindByName("Curve25519")
|
||||
priv = new(PrivateKey)
|
||||
priv.PublicKey.Curve = ci.Curve
|
||||
d, pubKey, err := x25519GenerateKeyPairBytes(rand)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
priv.PublicKey.KDF = kdf
|
||||
priv.D = make([]byte, 32)
|
||||
copyReversed(priv.D, d[:])
|
||||
priv.PublicKey.CurveType = ci.CurveType
|
||||
priv.PublicKey.Curve = ci.Curve
|
||||
/*
|
||||
* Note that ECPoint.point differs from the definition of public keys in
|
||||
* [Curve25519] in two ways: (1) the byte-ordering is big-endian, which is
|
||||
* more uniform with how big integers are represented in TLS, and (2) there
|
||||
* is an additional length byte (so ECpoint.point is actually 33 bytes),
|
||||
* again for uniformity (and extensibility).
|
||||
*/
|
||||
var encodedKey = make([]byte, 33)
|
||||
encodedKey[0] = 0x40
|
||||
copy(encodedKey[1:], pubKey[:])
|
||||
priv.PublicKey.X = new(big.Int).SetBytes(encodedKey[:])
|
||||
priv.PublicKey.Y = new(big.Int)
|
||||
return priv, nil
|
||||
}
|
||||
|
||||
func X25519Encrypt(random io.Reader, pub *PublicKey, msg, curveOID, fingerprint []byte) (vsG, c []byte, err error) {
|
||||
d, ephemeralKey, err := x25519GenerateKeyPairBytes(random)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
var pubKey [32]byte
|
||||
|
||||
if pub.X.BitLen() > 33*264 {
|
||||
return nil, nil, errors.New("ecdh: invalid key")
|
||||
}
|
||||
copy(pubKey[:], pub.X.Bytes()[1:])
|
||||
|
||||
var zb [32]byte
|
||||
curve25519.ScalarBaseMult(&zb, &d)
|
||||
curve25519.ScalarMult(&zb, &d, &pubKey)
|
||||
z, err := buildKey(pub, zb[:], curveOID, fingerprint, false, false)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if c, err = keywrap.Wrap(z, msg); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var vsg [33]byte
|
||||
vsg[0] = 0x40
|
||||
copy(vsg[1:], ephemeralKey[:])
|
||||
|
||||
return vsg[:], c, nil
|
||||
}
|
||||
|
||||
func X25519Decrypt(priv *PrivateKey, vsG, m, curveOID, fingerprint []byte) (msg []byte, err error) {
|
||||
var zb, d, ephemeralKey [32]byte
|
||||
if len(vsG) != 33 || vsG[0] != 0x40 {
|
||||
return nil, errors.New("ecdh: invalid key")
|
||||
}
|
||||
copy(ephemeralKey[:], vsG[1:33])
|
||||
|
||||
copyReversed(d[:], priv.D)
|
||||
curve25519.ScalarBaseMult(&zb, &d)
|
||||
curve25519.ScalarMult(&zb, &d, &ephemeralKey)
|
||||
|
||||
var c []byte
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
// Try buildKey three times for compat, see comments in buildKey.
|
||||
z, err := buildKey(&priv.PublicKey, zb[:], curveOID, fingerprint, i == 1, i == 2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := keywrap.Unwrap(z, m)
|
||||
if i == 2 && err != nil {
|
||||
// Only return an error after we've tried all variants of buildKey.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c = res
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return c[:len(c)-int(c[len(c)-1])], nil
|
||||
}
|
||||
|
||||
func copyReversed(out []byte, in []byte) {
|
||||
l := len(in)
|
||||
for i := 0; i < l; i++ {
|
||||
out[i] = in[l-i-1]
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@
|
|||
// This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it
|
||||
// unsuitable for other protocols. RSA should be used in preference in any
|
||||
// case.
|
||||
package elgamal // import "golang.org/x/crypto/openpgp/elgamal"
|
||||
package elgamal // import "github.com/ProtonMail/go-crypto/openpgp/elgamal"
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
|
@ -3,7 +3,7 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package errors contains common error types for the OpenPGP packages.
|
||||
package errors // import "golang.org/x/crypto/openpgp/errors"
|
||||
package errors // import "github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
@ -41,6 +41,25 @@ func (b SignatureError) Error() string {
|
|||
return "openpgp: invalid signature: " + string(b)
|
||||
}
|
||||
|
||||
var ErrMDCHashMismatch error = SignatureError("MDC hash mismatch")
|
||||
var ErrMDCMissing error = SignatureError("MDC packet not found")
|
||||
|
||||
type signatureExpiredError int
|
||||
|
||||
func (se signatureExpiredError) Error() string {
|
||||
return "openpgp: signature expired"
|
||||
}
|
||||
|
||||
var ErrSignatureExpired error = signatureExpiredError(0)
|
||||
|
||||
type keyExpiredError int
|
||||
|
||||
func (ke keyExpiredError) Error() string {
|
||||
return "openpgp: key expired"
|
||||
}
|
||||
|
||||
var ErrKeyExpired error = keyExpiredError(0)
|
||||
|
||||
type keyIncorrectError int
|
||||
|
||||
func (ki keyIncorrectError) Error() string {
|
||||
|
@ -49,6 +68,14 @@ func (ki keyIncorrectError) Error() string {
|
|||
|
||||
var ErrKeyIncorrect error = keyIncorrectError(0)
|
||||
|
||||
// KeyInvalidError indicates that the public key parameters are invalid
|
||||
// as they do not match the private ones
|
||||
type KeyInvalidError string
|
||||
|
||||
func (e KeyInvalidError) Error() string {
|
||||
return "openpgp: invalid key: " + string(e)
|
||||
}
|
||||
|
||||
type unknownIssuerError int
|
||||
|
||||
func (unknownIssuerError) Error() string {
|
||||
|
@ -70,3 +97,20 @@ type UnknownPacketTypeError uint8
|
|||
func (upte UnknownPacketTypeError) Error() string {
|
||||
return "openpgp: unknown packet type: " + strconv.Itoa(int(upte))
|
||||
}
|
||||
|
||||
// AEADError indicates that there is a problem when initializing or using a
|
||||
// AEAD instance, configuration struct, nonces or index values.
|
||||
type AEADError string
|
||||
|
||||
func (ae AEADError) Error() string {
|
||||
return "openpgp: aead error: " + string(ae)
|
||||
}
|
||||
|
||||
// ErrDummyPrivateKey results when operations are attempted on a private key
|
||||
// that is just a dummy key. See
|
||||
// https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/DETAILS;h=fe55ae16ab4e26d8356dc574c9e8bc935e71aef1;hb=23191d7851eae2217ecdac6484349849a24fd94a#l1109
|
||||
type ErrDummyPrivateKey string
|
||||
|
||||
func (dke ErrDummyPrivateKey) Error() string {
|
||||
return "openpgp: s2k GNU dummy key: " + string(dke)
|
||||
}
|
65
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/aead.go
generated
vendored
Normal file
65
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/aead.go
generated
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
// Copyright (C) 2019 ProtonTech AG
|
||||
|
||||
package algorithm
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"github.com/ProtonMail/go-crypto/eax"
|
||||
"github.com/ProtonMail/go-crypto/ocb"
|
||||
)
|
||||
|
||||
// AEADMode defines the Authenticated Encryption with Associated Data mode of
|
||||
// operation.
|
||||
type AEADMode uint8
|
||||
|
||||
// Supported modes of operation (see RFC4880bis [EAX] and RFC7253)
|
||||
const (
|
||||
AEADModeEAX = AEADMode(1)
|
||||
AEADModeOCB = AEADMode(2)
|
||||
AEADModeGCM = AEADMode(100)
|
||||
)
|
||||
|
||||
// TagLength returns the length in bytes of authentication tags.
|
||||
func (mode AEADMode) TagLength() int {
|
||||
switch mode {
|
||||
case AEADModeEAX:
|
||||
return 16
|
||||
case AEADModeOCB:
|
||||
return 16
|
||||
case AEADModeGCM:
|
||||
return 16
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// NonceLength returns the length in bytes of nonces.
|
||||
func (mode AEADMode) NonceLength() int {
|
||||
switch mode {
|
||||
case AEADModeEAX:
|
||||
return 16
|
||||
case AEADModeOCB:
|
||||
return 15
|
||||
case AEADModeGCM:
|
||||
return 12
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// New returns a fresh instance of the given mode
|
||||
func (mode AEADMode) New(block cipher.Block) (alg cipher.AEAD) {
|
||||
var err error
|
||||
switch mode {
|
||||
case AEADModeEAX:
|
||||
alg, err = eax.NewEAX(block)
|
||||
case AEADModeOCB:
|
||||
alg, err = ocb.NewOCB(block)
|
||||
case AEADModeGCM:
|
||||
alg, err = cipher.NewGCM(block)
|
||||
}
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
return alg
|
||||
}
|
107
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/cipher.go
generated
vendored
Normal file
107
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/cipher.go
generated
vendored
Normal file
|
@ -0,0 +1,107 @@
|
|||
// Copyright 2017 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 algorithm
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/des"
|
||||
|
||||
"golang.org/x/crypto/cast5"
|
||||
)
|
||||
|
||||
// Cipher is an official symmetric key cipher algorithm. See RFC 4880,
|
||||
// section 9.2.
|
||||
type Cipher interface {
|
||||
// Id returns the algorithm ID, as a byte, of the cipher.
|
||||
Id() uint8
|
||||
// KeySize returns the key size, in bytes, of the cipher.
|
||||
KeySize() int
|
||||
// BlockSize returns the block size, in bytes, of the cipher.
|
||||
BlockSize() int
|
||||
// New returns a fresh instance of the given cipher.
|
||||
New(key []byte) cipher.Block
|
||||
}
|
||||
|
||||
// The following constants mirror the OpenPGP standard (RFC 4880).
|
||||
const (
|
||||
TripleDES = CipherFunction(2)
|
||||
CAST5 = CipherFunction(3)
|
||||
AES128 = CipherFunction(7)
|
||||
AES192 = CipherFunction(8)
|
||||
AES256 = CipherFunction(9)
|
||||
)
|
||||
|
||||
// CipherById represents the different block ciphers specified for OpenPGP. See
|
||||
// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13
|
||||
var CipherById = map[uint8]Cipher{
|
||||
TripleDES.Id(): TripleDES,
|
||||
CAST5.Id(): CAST5,
|
||||
AES128.Id(): AES128,
|
||||
AES192.Id(): AES192,
|
||||
AES256.Id(): AES256,
|
||||
}
|
||||
|
||||
type CipherFunction uint8
|
||||
|
||||
// ID returns the algorithm Id, as a byte, of cipher.
|
||||
func (sk CipherFunction) Id() uint8 {
|
||||
return uint8(sk)
|
||||
}
|
||||
|
||||
var keySizeByID = map[uint8]int{
|
||||
TripleDES.Id(): 24,
|
||||
CAST5.Id(): cast5.KeySize,
|
||||
AES128.Id(): 16,
|
||||
AES192.Id(): 24,
|
||||
AES256.Id(): 32,
|
||||
}
|
||||
|
||||
// KeySize returns the key size, in bytes, of cipher.
|
||||
func (cipher CipherFunction) KeySize() int {
|
||||
switch cipher {
|
||||
case TripleDES:
|
||||
return 24
|
||||
case CAST5:
|
||||
return cast5.KeySize
|
||||
case AES128:
|
||||
return 16
|
||||
case AES192:
|
||||
return 24
|
||||
case AES256:
|
||||
return 32
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// BlockSize returns the block size, in bytes, of cipher.
|
||||
func (cipher CipherFunction) BlockSize() int {
|
||||
switch cipher {
|
||||
case TripleDES:
|
||||
return des.BlockSize
|
||||
case CAST5:
|
||||
return 8
|
||||
case AES128, AES192, AES256:
|
||||
return 16
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// New returns a fresh instance of the given cipher.
|
||||
func (cipher CipherFunction) New(key []byte) (block cipher.Block) {
|
||||
var err error
|
||||
switch cipher {
|
||||
case TripleDES:
|
||||
block, err = des.NewTripleDESCipher(key)
|
||||
case CAST5:
|
||||
block, err = cast5.NewCipher(key)
|
||||
case AES128, AES192, AES256:
|
||||
block, err = aes.NewCipher(key)
|
||||
}
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
86
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/hash.go
generated
vendored
Normal file
86
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/hash.go
generated
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
// Copyright 2017 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 algorithm
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"fmt"
|
||||
"hash"
|
||||
)
|
||||
|
||||
// Hash is an official hash function algorithm. See RFC 4880, section 9.4.
|
||||
type Hash interface {
|
||||
// Id returns the algorithm ID, as a byte, of Hash.
|
||||
Id() uint8
|
||||
// Available reports whether the given hash function is linked into the binary.
|
||||
Available() bool
|
||||
// HashFunc simply returns the value of h so that Hash implements SignerOpts.
|
||||
HashFunc() crypto.Hash
|
||||
// New returns a new hash.Hash calculating the given hash function. New
|
||||
// panics if the hash function is not linked into the binary.
|
||||
New() hash.Hash
|
||||
// Size returns the length, in bytes, of a digest resulting from the given
|
||||
// hash function. It doesn't require that the hash function in question be
|
||||
// linked into the program.
|
||||
Size() int
|
||||
// String is the name of the hash function corresponding to the given
|
||||
// OpenPGP hash id.
|
||||
String() string
|
||||
}
|
||||
|
||||
// The following vars mirror the crypto/Hash supported hash functions.
|
||||
var (
|
||||
MD5 Hash = cryptoHash{1, crypto.MD5}
|
||||
SHA1 Hash = cryptoHash{2, crypto.SHA1}
|
||||
RIPEMD160 Hash = cryptoHash{3, crypto.RIPEMD160}
|
||||
SHA256 Hash = cryptoHash{8, crypto.SHA256}
|
||||
SHA384 Hash = cryptoHash{9, crypto.SHA384}
|
||||
SHA512 Hash = cryptoHash{10, crypto.SHA512}
|
||||
SHA224 Hash = cryptoHash{11, crypto.SHA224}
|
||||
)
|
||||
|
||||
// HashById represents the different hash functions specified for OpenPGP. See
|
||||
// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-14
|
||||
var (
|
||||
HashById = map[uint8]Hash{
|
||||
MD5.Id(): MD5,
|
||||
SHA1.Id(): SHA1,
|
||||
RIPEMD160.Id(): RIPEMD160,
|
||||
SHA256.Id(): SHA256,
|
||||
SHA384.Id(): SHA384,
|
||||
SHA512.Id(): SHA512,
|
||||
SHA224.Id(): SHA224,
|
||||
}
|
||||
)
|
||||
|
||||
// cryptoHash contains pairs relating OpenPGP's hash identifier with
|
||||
// Go's crypto.Hash type. See RFC 4880, section 9.4.
|
||||
type cryptoHash struct {
|
||||
id uint8
|
||||
crypto.Hash
|
||||
}
|
||||
|
||||
// Id returns the algorithm ID, as a byte, of cryptoHash.
|
||||
func (h cryptoHash) Id() uint8 {
|
||||
return h.id
|
||||
}
|
||||
|
||||
var hashNames = map[uint8]string{
|
||||
MD5.Id(): "MD5",
|
||||
SHA1.Id(): "SHA1",
|
||||
RIPEMD160.Id(): "RIPEMD160",
|
||||
SHA256.Id(): "SHA256",
|
||||
SHA384.Id(): "SHA384",
|
||||
SHA512.Id(): "SHA512",
|
||||
SHA224.Id(): "SHA224",
|
||||
}
|
||||
|
||||
func (h cryptoHash) String() string {
|
||||
s, ok := hashNames[h.id]
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("Unsupported hash function %d", h.id))
|
||||
}
|
||||
return s
|
||||
}
|
118
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curveInfo.go
generated
vendored
Normal file
118
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curveInfo.go
generated
vendored
Normal file
|
@ -0,0 +1,118 @@
|
|||
package ecc
|
||||
|
||||
import (
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
|
||||
"crypto/elliptic"
|
||||
"bytes"
|
||||
"github.com/ProtonMail/go-crypto/bitcurves"
|
||||
"github.com/ProtonMail/go-crypto/brainpool"
|
||||
)
|
||||
|
||||
type SignatureAlgorithm uint8
|
||||
|
||||
const (
|
||||
ECDSA SignatureAlgorithm = 1
|
||||
EdDSA SignatureAlgorithm = 2
|
||||
)
|
||||
|
||||
type CurveInfo struct {
|
||||
Name string
|
||||
Oid *encoding.OID
|
||||
Curve elliptic.Curve
|
||||
SigAlgorithm SignatureAlgorithm
|
||||
CurveType CurveType
|
||||
}
|
||||
|
||||
var curves = []CurveInfo{
|
||||
{
|
||||
Name: "NIST curve P-256",
|
||||
Oid: encoding.NewOID([]byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}),
|
||||
Curve: elliptic.P256(),
|
||||
CurveType: NISTCurve,
|
||||
SigAlgorithm: ECDSA,
|
||||
},
|
||||
{
|
||||
Name: "NIST curve P-384",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x22}),
|
||||
Curve: elliptic.P384(),
|
||||
CurveType: NISTCurve,
|
||||
SigAlgorithm: ECDSA,
|
||||
},
|
||||
{
|
||||
Name: "NIST curve P-521",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x23}),
|
||||
Curve: elliptic.P521(),
|
||||
CurveType: NISTCurve,
|
||||
SigAlgorithm: ECDSA,
|
||||
},
|
||||
{
|
||||
Name: "SecP256k1",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x0A}),
|
||||
Curve: bitcurves.S256(),
|
||||
CurveType: BitCurve,
|
||||
SigAlgorithm: ECDSA,
|
||||
},
|
||||
{
|
||||
Name: "Curve25519",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01}),
|
||||
Curve: elliptic.P256(),// filler
|
||||
CurveType: Curve25519,
|
||||
SigAlgorithm: ECDSA,
|
||||
},
|
||||
{
|
||||
Name: "Ed25519",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01}),
|
||||
Curve: elliptic.P256(), // filler
|
||||
CurveType: NISTCurve,
|
||||
SigAlgorithm: EdDSA,
|
||||
},
|
||||
{
|
||||
Name: "Brainpool P256r1",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07}),
|
||||
Curve: brainpool.P256r1(),
|
||||
CurveType: BrainpoolCurve,
|
||||
SigAlgorithm: ECDSA,
|
||||
},
|
||||
{
|
||||
Name: "BrainpoolP384r1",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B}),
|
||||
Curve: brainpool.P384r1(),
|
||||
CurveType: BrainpoolCurve,
|
||||
SigAlgorithm: ECDSA,
|
||||
},
|
||||
{
|
||||
Name: "BrainpoolP512r1",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D}),
|
||||
Curve: brainpool.P512r1(),
|
||||
CurveType: BrainpoolCurve,
|
||||
SigAlgorithm: ECDSA,
|
||||
},
|
||||
}
|
||||
|
||||
func FindByCurve(curve elliptic.Curve) *CurveInfo {
|
||||
for _, curveInfo := range curves {
|
||||
if curveInfo.Curve == curve {
|
||||
return &curveInfo
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func FindByOid(oid encoding.Field) *CurveInfo {
|
||||
var rawBytes = oid.Bytes()
|
||||
for _, curveInfo := range curves {
|
||||
if bytes.Equal(curveInfo.Oid.Bytes(), rawBytes) {
|
||||
return &curveInfo
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func FindByName(name string) *CurveInfo {
|
||||
for _, curveInfo := range curves {
|
||||
if curveInfo.Name == name {
|
||||
return &curveInfo
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
10
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curveType.go
generated
vendored
Normal file
10
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curveType.go
generated
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
package ecc
|
||||
|
||||
type CurveType uint8
|
||||
|
||||
const (
|
||||
NISTCurve CurveType = 1
|
||||
Curve25519 CurveType = 2
|
||||
BitCurve CurveType = 3
|
||||
BrainpoolCurve CurveType = 4
|
||||
)
|
27
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/encoding.go
generated
vendored
Normal file
27
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/encoding.go
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2017 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 encoding implements openpgp packet field encodings as specified in
|
||||
// RFC 4880 and 6637.
|
||||
package encoding
|
||||
|
||||
import "io"
|
||||
|
||||
// Field is an encoded field of an openpgp packet.
|
||||
type Field interface {
|
||||
// Bytes returns the decoded data.
|
||||
Bytes() []byte
|
||||
|
||||
// BitLength is the size in bits of the decoded data.
|
||||
BitLength() uint16
|
||||
|
||||
// EncodedBytes returns the encoded data.
|
||||
EncodedBytes() []byte
|
||||
|
||||
// EncodedLength is the size in bytes of the encoded data.
|
||||
EncodedLength() uint16
|
||||
|
||||
// ReadFrom reads the next Field from r.
|
||||
ReadFrom(r io.Reader) (int64, error)
|
||||
}
|
91
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/mpi.go
generated
vendored
Normal file
91
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/mpi.go
generated
vendored
Normal file
|
@ -0,0 +1,91 @@
|
|||
// Copyright 2017 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 encoding
|
||||
|
||||
import (
|
||||
"io"
|
||||
"math/big"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
// An MPI is used to store the contents of a big integer, along with the bit
|
||||
// length that was specified in the original input. This allows the MPI to be
|
||||
// reserialized exactly.
|
||||
type MPI struct {
|
||||
bytes []byte
|
||||
bitLength uint16
|
||||
}
|
||||
|
||||
// NewMPI returns a MPI initialized with bytes.
|
||||
func NewMPI(bytes []byte) *MPI {
|
||||
for len(bytes) != 0 && bytes[0] == 0 {
|
||||
bytes = bytes[1:]
|
||||
}
|
||||
if len(bytes) == 0 {
|
||||
bitLength := uint16(0)
|
||||
return &MPI{bytes, bitLength}
|
||||
}
|
||||
bitLength := 8*uint16(len(bytes)-1) + uint16(bits.Len8(bytes[0]))
|
||||
return &MPI{bytes, bitLength}
|
||||
}
|
||||
|
||||
// Bytes returns the decoded data.
|
||||
func (m *MPI) Bytes() []byte {
|
||||
return m.bytes
|
||||
}
|
||||
|
||||
// BitLength is the size in bits of the decoded data.
|
||||
func (m *MPI) BitLength() uint16 {
|
||||
return m.bitLength
|
||||
}
|
||||
|
||||
// EncodedBytes returns the encoded data.
|
||||
func (m *MPI) EncodedBytes() []byte {
|
||||
return append([]byte{byte(m.bitLength >> 8), byte(m.bitLength)}, m.bytes...)
|
||||
}
|
||||
|
||||
// EncodedLength is the size in bytes of the encoded data.
|
||||
func (m *MPI) EncodedLength() uint16 {
|
||||
return uint16(2 + len(m.bytes))
|
||||
}
|
||||
|
||||
// ReadFrom reads into m the next MPI from r.
|
||||
func (m *MPI) ReadFrom(r io.Reader) (int64, error) {
|
||||
var buf [2]byte
|
||||
n, err := io.ReadFull(r, buf[0:])
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
return int64(n), err
|
||||
}
|
||||
|
||||
m.bitLength = uint16(buf[0])<<8 | uint16(buf[1])
|
||||
m.bytes = make([]byte, (int(m.bitLength)+7)/8)
|
||||
|
||||
nn, err := io.ReadFull(r, m.bytes)
|
||||
if err == io.EOF {
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
// remove leading zero bytes from malformed GnuPG encoded MPIs:
|
||||
// https://bugs.gnupg.org/gnupg/issue1853
|
||||
// for _, b := range m.bytes {
|
||||
// if b != 0 {
|
||||
// break
|
||||
// }
|
||||
// m.bytes = m.bytes[1:]
|
||||
// m.bitLength -= 8
|
||||
// }
|
||||
|
||||
return int64(n) + int64(nn), err
|
||||
}
|
||||
|
||||
// SetBig initializes m with the bits from n.
|
||||
func (m *MPI) SetBig(n *big.Int) *MPI {
|
||||
m.bytes = n.Bytes()
|
||||
m.bitLength = uint16(n.BitLen())
|
||||
return m
|
||||
}
|
88
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/oid.go
generated
vendored
Normal file
88
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/oid.go
generated
vendored
Normal file
|
@ -0,0 +1,88 @@
|
|||
// Copyright 2017 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 encoding
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
)
|
||||
|
||||
// OID is used to store a variable-length field with a one-octet size
|
||||
// prefix. See https://tools.ietf.org/html/rfc6637#section-9.
|
||||
type OID struct {
|
||||
bytes []byte
|
||||
}
|
||||
|
||||
const (
|
||||
// maxOID is the maximum number of bytes in a OID.
|
||||
maxOID = 254
|
||||
// reservedOIDLength1 and reservedOIDLength2 are OID lengths that the RFC
|
||||
// specifies are reserved.
|
||||
reservedOIDLength1 = 0
|
||||
reservedOIDLength2 = 0xff
|
||||
)
|
||||
|
||||
// NewOID returns a OID initialized with bytes.
|
||||
func NewOID(bytes []byte) *OID {
|
||||
switch len(bytes) {
|
||||
case reservedOIDLength1, reservedOIDLength2:
|
||||
panic("encoding: NewOID argument length is reserved")
|
||||
default:
|
||||
if len(bytes) > maxOID {
|
||||
panic("encoding: NewOID argment too large")
|
||||
}
|
||||
}
|
||||
|
||||
return &OID{
|
||||
bytes: bytes,
|
||||
}
|
||||
}
|
||||
|
||||
// Bytes returns the decoded data.
|
||||
func (o *OID) Bytes() []byte {
|
||||
return o.bytes
|
||||
}
|
||||
|
||||
// BitLength is the size in bits of the decoded data.
|
||||
func (o *OID) BitLength() uint16 {
|
||||
return uint16(len(o.bytes) * 8)
|
||||
}
|
||||
|
||||
// EncodedBytes returns the encoded data.
|
||||
func (o *OID) EncodedBytes() []byte {
|
||||
return append([]byte{byte(len(o.bytes))}, o.bytes...)
|
||||
}
|
||||
|
||||
// EncodedLength is the size in bytes of the encoded data.
|
||||
func (o *OID) EncodedLength() uint16 {
|
||||
return uint16(1 + len(o.bytes))
|
||||
}
|
||||
|
||||
// ReadFrom reads into b the next OID from r.
|
||||
func (o *OID) ReadFrom(r io.Reader) (int64, error) {
|
||||
var buf [1]byte
|
||||
n, err := io.ReadFull(r, buf[:])
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
return int64(n), err
|
||||
}
|
||||
|
||||
switch buf[0] {
|
||||
case reservedOIDLength1, reservedOIDLength2:
|
||||
return int64(n), errors.UnsupportedError("reserved for future extensions")
|
||||
}
|
||||
|
||||
o.bytes = make([]byte, buf[0])
|
||||
|
||||
nn, err := io.ReadFull(r, o.bytes)
|
||||
if err == io.EOF {
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
return int64(n) + int64(nn), err
|
||||
}
|
375
vendor/github.com/ProtonMail/go-crypto/openpgp/key_generation.go
generated
vendored
Normal file
375
vendor/github.com/ProtonMail/go-crypto/openpgp/key_generation.go
generated
vendored
Normal file
|
@ -0,0 +1,375 @@
|
|||
// Copyright 2011 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 openpgp
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
goerrors "errors"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/ecdh"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/packet"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
)
|
||||
|
||||
// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a
|
||||
// single identity composed of the given full name, comment and email, any of
|
||||
// which may be empty but must not contain any of "()<>\x00".
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) {
|
||||
creationTime := config.Now()
|
||||
keyLifetimeSecs := config.KeyLifetime()
|
||||
|
||||
uid := packet.NewUserId(name, comment, email)
|
||||
if uid == nil {
|
||||
return nil, errors.InvalidArgumentError("user id field contained invalid characters")
|
||||
}
|
||||
|
||||
// Generate a primary signing key
|
||||
primaryPrivRaw, err := newSigner(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
primary := packet.NewSignerPrivateKey(creationTime, primaryPrivRaw)
|
||||
if config != nil && config.V5Keys {
|
||||
primary.UpgradeToV5()
|
||||
}
|
||||
|
||||
isPrimaryId := true
|
||||
selfSignature := &packet.Signature{
|
||||
Version: primary.PublicKey.Version,
|
||||
SigType: packet.SigTypePositiveCert,
|
||||
PubKeyAlgo: primary.PublicKey.PubKeyAlgo,
|
||||
Hash: config.Hash(),
|
||||
CreationTime: creationTime,
|
||||
KeyLifetimeSecs: &keyLifetimeSecs,
|
||||
IssuerKeyId: &primary.PublicKey.KeyId,
|
||||
IssuerFingerprint: primary.PublicKey.Fingerprint,
|
||||
IsPrimaryId: &isPrimaryId,
|
||||
FlagsValid: true,
|
||||
FlagSign: true,
|
||||
FlagCertify: true,
|
||||
MDC: true, // true by default, see 5.8 vs. 5.14
|
||||
AEAD: config.AEAD() != nil,
|
||||
V5Keys: config != nil && config.V5Keys,
|
||||
}
|
||||
|
||||
// Set the PreferredHash for the SelfSignature from the packet.Config.
|
||||
// If it is not the must-implement algorithm from rfc4880bis, append that.
|
||||
selfSignature.PreferredHash = []uint8{hashToHashId(config.Hash())}
|
||||
if config.Hash() != crypto.SHA256 {
|
||||
selfSignature.PreferredHash = append(selfSignature.PreferredHash, hashToHashId(crypto.SHA256))
|
||||
}
|
||||
|
||||
// Likewise for DefaultCipher.
|
||||
selfSignature.PreferredSymmetric = []uint8{uint8(config.Cipher())}
|
||||
if config.Cipher() != packet.CipherAES128 {
|
||||
selfSignature.PreferredSymmetric = append(selfSignature.PreferredSymmetric, uint8(packet.CipherAES128))
|
||||
}
|
||||
|
||||
// And for DefaultMode.
|
||||
selfSignature.PreferredAEAD = []uint8{uint8(config.AEAD().Mode())}
|
||||
if config.AEAD().Mode() != packet.AEADModeEAX {
|
||||
selfSignature.PreferredAEAD = append(selfSignature.PreferredAEAD, uint8(packet.AEADModeEAX))
|
||||
}
|
||||
|
||||
// User ID binding signature
|
||||
err = selfSignature.SignUserId(uid.Id, &primary.PublicKey, primary, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Generate an encryption subkey
|
||||
subPrivRaw, err := newDecrypter(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sub := packet.NewDecrypterPrivateKey(creationTime, subPrivRaw)
|
||||
sub.IsSubkey = true
|
||||
sub.PublicKey.IsSubkey = true
|
||||
if config != nil && config.V5Keys {
|
||||
sub.UpgradeToV5()
|
||||
}
|
||||
|
||||
// NOTE: No KeyLifetimeSecs here, but we will not return this subkey in EncryptionKey()
|
||||
// if the primary/master key has expired.
|
||||
subKey := Subkey{
|
||||
PublicKey: &sub.PublicKey,
|
||||
PrivateKey: sub,
|
||||
Sig: &packet.Signature{
|
||||
Version: primary.PublicKey.Version,
|
||||
CreationTime: creationTime,
|
||||
SigType: packet.SigTypeSubkeyBinding,
|
||||
PubKeyAlgo: primary.PublicKey.PubKeyAlgo,
|
||||
Hash: config.Hash(),
|
||||
FlagsValid: true,
|
||||
FlagEncryptStorage: true,
|
||||
FlagEncryptCommunications: true,
|
||||
IssuerKeyId: &primary.PublicKey.KeyId,
|
||||
},
|
||||
}
|
||||
|
||||
// Subkey binding signature
|
||||
err = subKey.Sig.SignKey(subKey.PublicKey, primary, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Entity{
|
||||
PrimaryKey: &primary.PublicKey,
|
||||
PrivateKey: primary,
|
||||
Identities: map[string]*Identity{
|
||||
uid.Id: &Identity{
|
||||
Name: uid.Id,
|
||||
UserId: uid,
|
||||
SelfSignature: selfSignature,
|
||||
Signatures: []*packet.Signature{selfSignature},
|
||||
},
|
||||
},
|
||||
Subkeys: []Subkey{subKey},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// AddSigningSubkey adds a signing keypair as a subkey to the Entity.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func (e *Entity) AddSigningSubkey(config *packet.Config) error {
|
||||
creationTime := config.Now()
|
||||
keyLifetimeSecs := config.KeyLifetime()
|
||||
|
||||
subPrivRaw, err := newSigner(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sub := packet.NewSignerPrivateKey(creationTime, subPrivRaw)
|
||||
|
||||
subkey := Subkey{
|
||||
PublicKey: &sub.PublicKey,
|
||||
PrivateKey: sub,
|
||||
Sig: &packet.Signature{
|
||||
Version: e.PrimaryKey.Version,
|
||||
CreationTime: creationTime,
|
||||
KeyLifetimeSecs: &keyLifetimeSecs,
|
||||
SigType: packet.SigTypeSubkeyBinding,
|
||||
PubKeyAlgo: e.PrimaryKey.PubKeyAlgo,
|
||||
Hash: config.Hash(),
|
||||
FlagsValid: true,
|
||||
FlagSign: true,
|
||||
IssuerKeyId: &e.PrimaryKey.KeyId,
|
||||
EmbeddedSignature: &packet.Signature{
|
||||
Version: e.PrimaryKey.Version,
|
||||
CreationTime: creationTime,
|
||||
SigType: packet.SigTypePrimaryKeyBinding,
|
||||
PubKeyAlgo: sub.PublicKey.PubKeyAlgo,
|
||||
Hash: config.Hash(),
|
||||
IssuerKeyId: &e.PrimaryKey.KeyId,
|
||||
},
|
||||
},
|
||||
}
|
||||
if config != nil && config.V5Keys {
|
||||
subkey.PublicKey.UpgradeToV5()
|
||||
}
|
||||
|
||||
err = subkey.Sig.EmbeddedSignature.CrossSignKey(subkey.PublicKey, e.PrimaryKey, subkey.PrivateKey, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
subkey.PublicKey.IsSubkey = true
|
||||
subkey.PrivateKey.IsSubkey = true
|
||||
if err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
e.Subkeys = append(e.Subkeys, subkey)
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddEncryptionSubkey adds an encryption keypair as a subkey to the Entity.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func (e *Entity) AddEncryptionSubkey(config *packet.Config) error {
|
||||
creationTime := config.Now()
|
||||
keyLifetimeSecs := config.KeyLifetime()
|
||||
|
||||
subPrivRaw, err := newDecrypter(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sub := packet.NewDecrypterPrivateKey(creationTime, subPrivRaw)
|
||||
|
||||
subkey := Subkey{
|
||||
PublicKey: &sub.PublicKey,
|
||||
PrivateKey: sub,
|
||||
Sig: &packet.Signature{
|
||||
Version: e.PrimaryKey.Version,
|
||||
CreationTime: creationTime,
|
||||
KeyLifetimeSecs: &keyLifetimeSecs,
|
||||
SigType: packet.SigTypeSubkeyBinding,
|
||||
PubKeyAlgo: e.PrimaryKey.PubKeyAlgo,
|
||||
Hash: config.Hash(),
|
||||
FlagsValid: true,
|
||||
FlagEncryptStorage: true,
|
||||
FlagEncryptCommunications: true,
|
||||
IssuerKeyId: &e.PrimaryKey.KeyId,
|
||||
},
|
||||
}
|
||||
if config != nil && config.V5Keys {
|
||||
subkey.PublicKey.UpgradeToV5()
|
||||
}
|
||||
|
||||
subkey.PublicKey.IsSubkey = true
|
||||
subkey.PrivateKey.IsSubkey = true
|
||||
if err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
e.Subkeys = append(e.Subkeys, subkey)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Generates a signing key
|
||||
func newSigner(config *packet.Config) (signer crypto.Signer, err error) {
|
||||
switch config.PublicKeyAlgorithm() {
|
||||
case packet.PubKeyAlgoRSA:
|
||||
bits := config.RSAModulusBits()
|
||||
if bits < 1024 {
|
||||
return nil, errors.InvalidArgumentError("bits must be >= 1024")
|
||||
}
|
||||
if config != nil && len(config.RSAPrimes) >= 2 {
|
||||
primes := config.RSAPrimes[0:2]
|
||||
config.RSAPrimes = config.RSAPrimes[2:]
|
||||
return generateRSAKeyWithPrimes(config.Random(), 2, bits, primes)
|
||||
}
|
||||
return rsa.GenerateKey(config.Random(), bits)
|
||||
case packet.PubKeyAlgoEdDSA:
|
||||
_, priv, err := ed25519.GenerateKey(config.Random())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &priv, nil
|
||||
default:
|
||||
return nil, errors.InvalidArgumentError("unsupported public key algorithm")
|
||||
}
|
||||
}
|
||||
|
||||
// Generates an encryption/decryption key
|
||||
func newDecrypter(config *packet.Config) (decrypter interface{}, err error) {
|
||||
switch config.PublicKeyAlgorithm() {
|
||||
case packet.PubKeyAlgoRSA:
|
||||
bits := config.RSAModulusBits()
|
||||
if bits < 1024 {
|
||||
return nil, errors.InvalidArgumentError("bits must be >= 1024")
|
||||
}
|
||||
if config != nil && len(config.RSAPrimes) >= 2 {
|
||||
primes := config.RSAPrimes[0:2]
|
||||
config.RSAPrimes = config.RSAPrimes[2:]
|
||||
return generateRSAKeyWithPrimes(config.Random(), 2, bits, primes)
|
||||
}
|
||||
return rsa.GenerateKey(config.Random(), bits)
|
||||
case packet.PubKeyAlgoEdDSA:
|
||||
fallthrough // When passing EdDSA, we generate an ECDH subkey
|
||||
case packet.PubKeyAlgoECDH:
|
||||
var kdf = ecdh.KDF{
|
||||
Hash: algorithm.SHA512,
|
||||
Cipher: algorithm.AES256,
|
||||
}
|
||||
return ecdh.X25519GenerateKey(config.Random(), kdf)
|
||||
default:
|
||||
return nil, errors.InvalidArgumentError("unsupported public key algorithm")
|
||||
}
|
||||
}
|
||||
|
||||
var bigOne = big.NewInt(1)
|
||||
|
||||
// generateRSAKeyWithPrimes generates a multi-prime RSA keypair of the
|
||||
// given bit size, using the given random source and prepopulated primes.
|
||||
func generateRSAKeyWithPrimes(random io.Reader, nprimes int, bits int, prepopulatedPrimes []*big.Int) (*rsa.PrivateKey, error) {
|
||||
priv := new(rsa.PrivateKey)
|
||||
priv.E = 65537
|
||||
|
||||
if nprimes < 2 {
|
||||
return nil, goerrors.New("generateRSAKeyWithPrimes: nprimes must be >= 2")
|
||||
}
|
||||
|
||||
if bits < 1024 {
|
||||
return nil, goerrors.New("generateRSAKeyWithPrimes: bits must be >= 1024")
|
||||
}
|
||||
|
||||
primes := make([]*big.Int, nprimes)
|
||||
|
||||
NextSetOfPrimes:
|
||||
for {
|
||||
todo := bits
|
||||
// crypto/rand should set the top two bits in each prime.
|
||||
// Thus each prime has the form
|
||||
// p_i = 2^bitlen(p_i) × 0.11... (in base 2).
|
||||
// And the product is:
|
||||
// P = 2^todo × α
|
||||
// where α is the product of nprimes numbers of the form 0.11...
|
||||
//
|
||||
// If α < 1/2 (which can happen for nprimes > 2), we need to
|
||||
// shift todo to compensate for lost bits: the mean value of 0.11...
|
||||
// is 7/8, so todo + shift - nprimes * log2(7/8) ~= bits - 1/2
|
||||
// will give good results.
|
||||
if nprimes >= 7 {
|
||||
todo += (nprimes - 2) / 5
|
||||
}
|
||||
for i := 0; i < nprimes; i++ {
|
||||
var err error
|
||||
if len(prepopulatedPrimes) == 0 {
|
||||
primes[i], err = rand.Prime(random, todo/(nprimes-i))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
primes[i] = prepopulatedPrimes[0]
|
||||
prepopulatedPrimes = prepopulatedPrimes[1:]
|
||||
}
|
||||
|
||||
todo -= primes[i].BitLen()
|
||||
}
|
||||
|
||||
// Make sure that primes is pairwise unequal.
|
||||
for i, prime := range primes {
|
||||
for j := 0; j < i; j++ {
|
||||
if prime.Cmp(primes[j]) == 0 {
|
||||
continue NextSetOfPrimes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
n := new(big.Int).Set(bigOne)
|
||||
totient := new(big.Int).Set(bigOne)
|
||||
pminus1 := new(big.Int)
|
||||
for _, prime := range primes {
|
||||
n.Mul(n, prime)
|
||||
pminus1.Sub(prime, bigOne)
|
||||
totient.Mul(totient, pminus1)
|
||||
}
|
||||
if n.BitLen() != bits {
|
||||
// This should never happen for nprimes == 2 because
|
||||
// crypto/rand should set the top two bits in each prime.
|
||||
// For nprimes > 2 we hope it does not happen often.
|
||||
continue NextSetOfPrimes
|
||||
}
|
||||
|
||||
priv.D = new(big.Int)
|
||||
e := big.NewInt(int64(priv.E))
|
||||
ok := priv.D.ModInverse(e, totient)
|
||||
|
||||
if ok != nil {
|
||||
priv.Primes = primes
|
||||
priv.N = n
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
priv.Precompute()
|
||||
return priv, nil
|
||||
}
|
|
@ -5,13 +5,13 @@
|
|||
package openpgp
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
goerrors "errors"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/openpgp/armor"
|
||||
"golang.org/x/crypto/openpgp/errors"
|
||||
"golang.org/x/crypto/openpgp/packet"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/armor"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/packet"
|
||||
)
|
||||
|
||||
// PublicKeyType is the armor type for a PGP public key.
|
||||
|
@ -71,9 +71,9 @@ type KeyRing interface {
|
|||
DecryptionKeys() []Key
|
||||
}
|
||||
|
||||
// primaryIdentity returns the Identity marked as primary or the first identity
|
||||
// PrimaryIdentity returns the Identity marked as primary or the first identity
|
||||
// if none are so marked.
|
||||
func (e *Entity) primaryIdentity() *Identity {
|
||||
func (e *Entity) PrimaryIdentity() *Identity {
|
||||
var firstIdentity *Identity
|
||||
for _, ident := range e.Identities {
|
||||
if firstIdentity == nil {
|
||||
|
@ -86,18 +86,24 @@ func (e *Entity) primaryIdentity() *Identity {
|
|||
return firstIdentity
|
||||
}
|
||||
|
||||
// encryptionKey returns the best candidate Key for encrypting a message to the
|
||||
// EncryptionKey returns the best candidate Key for encrypting a message to the
|
||||
// given Entity.
|
||||
func (e *Entity) encryptionKey(now time.Time) (Key, bool) {
|
||||
candidateSubkey := -1
|
||||
func (e *Entity) EncryptionKey(now time.Time) (Key, bool) {
|
||||
// Fail to find any encryption key if the primary key has expired.
|
||||
i := e.PrimaryIdentity()
|
||||
primaryKeyExpired := e.PrimaryKey.KeyExpired(i.SelfSignature, now)
|
||||
if primaryKeyExpired {
|
||||
return Key{}, false
|
||||
}
|
||||
|
||||
// Iterate the keys to find the newest key
|
||||
// Iterate the keys to find the newest, unexpired one
|
||||
candidateSubkey := -1
|
||||
var maxTime time.Time
|
||||
for i, subkey := range e.Subkeys {
|
||||
if subkey.Sig.FlagsValid &&
|
||||
subkey.Sig.FlagEncryptCommunications &&
|
||||
subkey.PublicKey.PubKeyAlgo.CanEncrypt() &&
|
||||
!subkey.Sig.KeyExpired(now) &&
|
||||
!subkey.PublicKey.KeyExpired(subkey.Sig, now) &&
|
||||
(maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) {
|
||||
candidateSubkey = i
|
||||
maxTime = subkey.Sig.CreationTime
|
||||
|
@ -112,30 +118,44 @@ func (e *Entity) encryptionKey(now time.Time) (Key, bool) {
|
|||
// If we don't have any candidate subkeys for encryption and
|
||||
// the primary key doesn't have any usage metadata then we
|
||||
// assume that the primary key is ok. Or, if the primary key is
|
||||
// marked as ok to encrypt to, then we can obviously use it.
|
||||
i := e.primaryIdentity()
|
||||
// marked as ok to encrypt with, then we can obviously use it.
|
||||
// Also, check expiry again just to be safe.
|
||||
if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptCommunications &&
|
||||
e.PrimaryKey.PubKeyAlgo.CanEncrypt() &&
|
||||
!i.SelfSignature.KeyExpired(now) {
|
||||
e.PrimaryKey.PubKeyAlgo.CanEncrypt() && !primaryKeyExpired {
|
||||
return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true
|
||||
}
|
||||
|
||||
// This Entity appears to be signing only.
|
||||
return Key{}, false
|
||||
}
|
||||
|
||||
// signingKey return the best candidate Key for signing a message with this
|
||||
// SigningKey return the best candidate Key for signing a message with this
|
||||
// Entity.
|
||||
func (e *Entity) signingKey(now time.Time) (Key, bool) {
|
||||
candidateSubkey := -1
|
||||
func (e *Entity) SigningKey(now time.Time) (Key, bool) {
|
||||
return e.SigningKeyById(now, 0)
|
||||
}
|
||||
|
||||
for i, subkey := range e.Subkeys {
|
||||
// SigningKeyById return the Key for signing a message with this
|
||||
// Entity and keyID.
|
||||
func (e *Entity) SigningKeyById(now time.Time, id uint64) (Key, bool) {
|
||||
// Fail to find any signing key if the primary key has expired.
|
||||
i := e.PrimaryIdentity()
|
||||
primaryKeyExpired := e.PrimaryKey.KeyExpired(i.SelfSignature, now)
|
||||
if primaryKeyExpired {
|
||||
return Key{}, false
|
||||
}
|
||||
|
||||
// Iterate the keys to find the newest, unexpired one
|
||||
candidateSubkey := -1
|
||||
var maxTime time.Time
|
||||
for idx, subkey := range e.Subkeys {
|
||||
if subkey.Sig.FlagsValid &&
|
||||
subkey.Sig.FlagSign &&
|
||||
subkey.PublicKey.PubKeyAlgo.CanSign() &&
|
||||
!subkey.Sig.KeyExpired(now) {
|
||||
candidateSubkey = i
|
||||
break
|
||||
!subkey.PublicKey.KeyExpired(subkey.Sig, now) &&
|
||||
(maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) &&
|
||||
(id == 0 || subkey.PrivateKey.KeyId == id) {
|
||||
candidateSubkey = idx
|
||||
maxTime = subkey.Sig.CreationTime
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,13 +165,15 @@ func (e *Entity) signingKey(now time.Time) (Key, bool) {
|
|||
}
|
||||
|
||||
// If we have no candidate subkey then we assume that it's ok to sign
|
||||
// with the primary key.
|
||||
i := e.primaryIdentity()
|
||||
// with the primary key. Or, if the primary key is marked as ok to
|
||||
// sign with, then we can use it. Also, check expiry again just to be safe.
|
||||
if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagSign &&
|
||||
!i.SelfSignature.KeyExpired(now) {
|
||||
e.PrimaryKey.PubKeyAlgo.CanSign() && !primaryKeyExpired &&
|
||||
(id == 0 || e.PrivateKey.KeyId == id) {
|
||||
return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true
|
||||
}
|
||||
|
||||
// No keys with a valid Signing Flag or no keys matched the id passed in
|
||||
return Key{}, false
|
||||
}
|
||||
|
||||
|
@ -420,11 +442,14 @@ func addUserID(e *Entity, packets *packet.Reader, pkt *packet.UserId) error {
|
|||
break
|
||||
}
|
||||
|
||||
if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId {
|
||||
if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.CheckKeyIdOrFingerprint(e.PrimaryKey) {
|
||||
if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil {
|
||||
return errors.StructuralError("user ID self-signature invalid: " + err.Error())
|
||||
}
|
||||
identity.SelfSignature = sig
|
||||
if identity.SelfSignature == nil || sig.CreationTime.After(identity.SelfSignature.CreationTime) {
|
||||
identity.SelfSignature = sig
|
||||
}
|
||||
identity.Signatures = append(identity.Signatures, sig)
|
||||
e.Identities[pkt.Id] = identity
|
||||
} else {
|
||||
identity.Signatures = append(identity.Signatures, sig)
|
||||
|
@ -465,7 +490,6 @@ func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *p
|
|||
case packet.SigTypeSubkeyRevocation:
|
||||
subKey.Sig = sig
|
||||
case packet.SigTypeSubkeyBinding:
|
||||
|
||||
if shouldReplaceSubkeySig(subKey.Sig, sig) {
|
||||
subKey.Sig = sig
|
||||
}
|
||||
|
@ -497,99 +521,30 @@ func shouldReplaceSubkeySig(existingSig, potentialNewSig *packet.Signature) bool
|
|||
return potentialNewSig.CreationTime.After(existingSig.CreationTime)
|
||||
}
|
||||
|
||||
const defaultRSAKeyBits = 2048
|
||||
|
||||
// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a
|
||||
// single identity composed of the given full name, comment and email, any of
|
||||
// which may be empty but must not contain any of "()<>\x00".
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) {
|
||||
creationTime := config.Now()
|
||||
|
||||
bits := defaultRSAKeyBits
|
||||
if config != nil && config.RSABits != 0 {
|
||||
bits = config.RSABits
|
||||
}
|
||||
|
||||
uid := packet.NewUserId(name, comment, email)
|
||||
if uid == nil {
|
||||
return nil, errors.InvalidArgumentError("user id field contained invalid characters")
|
||||
}
|
||||
signingPriv, err := rsa.GenerateKey(config.Random(), bits)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
encryptingPriv, err := rsa.GenerateKey(config.Random(), bits)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
e := &Entity{
|
||||
PrimaryKey: packet.NewRSAPublicKey(creationTime, &signingPriv.PublicKey),
|
||||
PrivateKey: packet.NewRSAPrivateKey(creationTime, signingPriv),
|
||||
Identities: make(map[string]*Identity),
|
||||
}
|
||||
isPrimaryId := true
|
||||
e.Identities[uid.Id] = &Identity{
|
||||
Name: uid.Id,
|
||||
UserId: uid,
|
||||
SelfSignature: &packet.Signature{
|
||||
CreationTime: creationTime,
|
||||
SigType: packet.SigTypePositiveCert,
|
||||
PubKeyAlgo: packet.PubKeyAlgoRSA,
|
||||
Hash: config.Hash(),
|
||||
IsPrimaryId: &isPrimaryId,
|
||||
FlagsValid: true,
|
||||
FlagSign: true,
|
||||
FlagCertify: true,
|
||||
IssuerKeyId: &e.PrimaryKey.KeyId,
|
||||
},
|
||||
}
|
||||
err = e.Identities[uid.Id].SelfSignature.SignUserId(uid.Id, e.PrimaryKey, e.PrivateKey, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If the user passes in a DefaultHash via packet.Config,
|
||||
// set the PreferredHash for the SelfSignature.
|
||||
if config != nil && config.DefaultHash != 0 {
|
||||
e.Identities[uid.Id].SelfSignature.PreferredHash = []uint8{hashToHashId(config.DefaultHash)}
|
||||
}
|
||||
|
||||
// Likewise for DefaultCipher.
|
||||
if config != nil && config.DefaultCipher != 0 {
|
||||
e.Identities[uid.Id].SelfSignature.PreferredSymmetric = []uint8{uint8(config.DefaultCipher)}
|
||||
}
|
||||
|
||||
e.Subkeys = make([]Subkey, 1)
|
||||
e.Subkeys[0] = Subkey{
|
||||
PublicKey: packet.NewRSAPublicKey(creationTime, &encryptingPriv.PublicKey),
|
||||
PrivateKey: packet.NewRSAPrivateKey(creationTime, encryptingPriv),
|
||||
Sig: &packet.Signature{
|
||||
CreationTime: creationTime,
|
||||
SigType: packet.SigTypeSubkeyBinding,
|
||||
PubKeyAlgo: packet.PubKeyAlgoRSA,
|
||||
Hash: config.Hash(),
|
||||
FlagsValid: true,
|
||||
FlagEncryptStorage: true,
|
||||
FlagEncryptCommunications: true,
|
||||
IssuerKeyId: &e.PrimaryKey.KeyId,
|
||||
},
|
||||
}
|
||||
e.Subkeys[0].PublicKey.IsSubkey = true
|
||||
e.Subkeys[0].PrivateKey.IsSubkey = true
|
||||
err = e.Subkeys[0].Sig.SignKey(e.Subkeys[0].PublicKey, e.PrivateKey, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return e, nil
|
||||
}
|
||||
|
||||
// SerializePrivate serializes an Entity, including private key material, but
|
||||
// excluding signatures from other entities, to the given Writer.
|
||||
// Identities and subkeys are re-signed in case they changed since NewEntry.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) {
|
||||
if e.PrivateKey.Dummy() {
|
||||
return errors.ErrDummyPrivateKey("dummy private key cannot re-sign identities")
|
||||
}
|
||||
return e.serializePrivate(w, config, true)
|
||||
}
|
||||
|
||||
// SerializePrivateWithoutSigning serializes an Entity, including private key
|
||||
// material, but excluding signatures from other entities, to the given Writer.
|
||||
// Self-signatures of identities and subkeys are not re-signed. This is useful
|
||||
// when serializing GNU dummy keys, among other things.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func (e *Entity) SerializePrivateWithoutSigning(w io.Writer, config *packet.Config) (err error) {
|
||||
return e.serializePrivate(w, config, false)
|
||||
}
|
||||
|
||||
func (e *Entity) serializePrivate(w io.Writer, config *packet.Config, reSign bool) (err error) {
|
||||
if e.PrivateKey == nil {
|
||||
return goerrors.New("openpgp: private key is missing")
|
||||
}
|
||||
err = e.PrivateKey.Serialize(w)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -599,9 +554,11 @@ func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config)
|
||||
if err != nil {
|
||||
return
|
||||
if reSign {
|
||||
err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
err = ident.SelfSignature.Serialize(w)
|
||||
if err != nil {
|
||||
|
@ -613,9 +570,18 @@ func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
|
||||
if err != nil {
|
||||
return
|
||||
if reSign {
|
||||
err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if subkey.Sig.EmbeddedSignature != nil {
|
||||
err = subkey.Sig.EmbeddedSignature.CrossSignKey(subkey.PublicKey, e.PrimaryKey,
|
||||
subkey.PrivateKey, config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
err = subkey.Sig.Serialize(w)
|
||||
if err != nil {
|
||||
|
@ -637,10 +603,6 @@ func (e *Entity) Serialize(w io.Writer) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ident.SelfSignature.Serialize(w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, sig := range ident.Signatures {
|
||||
err = sig.Serialize(w)
|
||||
if err != nil {
|
||||
|
@ -679,6 +641,7 @@ func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Co
|
|||
}
|
||||
|
||||
sig := &packet.Signature{
|
||||
Version: signer.PrivateKey.Version,
|
||||
SigType: packet.SigTypeGenericCert,
|
||||
PubKeyAlgo: signer.PrivateKey.PubKeyAlgo,
|
||||
Hash: config.Hash(),
|
||||
|
@ -691,3 +654,54 @@ func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Co
|
|||
ident.Signatures = append(ident.Signatures, sig)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RevokeKey generates a key revocation signature (packet.SigTypeKeyRevocation) with the
|
||||
// specified reason code and text (RFC4880 section-5.2.3.23).
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func (e *Entity) RevokeKey(reason packet.ReasonForRevocation, reasonText string, config *packet.Config) error {
|
||||
reasonCode := uint8(reason)
|
||||
revSig := &packet.Signature{
|
||||
Version: e.PrimaryKey.Version,
|
||||
CreationTime: config.Now(),
|
||||
SigType: packet.SigTypeKeyRevocation,
|
||||
PubKeyAlgo: packet.PubKeyAlgoRSA,
|
||||
Hash: config.Hash(),
|
||||
RevocationReason: &reasonCode,
|
||||
RevocationReasonText: reasonText,
|
||||
IssuerKeyId: &e.PrimaryKey.KeyId,
|
||||
}
|
||||
|
||||
if err := revSig.RevokeKey(e.PrimaryKey, e.PrivateKey, config); err != nil {
|
||||
return err
|
||||
}
|
||||
e.Revocations = append(e.Revocations, revSig)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RevokeSubkey generates a subkey revocation signature (packet.SigTypeSubkeyRevocation) for
|
||||
// a subkey with the specified reason code and text (RFC4880 section-5.2.3.23).
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func (e *Entity) RevokeSubkey(sk *Subkey, reason packet.ReasonForRevocation, reasonText string, config *packet.Config) error {
|
||||
if err := e.PrimaryKey.VerifyKeySignature(sk.PublicKey, sk.Sig); err != nil {
|
||||
return errors.InvalidArgumentError("given subkey is not associated with this key")
|
||||
}
|
||||
|
||||
reasonCode := uint8(reason)
|
||||
revSig := &packet.Signature{
|
||||
Version: e.PrimaryKey.Version,
|
||||
CreationTime: config.Now(),
|
||||
SigType: packet.SigTypeSubkeyRevocation,
|
||||
PubKeyAlgo: packet.PubKeyAlgoRSA,
|
||||
Hash: config.Hash(),
|
||||
RevocationReason: &reasonCode,
|
||||
RevocationReasonText: reasonText,
|
||||
IssuerKeyId: &e.PrimaryKey.KeyId,
|
||||
}
|
||||
|
||||
if err := revSig.RevokeKey(sk.PublicKey, e.PrivateKey, config); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sk.Sig = revSig
|
||||
return nil
|
||||
}
|
336
vendor/github.com/ProtonMail/go-crypto/openpgp/keys_test_data.go
generated
vendored
Normal file
336
vendor/github.com/ProtonMail/go-crypto/openpgp/keys_test_data.go
generated
vendored
Normal file
|
@ -0,0 +1,336 @@
|
|||
package openpgp
|
||||
|
||||
const expiringKeyHex = "c6c04d0451d0c680010800abbb021fd03ffc4e96618901180c3fdcb060ee69eeead97b91256d11420d80b5f1b51930248044130bd300605cf8a05b7a40d3d8cfb0a910be2e3db50dcd50a9c54064c2a5550801daa834ff4480b33d3d3ca495ff8a4e84a886977d17d998f881241a874083d8b995beab555b6d22b8a4817ab17ac3e7304f7d4d2c05c495fb2218348d3bc13651db1d92732e368a9dd7dcefa6eddff30b94706a9aaee47e9d39321460b740c59c6fc3c2fd8ab6c0fb868cb87c0051f0321301fe0f0e1820b15e7fb7063395769b525005c7e30a7ce85984f5cac00504e7b4fdc45d74958de8388436fd5c7ba9ea121f1c851b5911dd1b47a14d81a09e92ef37721e2325b6790011010001cd00c2c07b041001080025050251d0c680050900278d00060b09070803020415080a0203160201021901021b03021e01000a0910e7b484133a890a35ae4b0800a1beb82e7f28eaf5273d6af9d3391314f6280b2b624eaca2851f89a9ebcaf80ac589ebd509f168bc4322106ca2e2ce77a76e071a3c7444787d65216b5f05e82c77928860b92aace3b7d0327db59492f422eb9dfab7249266d37429870b091a98aba8724c2259ebf8f85093f21255eafa75aa841e31d94f2ac891b9755fed455e539044ee69fc47950b80e003fc9f298d695660f28329eaa38037c367efde1727458e514faf990d439a21461b719edaddf9296d3d0647b43ca56cb8dbf63b4fcf8b9968e7928c463470fab3b98e44d0d95645062f94b2d04fe56bd52822b71934db8ce845622c40b92fcbe765a142e7f38b61a6aa9606c8e8858dcd3b6eb1894acec04d0451d1f06b01080088bea67444e1789390e7c0335c86775502d58ec783d99c8ef4e06de235ed3dd4b0467f6f358d818c7d8989d43ec6d69fcbc8c32632d5a1b605e3fa8e41d695fcdcaa535936cd0157f9040dce362519803b908eafe838bb13216c885c6f93e9e8d5745607f0d062322085d6bdc760969149a8ff8dd9f5c18d9bfe2e6f63a06e17694cf1f67587c6fb70e9aebf90ffc528ca3b615ac7c9d4a21ea4f7c06f2e98fbbd90a859b8608bf9ea638e3a54289ce44c283110d0c45fa458de6251cd6e7baf71f80f12c8978340490fd90c92b81736ae902ed958e478dceae2835953d189c45d182aff02ea2be61b81d8e94430f041d638647b43e2fcb45fd512fbf5068b810011010001c2c06504180108000f050251d1f06b050900081095021b0c000a0910e7b484133a890a35e63407fe2ec88d6d1e6c9ce7553ece0cb2524747217bad29f251d33df84599ffcc900141a355abd62126800744068a5e05dc167056aa9205273dc7765a2ed49db15c2a83b8d6e6429c902136f1e12229086c1c10c0053242c2a4ae1930db58163387a48cad64607ff2153c320e42843dec28e3fce90e7399d63ac0affa2fee1f0adc0953c89eb3f46ef1d6c04328ed13b491669d5120a3782e3ffb7c69575fb77eebd108794f4dda9d34be2bae57e8e59ec8ebfda2f6f06104b2321be408ea146e2db482b00c5055c8618de36ac9716f80da2617e225556d0fce61b01c8cea2d1e0ea982c31711060ca370f2739366e1e708f38405d784b49d16a26cf62d152eae734327cec04d0451d1f07b010800d5af91c5e7c2fd8951c8d254eab0c97cdcb66822f868b79b78c366255059a68fd74ebca9adb9b970cd9e586690e6e0756705432306878c897b10a4b4ca0005966f99ac8fa4e6f9caf54bf8e53844544beee9872a7ac64c119cf1393d96e674254b661f61ee975633d0e8a8672531edb6bb8e211204e7754a9efa802342118eee850beea742bac95a3f706cc2024cf6037a308bb68162b2f53b9a6346a96e6d31871a2456186e24a1c7a82b82ac04afdfd57cd7fb9ba77a9c760d40b76a170f7be525e5fb6a9848cc726e806187710d9b190387df28700f321f988a392899f93815cc937f309129eb94d5299c5547cb2c085898e6639496e70d746c9d3fb9881d0011010001c2c06504180108000f050251d1f07b050900266305021b0c000a0910e7b484133a890a35bff207fd10dfe8c4a6ea1dd30568012b6fd6891a763c87ad0f7a1d112aad9e8e3239378a3b85588c235865bac2e614348cb4f216d7217f53b3ef48c192e0a4d31d64d7bfa5faccf21155965fa156e887056db644a05ad08a85cc6152d1377d9e37b46f4ff462bbe68ace2dc586ef90070314576c985d8037c2ba63f0a7dc17a62e15bd77e88bc61d9d00858979709f12304264a4cf4225c5cf86f12c8e19486cb9cdcc69f18f027e5f16f4ca8b50e28b3115eaff3a345acd21f624aef81f6ede515c1b55b26b84c1e32264754eab672d5489b287e7277ea855e0a5ff2aa9e8b8c76d579a964ec225255f4d57bf66639ccb34b64798846943e162a41096a7002ca21c7f56"
|
||||
const subkeyUsageHex = "988d04533a52bc010400d26af43085558f65b9e7dbc90cb9238015259aed5e954637adcfa2181548b2d0b60c65f1f42ec5081cbf1bc0a8aa4900acfb77070837c58f26012fbce297d70afe96e759ad63531f0037538e70dbf8e384569b9720d99d8eb39d8d0a2947233ed242436cb6ac7dfe74123354b3d0119b5c235d3dd9c9d6c004f8ffaf67ad8583001101000188b7041f010200210502533b8552170c8001ce094aa433f7040bb2ddf0be3893cb843d0fe70c020700000a0910a42704b92866382aa98404009d63d916a27543da4221c60087c33f1c44bec9998c5438018ed370cca4962876c748e94b73eb39c58eb698063f3fd6346d58dd2a11c0247934c4a9d71f24754f7468f96fb24c3e791dd2392b62f626148ad724189498cbf993db2df7c0cdc2d677c35da0f16cb16c9ce7c33b4de65a4a91b1d21a130ae9cc26067718910ef8e2b417556d627261203c756d627261407379642e65642e61753e88b80413010200220502533a52bc021b03060b090807030206150802090a0b0416020301021e01021780000a0910a42704b92866382a47840400c0c2bd04f5fca586de408b395b3c280a278259c93eaaa8b79a53b97003f8ed502a8a00446dd9947fb462677e4fcac0dac2f0701847d15130aadb6cd9e0705ea0cf5f92f129136c7be21a718d46c8e641eb7f044f2adae573e11ae423a0a9ca51324f03a8a2f34b91fa40c3cc764bee4dccadedb54c768ba0469b683ea53f1c29b88d04533a52bc01040099c92a5d6f8b744224da27bc2369127c35269b58bec179de6bbc038f749344222f85a31933224f26b70243c4e4b2d242f0c4777eaef7b5502f9dad6d8bf3aaeb471210674b74de2d7078af497d55f5cdad97c7bedfbc1b41e8065a97c9c3d344b21fc81d27723af8e374bc595da26ea242dccb6ae497be26eea57e563ed517e90011010001889f0418010200090502533a52bc021b0c000a0910a42704b92866382afa1403ff70284c2de8a043ff51d8d29772602fa98009b7861c540535f874f2c230af8caf5638151a636b21f8255003997ccd29747fdd06777bb24f9593bd7d98a3e887689bf902f999915fcc94625ae487e5d13e6616f89090ebc4fdc7eb5cad8943e4056995bb61c6af37f8043016876a958ec7ebf39c43d20d53b7f546cfa83e8d2604b88d04533b8283010400c0b529316dbdf58b4c54461e7e669dc11c09eb7f73819f178ccd4177b9182b91d138605fcf1e463262fabefa73f94a52b5e15d1904635541c7ea540f07050ce0fb51b73e6f88644cec86e91107c957a114f69554548a85295d2b70bd0b203992f76eb5d493d86d9eabcaa7ef3fc7db7e458438db3fcdb0ca1cc97c638439a9170011010001889f0418010200090502533b8283021b0c000a0910a42704b92866382adc6d0400cfff6258485a21675adb7a811c3e19ebca18851533f75a7ba317950b9997fda8d1a4c8c76505c08c04b6c2cc31dc704d33da36a21273f2b388a1a706f7c3378b66d887197a525936ed9a69acb57fe7f718133da85ec742001c5d1864e9c6c8ea1b94f1c3759cebfd93b18606066c063a63be86085b7e37bdbc65f9a915bf084bb901a204533b85cd110400aed3d2c52af2b38b5b67904b0ef73d6dd7aef86adb770e2b153cd22489654dcc91730892087bb9856ae2d9f7ed1eb48f214243fe86bfe87b349ebd7c30e630e49c07b21fdabf78b7a95c8b7f969e97e3d33f2e074c63552ba64a2ded7badc05ce0ea2be6d53485f6900c7860c7aa76560376ce963d7271b9b54638a4028b573f00a0d8854bfcdb04986141568046202192263b9b67350400aaa1049dbc7943141ef590a70dcb028d730371d92ea4863de715f7f0f16d168bd3dc266c2450457d46dcbbf0b071547e5fbee7700a820c3750b236335d8d5848adb3c0da010e998908dfd93d961480084f3aea20b247034f8988eccb5546efaa35a92d0451df3aaf1aee5aa36a4c4d462c760ecd9cebcabfbe1412b1f21450f203fd126687cd486496e971a87fd9e1a8a765fe654baa219a6871ab97768596ab05c26c1aeea8f1a2c72395a58dbc12ef9640d2b95784e974a4d2d5a9b17c25fedacfe551bda52602de8f6d2e48443f5dd1a2a2a8e6a5e70ecdb88cd6e766ad9745c7ee91d78cc55c3d06536b49c3fee6c3d0b6ff0fb2bf13a314f57c953b8f4d93bf88e70418010200090502533b85cd021b0200520910a42704b92866382a47200419110200060502533b85cd000a091042ce2c64bc0ba99214b2009e26b26852c8b13b10c35768e40e78fbbb48bd084100a0c79d9ea0844fa5853dd3c85ff3ecae6f2c9dd6c557aa04008bbbc964cd65b9b8299d4ebf31f41cc7264b8cf33a00e82c5af022331fac79efc9563a822497ba012953cefe2629f1242fcdcb911dbb2315985bab060bfd58261ace3c654bdbbe2e8ed27a46e836490145c86dc7bae15c011f7e1ffc33730109b9338cd9f483e7cef3d2f396aab5bd80efb6646d7e778270ee99d934d187dd98"
|
||||
const revokedKeyHex = "988d045331ce82010400c4fdf7b40a5477f206e6ee278eaef888ca73bf9128a9eef9f2f1ddb8b7b71a4c07cfa241f028a04edb405e4d916c61d6beabc333813dc7b484d2b3c52ee233c6a79b1eea4e9cc51596ba9cd5ac5aeb9df62d86ea051055b79d03f8a4fa9f38386f5bd17529138f3325d46801514ea9047977e0829ed728e68636802796801be10011010001889f04200102000905025331d0e3021d03000a0910a401d9f09a34f7c042aa040086631196405b7e6af71026b88e98012eab44aa9849f6ef3fa930c7c9f23deaedba9db1538830f8652fb7648ec3fcade8dbcbf9eaf428e83c6cbcc272201bfe2fbb90d41963397a7c0637a1a9d9448ce695d9790db2dc95433ad7be19eb3de72dacf1d6db82c3644c13eae2a3d072b99bb341debba012c5ce4006a7d34a1f4b94b444526567205265766f6b657220283c52656727732022424d204261726973746122204b657920262530305c303e5c29203c72656740626d626172697374612e636f2e61753e88b704130102002205025331ce82021b03060b090807030206150802090a0b0416020301021e01021780000a0910a401d9f09a34f7c0019c03f75edfbeb6a73e7225ad3cc52724e2872e04260d7daf0d693c170d8c4b243b8767bc7785763533febc62ec2600c30603c433c095453ede59ff2fcabeb84ce32e0ed9d5cf15ffcbc816202b64370d4d77c1e9077d74e94a16fb4fa2e5bec23a56d7a73cf275f91691ae1801a976fcde09e981a2f6327ac27ea1fecf3185df0d56889c04100102000605025331cfb5000a0910fe9645554e8266b64b4303fc084075396674fb6f778d302ac07cef6bc0b5d07b66b2004c44aef711cbac79617ef06d836b4957522d8772dd94bf41a2f4ac8b1ee6d70c57503f837445a74765a076d07b829b8111fc2a918423ddb817ead7ca2a613ef0bfb9c6b3562aec6c3cf3c75ef3031d81d95f6563e4cdcc9960bcb386c5d757b104fcca5fe11fc709df884604101102000605025331cfe7000a09107b15a67f0b3ddc0317f6009e360beea58f29c1d963a22b962b80788c3fa6c84e009d148cfde6b351469b8eae91187eff07ad9d08fcaab88d045331ce820104009f25e20a42b904f3fa555530fe5c46737cf7bd076c35a2a0d22b11f7e0b61a69320b768f4a80fe13980ce380d1cfc4a0cd8fbe2d2e2ef85416668b77208baa65bf973fe8e500e78cc310d7c8705cdb34328bf80e24f0385fce5845c33bc7943cf6b11b02348a23da0bf6428e57c05135f2dc6bd7c1ce325d666d5a5fd2fd5e410011010001889f04180102000905025331ce82021b0c000a0910a401d9f09a34f7c0418003fe34feafcbeaef348a800a0d908a7a6809cc7304017d820f70f0474d5e23cb17e38b67dc6dca282c6ca00961f4ec9edf2738d0f087b1d81e4871ef08e1798010863afb4eac4c44a376cb343be929c5be66a78cfd4456ae9ec6a99d97f4e1c3ff3583351db2147a65c0acef5c003fb544ab3a2e2dc4d43646f58b811a6c3a369d1f"
|
||||
const revokedSubkeyHex = "988d04533121f6010400aefc803a3e4bb1a61c86e8a86d2726c6a43e0079e9f2713f1fa017e9854c83877f4aced8e331d675c67ea83ddab80aacbfa0b9040bb12d96f5a3d6be09455e2a76546cbd21677537db941cab710216b6d24ec277ee0bd65b910f416737ed120f6b93a9d3b306245c8cfd8394606fdb462e5cf43c551438d2864506c63367fc890011010001b41d416c696365203c616c69636540626d626172697374612e636f2e61753e88bb041301020025021b03060b090807030206150802090a0b0416020301021e01021780050253312798021901000a09104ef7e4beccde97f015a803ff5448437780f63263b0df8442a995e7f76c221351a51edd06f2063d8166cf3157aada4923dfc44aa0f2a6a4da5cf83b7fe722ba8ab416c976e77c6b5682e7f1069026673bd0de56ba06fd5d7a9f177607f277d9b55ff940a638c3e68525c67517e2b3d976899b93ca267f705b3e5efad7d61220e96b618a4497eab8d04403d23f8846041011020006050253312910000a09107b15a67f0b3ddc03d96e009f50b6365d86c4be5d5e9d0ea42d5e56f5794c617700a0ab274e19c2827780016d23417ce89e0a2c0d987d889c04100102000605025331cf7a000a0910a401d9f09a34f7c0ee970400aca292f213041c9f3b3fc49148cbda9d84afee6183c8dd6c5ff2600b29482db5fecd4303797be1ee6d544a20a858080fec43412061c9a71fae4039fd58013b4ae341273e6c66ad4c7cdd9e68245bedb260562e7b166f2461a1032f2b38c0e0e5715fb3d1656979e052b55ca827a76f872b78a9fdae64bc298170bfcebedc1271b41a416c696365203c616c696365407379646973702e6f722e61753e88b804130102002205025331278b021b03060b090807030206150802090a0b0416020301021e01021780000a09104ef7e4beccde97f06a7003fa03c3af68d272ebc1fa08aa72a03b02189c26496a2833d90450801c4e42c5b5f51ad96ce2d2c9cef4b7c02a6a2fcf1412d6a2d486098eb762f5010a201819c17fd2888aec8eda20c65a3b75744de7ee5cc8ac7bfc470cbe3cb982720405a27a3c6a8c229cfe36905f881b02ed5680f6a8f05866efb9d6c5844897e631deb949ca8846041011020006050253312910000a09107b15a67f0b3ddc0347bc009f7fa35db59147469eb6f2c5aaf6428accb138b22800a0caa2f5f0874bacc5909c652a57a31beda65eddd5889c04100102000605025331cf7a000a0910a401d9f09a34f7c0316403ff46f2a5c101256627f16384d34a38fb47a6c88ba60506843e532d91614339fccae5f884a5741e7582ffaf292ba38ee10a270a05f139bde3814b6a077e8cd2db0f105ebea2a83af70d385f13b507fac2ad93ff79d84950328bb86f3074745a8b7f9b64990fb142e2a12976e27e8d09a28dc5621f957ac49091116da410ac3cbde1b88d04533121f6010400cbd785b56905e4192e2fb62a720727d43c4fa487821203cf72138b884b78b701093243e1d8c92a0248a6c0203a5a88693da34af357499abacaf4b3309c640797d03093870a323b4b6f37865f6eaa2838148a67df4735d43a90ca87942554cdf1c4a751b1e75f9fd4ce4e97e278d6c1c7ed59d33441df7d084f3f02beb68896c70011010001889f0418010200090502533121f6021b0c000a09104ef7e4beccde97f0b98b03fc0a5ccf6a372995835a2f5da33b282a7d612c0ab2a97f59cf9fff73e9110981aac2858c41399afa29624a7fd8a0add11654e3d882c0fd199e161bdad65e5e2548f7b68a437ea64293db1246e3011cbb94dc1bcdeaf0f2539bd88ff16d95547144d97cead6a8c5927660a91e6db0d16eb36b7b49a3525b54d1644e65599b032b7eb901a204533127a0110400bd3edaa09eff9809c4edc2c2a0ebe52e53c50a19c1e49ab78e6167bf61473bb08f2050d78a5cbbc6ed66aff7b42cd503f16b4a0b99fa1609681fca9b7ce2bbb1a5b3864d6cdda4d7ef7849d156d534dea30fb0efb9e4cf8959a2b2ce623905882d5430b995a15c3b9fe92906086788b891002924f94abe139b42cbbfaaabe42f00a0b65dc1a1ad27d798adbcb5b5ad02d2688c89477b03ff4eebb6f7b15a73b96a96bed201c0e5e4ea27e4c6e2dd1005b94d4b90137a5b1cf5e01c6226c070c4cc999938101578877ee76d296b9aab8246d57049caacf489e80a3f40589cade790a020b1ac146d6f7a6241184b8c7fcde680eae3188f5dcbe846d7f7bdad34f6fcfca08413e19c1d5df83fc7c7c627d493492e009c2f52a80400a2fe82de87136fd2e8845888c4431b032ba29d9a29a804277e31002a8201fb8591a3e55c7a0d0881496caf8b9fb07544a5a4879291d0dc026a0ea9e5bd88eb4aa4947bbd694b25012e208a250d65ddc6f1eea59d3aed3b4ec15fcab85e2afaa23a40ab1ef9ce3e11e1bc1c34a0e758e7aa64deb8739276df0af7d4121f834a9b88e70418010200090502533127a0021b02005209104ef7e4beccde97f047200419110200060502533127a0000a0910dbce4ee19529437fe045009c0b32f5ead48ee8a7e98fac0dea3d3e6c0e2c552500a0ad71fadc5007cfaf842d9b7db3335a8cdad15d3d1a6404009b08e2c68fe8f3b45c1bb72a4b3278cdf3012aa0f229883ad74aa1f6000bb90b18301b2f85372ca5d6b9bf478d235b733b1b197d19ccca48e9daf8e890cb64546b4ce1b178faccfff07003c172a2d4f5ebaba9f57153955f3f61a9b80a4f5cb959908f8b211b03b7026a8a82fc612bfedd3794969bcf458c4ce92be215a1176ab88d045331d144010400a5063000c5aaf34953c1aa3bfc95045b3aab9882b9a8027fecfe2142dc6b47ba8aca667399990244d513dd0504716908c17d92c65e74219e004f7b83fc125e575dd58efec3ab6dd22e3580106998523dea42ec75bf9aa111734c82df54630bebdff20fe981cfc36c76f865eb1c2fb62c9e85bc3a6e5015a361a2eb1c8431578d0011010001889f04280102000905025331d433021d03000a09104ef7e4beccde97f02e5503ff5e0630d1b65291f4882b6d40a29da4616bb5088717d469fbcc3648b8276de04a04988b1f1b9f3e18f52265c1f8b6c85861691c1a6b8a3a25a1809a0b32ad330aec5667cb4262f4450649184e8113849b05e5ad06a316ea80c001e8e71838190339a6e48bbde30647bcf245134b9a97fa875c1d83a9862cae87ffd7e2c4ce3a1b89013d04180102000905025331d144021b0200a809104ef7e4beccde97f09d2004190102000605025331d144000a0910677815e371c2fd23522203fe22ab62b8e7a151383cea3edd3a12995693911426f8ccf125e1f6426388c0010f88d9ca7da2224aee8d1c12135998640c5e1813d55a93df472faae75bef858457248db41b4505827590aeccf6f9eb646da7f980655dd3050c6897feddddaca90676dee856d66db8923477d251712bb9b3186b4d0114daf7d6b59272b53218dd1da94a03ff64006fcbe71211e5daecd9961fba66cdb6de3f914882c58ba5beddeba7dcb950c1156d7fba18c19ea880dccc800eae335deec34e3b84ac75ffa24864f782f87815cda1c0f634b3dd2fa67cea30811d21723d21d9551fa12ccbcfa62b6d3a15d01307b99925707992556d50065505b090aadb8579083a20fe65bd2a270da9b011"
|
||||
|
||||
const missingCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Charset: UTF-8
|
||||
|
||||
mQENBFMYynYBCACVOZ3/e8Bm2b9KH9QyIlHGo/i1bnkpqsgXj8tpJ2MIUOnXMMAY
|
||||
ztW7kKFLCmgVdLIC0vSoLA4yhaLcMojznh/2CcUglZeb6Ao8Gtelr//Rd5DRfPpG
|
||||
zqcfUo+m+eO1co2Orabw0tZDfGpg5p3AYl0hmxhUyYSc/xUq93xL1UJzBFgYXY54
|
||||
QsM8dgeQgFseSk/YvdP5SMx1ev+eraUyiiUtWzWrWC1TdyRa5p4UZg6Rkoppf+WJ
|
||||
QrW6BWrhAtqATHc8ozV7uJjeONjUEq24roRc/OFZdmQQGK6yrzKnnbA6MdHhqpdo
|
||||
9kWDcXYb7pSE63Lc+OBa5X2GUVvXJLS/3nrtABEBAAG0F2ludmFsaWQtc2lnbmlu
|
||||
Zy1zdWJrZXlziQEoBBMBAgASBQJTnKB5AhsBAgsHAhUIAh4BAAoJEO3UDQUIHpI/
|
||||
dN4H/idX4FQ1LIZCnpHS/oxoWQWfpRgdKAEM0qCqjMgiipJeEwSQbqjTCynuh5/R
|
||||
JlODDz85ABR06aoF4l5ebGLQWFCYifPnJZ/Yf5OYcMGtb7dIbqxWVFL9iLMO/oDL
|
||||
ioI3dotjPui5e+2hI9pVH1UHB/bZ/GvMGo6Zg0XxLPolKQODMVjpjLAQ0YJ3spew
|
||||
RAmOGre6tIvbDsMBnm8qREt7a07cBJ6XK7xjxYaZHQBiHVxyEWDa6gyANONx8duW
|
||||
/fhQ/zDTnyVM/ik6VO0Ty9BhPpcEYLFwh5c1ilFari1ta3e6qKo6ZGa9YMk/REhu
|
||||
yBHd9nTkI+0CiQUmbckUiVjDKKe5AQ0EUxjKdgEIAJcXQeP+NmuciE99YcJoffxv
|
||||
2gVLU4ZXBNHEaP0mgaJ1+tmMD089vUQAcyGRvw8jfsNsVZQIOAuRxY94aHQhIRHR
|
||||
bUzBN28ofo/AJJtfx62C15xt6fDKRV6HXYqAiygrHIpEoRLyiN69iScUsjIJeyFL
|
||||
C8wa72e8pSL6dkHoaV1N9ZH/xmrJ+k0vsgkQaAh9CzYufncDxcwkoP+aOlGtX1gP
|
||||
WwWoIbz0JwLEMPHBWvDDXQcQPQTYQyj+LGC9U6f9VZHN25E94subM1MjuT9OhN9Y
|
||||
MLfWaaIc5WyhLFyQKW2Upofn9wSFi8ubyBnv640Dfd0rVmaWv7LNTZpoZ/GbJAMA
|
||||
EQEAAYkBHwQYAQIACQUCU5ygeQIbAgAKCRDt1A0FCB6SP0zCB/sEzaVR38vpx+OQ
|
||||
MMynCBJrakiqDmUZv9xtplY7zsHSQjpd6xGflbU2n+iX99Q+nav0ETQZifNUEd4N
|
||||
1ljDGQejcTyKD6Pkg6wBL3x9/RJye7Zszazm4+toJXZ8xJ3800+BtaPoI39akYJm
|
||||
+ijzbskvN0v/j5GOFJwQO0pPRAFtdHqRs9Kf4YanxhedB4dIUblzlIJuKsxFit6N
|
||||
lgGRblagG3Vv2eBszbxzPbJjHCgVLR3RmrVezKOsZjr/2i7X+xLWIR0uD3IN1qOW
|
||||
CXQxLBizEEmSNVNxsp7KPGTLnqO3bPtqFirxS9PJLIMPTPLNBY7ZYuPNTMqVIUWF
|
||||
4artDmrG
|
||||
=7FfJ
|
||||
-----END PGP PUBLIC KEY BLOCK-----`
|
||||
|
||||
const invalidCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQENBFMYynYBCACVOZ3/e8Bm2b9KH9QyIlHGo/i1bnkpqsgXj8tpJ2MIUOnXMMAY
|
||||
ztW7kKFLCmgVdLIC0vSoLA4yhaLcMojznh/2CcUglZeb6Ao8Gtelr//Rd5DRfPpG
|
||||
zqcfUo+m+eO1co2Orabw0tZDfGpg5p3AYl0hmxhUyYSc/xUq93xL1UJzBFgYXY54
|
||||
QsM8dgeQgFseSk/YvdP5SMx1ev+eraUyiiUtWzWrWC1TdyRa5p4UZg6Rkoppf+WJ
|
||||
QrW6BWrhAtqATHc8ozV7uJjeONjUEq24roRc/OFZdmQQGK6yrzKnnbA6MdHhqpdo
|
||||
9kWDcXYb7pSE63Lc+OBa5X2GUVvXJLS/3nrtABEBAAG0F2ludmFsaWQtc2lnbmlu
|
||||
Zy1zdWJrZXlziQEoBBMBAgASBQJTnKB5AhsBAgsHAhUIAh4BAAoJEO3UDQUIHpI/
|
||||
dN4H/idX4FQ1LIZCnpHS/oxoWQWfpRgdKAEM0qCqjMgiipJeEwSQbqjTCynuh5/R
|
||||
JlODDz85ABR06aoF4l5ebGLQWFCYifPnJZ/Yf5OYcMGtb7dIbqxWVFL9iLMO/oDL
|
||||
ioI3dotjPui5e+2hI9pVH1UHB/bZ/GvMGo6Zg0XxLPolKQODMVjpjLAQ0YJ3spew
|
||||
RAmOGre6tIvbDsMBnm8qREt7a07cBJ6XK7xjxYaZHQBiHVxyEWDa6gyANONx8duW
|
||||
/fhQ/zDTnyVM/ik6VO0Ty9BhPpcEYLFwh5c1ilFari1ta3e6qKo6ZGa9YMk/REhu
|
||||
yBHd9nTkI+0CiQUmbckUiVjDKKe5AQ0EUxjKdgEIAIINDqlj7X6jYKc6DjwrOkjQ
|
||||
UIRWbQQar0LwmNilehmt70g5DCL1SYm9q4LcgJJ2Nhxj0/5qqsYib50OSWMcKeEe
|
||||
iRXpXzv1ObpcQtI5ithp0gR53YPXBib80t3bUzomQ5UyZqAAHzMp3BKC54/vUrSK
|
||||
FeRaxDzNLrCeyI00+LHNUtwghAqHvdNcsIf8VRumK8oTm3RmDh0TyjASWYbrt9c8
|
||||
R1Um3zuoACOVy+mEIgIzsfHq0u7dwYwJB5+KeM7ZLx+HGIYdUYzHuUE1sLwVoELh
|
||||
+SHIGHI1HDicOjzqgajShuIjj5hZTyQySVprrsLKiXS6NEwHAP20+XjayJ/R3tEA
|
||||
EQEAAYkCPgQYAQIBKAUCU5ygeQIbAsBdIAQZAQIABgUCU5ygeQAKCRCpVlnFZmhO
|
||||
52RJB/9uD1MSa0wjY6tHOIgquZcP3bHBvHmrHNMw9HR2wRCMO91ZkhrpdS3ZHtgb
|
||||
u3/55etj0FdvDo1tb8P8FGSVtO5Vcwf5APM8sbbqoi8L951Q3i7qt847lfhu6sMl
|
||||
w0LWFvPTOLHrliZHItPRjOltS1WAWfr2jUYhsU9ytaDAJmvf9DujxEOsN5G1YJep
|
||||
54JCKVCkM/y585Zcnn+yxk/XwqoNQ0/iJUT9qRrZWvoeasxhl1PQcwihCwss44A+
|
||||
YXaAt3hbk+6LEQuZoYS73yR3WHj+42tfm7YxRGeubXfgCEz/brETEWXMh4pe0vCL
|
||||
bfWrmfSPq2rDegYcAybxRQz0lF8PAAoJEO3UDQUIHpI/exkH/0vQfdHA8g/N4T6E
|
||||
i6b1CUVBAkvtdJpCATZjWPhXmShOw62gkDw306vHPilL4SCvEEi4KzG72zkp6VsB
|
||||
DSRcpxCwT4mHue+duiy53/aRMtSJ+vDfiV1Vhq+3sWAck/yUtfDU9/u4eFaiNok1
|
||||
8/Gd7reyuZt5CiJnpdPpjCwelK21l2w7sHAnJF55ITXdOxI8oG3BRKufz0z5lyDY
|
||||
s2tXYmhhQIggdgelN8LbcMhWs/PBbtUr6uZlNJG2lW1yscD4aI529VjwJlCeo745
|
||||
U7pO4eF05VViUJ2mmfoivL3tkhoTUWhx8xs8xCUcCg8DoEoSIhxtOmoTPR22Z9BL
|
||||
6LCg2mg=
|
||||
=Dhm4
|
||||
-----END PGP PUBLIC KEY BLOCK-----`
|
||||
|
||||
const goodCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: GnuPG v1
|
||||
|
||||
mI0EVUqeVwEEAMufHRrMPWK3gyvi0O0tABCs/oON9zV9KDZlr1a1M91ShCSFwCPo
|
||||
7r80PxdWVWcj0V5h50/CJYtpN3eE/mUIgW2z1uDYQF1OzrQ8ubrksfsJvpAhENom
|
||||
lTQEppv9mV8qhcM278teb7TX0pgrUHLYF5CfPdp1L957JLLXoQR/lwLVABEBAAG0
|
||||
E2dvb2Qtc2lnbmluZy1zdWJrZXmIuAQTAQIAIgUCVUqeVwIbAwYLCQgHAwIGFQgC
|
||||
CQoLBBYCAwECHgECF4AACgkQNRjL95IRWP69XQQAlH6+eyXJN4DZTLX78KGjHrsw
|
||||
6FCvxxClEPtPUjcJy/1KCRQmtLAt9PbbA78dvgzjDeZMZqRAwdjyJhjyg/fkU2OH
|
||||
7wq4ktjUu+dLcOBb+BFMEY+YjKZhf6EJuVfxoTVr5f82XNPbYHfTho9/OABKH6kv
|
||||
X70PaKZhbwnwij8Nts65AaIEVUqftREEAJ3WxZfqAX0bTDbQPf2CMT2IVMGDfhK7
|
||||
GyubOZgDFFjwUJQvHNvsrbeGLZ0xOBumLINyPO1amIfTgJNm1iiWFWfmnHReGcDl
|
||||
y5mpYG60Mb79Whdcer7CMm3AqYh/dW4g6IB02NwZMKoUHo3PXmFLxMKXnWyJ0clw
|
||||
R0LI/Qn509yXAKDh1SO20rqrBM+EAP2c5bfI98kyNwQAi3buu94qo3RR1ZbvfxgW
|
||||
CKXDVm6N99jdZGNK7FbRifXqzJJDLcXZKLnstnC4Sd3uyfyf1uFhmDLIQRryn5m+
|
||||
LBYHfDBPN3kdm7bsZDDq9GbTHiFZUfm/tChVKXWxkhpAmHhU/tH6GGzNSMXuIWSO
|
||||
aOz3Rqq0ED4NXyNKjdF9MiwD/i83S0ZBc0LmJYt4Z10jtH2B6tYdqnAK29uQaadx
|
||||
yZCX2scE09UIm32/w7pV77CKr1Cp/4OzAXS1tmFzQ+bX7DR+Gl8t4wxr57VeEMvl
|
||||
BGw4Vjh3X8//m3xynxycQU18Q1zJ6PkiMyPw2owZ/nss3hpSRKFJsxMLhW3fKmKr
|
||||
Ey2KiOcEGAECAAkFAlVKn7UCGwIAUgkQNRjL95IRWP5HIAQZEQIABgUCVUqftQAK
|
||||
CRD98VjDN10SqkWrAKDTpEY8D8HC02E/KVC5YUI01B30wgCgurpILm20kXEDCeHp
|
||||
C5pygfXw1DJrhAP+NyPJ4um/bU1I+rXaHHJYroYJs8YSweiNcwiHDQn0Engh/mVZ
|
||||
SqLHvbKh2dL/RXymC3+rjPvQf5cup9bPxNMa6WagdYBNAfzWGtkVISeaQW+cTEp/
|
||||
MtgVijRGXR/lGLGETPg2X3Afwn9N9bLMBkBprKgbBqU7lpaoPupxT61bL70=
|
||||
=vtbN
|
||||
-----END PGP PUBLIC KEY BLOCK-----`
|
||||
|
||||
const revokedUserIDKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQENBFsgO5EBCADhREPmcjsPkXe1z7ctvyWL0S7oa9JaoGZ9oPDHFDlQxd0qlX2e
|
||||
DZJZDg0qYvVixmaULIulApq1puEsaJCn3lHUbHlb4PYKwLEywYXM28JN91KtLsz/
|
||||
uaEX2KC5WqeP40utmzkNLq+oRX/xnRMgwbO7yUNVG2UlEa6eI+xOXO3YtLdmJMBW
|
||||
ClQ066ZnOIzEo1JxnIwha1CDBMWLLfOLrg6l8InUqaXbtEBbnaIYO6fXVXELUjkx
|
||||
nmk7t/QOk0tXCy8muH9UDqJkwDUESY2l79XwBAcx9riX8vY7vwC34pm22fAUVLCJ
|
||||
x1SJx0J8bkeNp38jKM2Zd9SUQqSbfBopQ4pPABEBAAG0I0dvbGFuZyBHb3BoZXIg
|
||||
PG5vLXJlcGx5QGdvbGFuZy5jb20+iQFUBBMBCgA+FiEE5Ik5JLcNx6l6rZfw1oFy
|
||||
9I6cUoMFAlsgO5ECGwMFCQPCZwAFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQ
|
||||
1oFy9I6cUoMIkwf8DNPeD23i4jRwd/pylbvxwZintZl1fSwTJW1xcOa1emXaEtX2
|
||||
depuqhP04fjlRQGfsYAQh7X9jOJxAHjTmhqFBi5sD7QvKU00cPFYbJ/JTx0B41bl
|
||||
aXnSbGhRPh63QtEZL7ACAs+shwvvojJqysx7kyVRu0EW2wqjXdHwR/SJO6nhNBa2
|
||||
DXzSiOU/SUA42mmG+5kjF8Aabq9wPwT9wjraHShEweNerNMmOqJExBOy3yFeyDpa
|
||||
XwEZFzBfOKoxFNkIaVf5GSdIUGhFECkGvBMB935khftmgR8APxdU4BE7XrXexFJU
|
||||
8RCuPXonm4WQOwTWR0vQg64pb2WKAzZ8HhwTGbQiR29sYW5nIEdvcGhlciA8cmV2
|
||||
b2tlZEBnb2xhbmcuY29tPokBNgQwAQoAIBYhBOSJOSS3Dcepeq2X8NaBcvSOnFKD
|
||||
BQJbIDv3Ah0AAAoJENaBcvSOnFKDfWMIAKhI/Tvu3h8fSUxp/gSAcduT6bC1JttG
|
||||
0lYQ5ilKB/58lBUA5CO3ZrKDKlzW3M8VEcvohVaqeTMKeoQd5rCZq8KxHn/KvN6N
|
||||
s85REfXfniCKfAbnGgVXX3kDmZ1g63pkxrFu0fDZjVDXC6vy+I0sGyI/Inro0Pzb
|
||||
tvn0QCsxjapKK15BtmSrpgHgzVqVg0cUp8vqZeKFxarYbYB2idtGRci4b9tObOK0
|
||||
BSTVFy26+I/mrFGaPrySYiy2Kz5NMEcRhjmTxJ8jSwEr2O2sUR0yjbgUAXbTxDVE
|
||||
/jg5fQZ1ACvBRQnB7LvMHcInbzjyeTM3FazkkSYQD6b97+dkWwb1iWG5AQ0EWyA7
|
||||
kQEIALkg04REDZo1JgdYV4x8HJKFS4xAYWbIva1ZPqvDNmZRUbQZR2+gpJGEwn7z
|
||||
VofGvnOYiGW56AS5j31SFf5kro1+1bZQ5iOONBng08OOo58/l1hRseIIVGB5TGSa
|
||||
PCdChKKHreJI6hS3mShxH6hdfFtiZuB45rwoaArMMsYcjaezLwKeLc396cpUwwcZ
|
||||
snLUNd1Xu5EWEF2OdFkZ2a1qYdxBvAYdQf4+1Nr+NRIx1u1NS9c8jp3PuMOkrQEi
|
||||
bNtc1v6v0Jy52mKLG4y7mC/erIkvkQBYJdxPaP7LZVaPYc3/xskcyijrJ/5ufoD8
|
||||
K71/ShtsZUXSQn9jlRaYR0EbojMAEQEAAYkBPAQYAQoAJhYhBOSJOSS3Dcepeq2X
|
||||
8NaBcvSOnFKDBQJbIDuRAhsMBQkDwmcAAAoJENaBcvSOnFKDkFMIAIt64bVZ8x7+
|
||||
TitH1bR4pgcNkaKmgKoZz6FXu80+SnbuEt2NnDyf1cLOSimSTILpwLIuv9Uft5Pb
|
||||
OraQbYt3xi9yrqdKqGLv80bxqK0NuryNkvh9yyx5WoG1iKqMj9/FjGghuPrRaT4l
|
||||
QinNAghGVkEy1+aXGFrG2DsOC1FFI51CC2WVTzZ5RwR2GpiNRfESsU1rZAUqf/2V
|
||||
yJl9bD5R4SUNy8oQmhOxi+gbhD4Ao34e4W0ilibslI/uawvCiOwlu5NGd8zv5n+U
|
||||
heiQvzkApQup5c+BhH5zFDFdKJ2CBByxw9+7QjMFI/wgLixKuE0Ob2kAokXf7RlB
|
||||
7qTZOahrETw=
|
||||
=IKnw
|
||||
-----END PGP PUBLIC KEY BLOCK-----`
|
||||
|
||||
const keyWithSubKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mI0EWyKwKQEEALwXhKBnyaaNFeK3ljfc/qn9X/QFw+28EUfgZPHjRmHubuXLE2uR
|
||||
s3ZoSXY2z7Dkv+NyHYMt8p+X8q5fR7JvUjK2XbPyKoiJVnHINll83yl67DaWfKNL
|
||||
EjNoO0kIfbXfCkZ7EG6DL+iKtuxniGTcnGT47e+HJSqb/STpLMnWwXjBABEBAAG0
|
||||
I0dvbGFuZyBHb3BoZXIgPG5vLXJlcGx5QGdvbGFuZy5jb20+iM4EEwEKADgWIQQ/
|
||||
lRafP/p9PytHbwxMvYJsOQdOOAUCWyKwKQIbAwULCQgHAwUVCgkICwUWAgMBAAIe
|
||||
AQIXgAAKCRBMvYJsOQdOOOsFBAC62mXww8XuqvYLcVOvHkWLT6mhxrQOJXnlfpn7
|
||||
2uBV9CMhoG/Ycd43NONsJrB95Apr9TDIqWnVszNbqPCuBhZQSGLdbiDKjxnCWBk0
|
||||
69qv4RNtkpOhYB7jK4s8F5oQZqId6JasT/PmJTH92mhBYhhTQr0GYFuPX2UJdkw9
|
||||
Sn9C67iNBFsisDUBBAC3A+Yo9lgCnxi/pfskyLrweYif6kIXWLAtLTsM6g/6jt7b
|
||||
wTrknuCPyTv0QKGXsAEe/cK/Xq3HvX9WfXPGIHc/X56ZIsHQ+RLowbZV/Lhok1IW
|
||||
FAuQm8axr/by80cRwFnzhfPc/ukkAq2Qyj4hLsGblu6mxeAhzcp8aqmWOO2H9QAR
|
||||
AQABiLYEKAEKACAWIQQ/lRafP/p9PytHbwxMvYJsOQdOOAUCWyK16gIdAAAKCRBM
|
||||
vYJsOQdOOB1vA/4u4uLONsE+2GVOyBsHyy7uTdkuxaR9b54A/cz6jT/tzUbeIzgx
|
||||
22neWhgvIEghnUZd0vEyK9k1wy5vbDlEo6nKzHso32N1QExGr5upRERAxweDxGOj
|
||||
7luDwNypI7QcifE64lS/JmlnunwRCdRWMKc0Fp+7jtRc5mpwyHN/Suf5RokBagQY
|
||||
AQoAIBYhBD+VFp8/+n0/K0dvDEy9gmw5B044BQJbIrA1AhsCAL8JEEy9gmw5B044
|
||||
tCAEGQEKAB0WIQSNdnkaWY6t62iX336UXbGvYdhXJwUCWyKwNQAKCRCUXbGvYdhX
|
||||
JxJSA/9fCPHP6sUtGF1o3G1a3yvOUDGr1JWcct9U+QpbCt1mZoNopCNDDQAJvDWl
|
||||
mvDgHfuogmgNJRjOMznvahbF+wpTXmB7LS0SK412gJzl1fFIpK4bgnhu0TwxNsO1
|
||||
8UkCZWqxRMgcNUn9z6XWONK8dgt5JNvHSHrwF4CxxwjL23AAtK+FA/UUoi3U4kbC
|
||||
0XnSr1Sl+mrzQi1+H7xyMe7zjqe+gGANtskqexHzwWPUJCPZ5qpIa2l8ghiUim6b
|
||||
4ymJ+N8/T8Yva1FaPEqfMzzqJr8McYFm0URioXJPvOAlRxdHPteZ0qUopt/Jawxl
|
||||
Xt6B9h1YpeLoJwjwsvbi98UTRs0jXwoY
|
||||
=3fWu
|
||||
-----END PGP PUBLIC KEY BLOCK-----`
|
||||
|
||||
const keyWithSubKeyAndBadSelfSigOrder = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mI0EWyLLDQEEAOqIOpJ/ha1OYAGduu9tS3rBz5vyjbNgJO4sFveEM0mgsHQ0X9/L
|
||||
plonW+d0gRoO1dhJ8QICjDAc6+cna1DE3tEb5m6JtQ30teLZuqrR398Cf6w7NNVz
|
||||
r3lrlmnH9JaKRuXl7tZciwyovneBfZVCdtsRZjaLI1uMQCz/BToiYe3DABEBAAG0
|
||||
I0dvbGFuZyBHb3BoZXIgPG5vLXJlcGx5QGdvbGFuZy5jb20+iM4EEwEKADgWIQRZ
|
||||
sixZOfQcZdW0wUqmgmdsv1O9xgUCWyLLDQIbAwULCQgHAwUVCgkICwUWAgMBAAIe
|
||||
AQIXgAAKCRCmgmdsv1O9xql2A/4pix98NxjhdsXtazA9agpAKeADf9tG4Za27Gj+
|
||||
3DCww/E4iP2X35jZimSm/30QRB6j08uGCqd9vXkkJxtOt63y/IpVOtWX6vMWSTUm
|
||||
k8xKkaYMP0/IzKNJ1qC/qYEUYpwERBKg9Z+k99E2Ql4kRHdxXUHq6OzY79H18Y+s
|
||||
GdeM/riNBFsiyxsBBAC54Pxg/8ZWaZX1phGdwfe5mek27SOYpC0AxIDCSOdMeQ6G
|
||||
HPk38pywl1d+S+KmF/F4Tdi+kWro62O4eG2uc/T8JQuRDUhSjX0Qa51gPzJrUOVT
|
||||
CFyUkiZ/3ZDhtXkgfuso8ua2ChBgR9Ngr4v43tSqa9y6AK7v0qjxD1x+xMrjXQAR
|
||||
AQABiQFxBBgBCgAmAhsCFiEEWbIsWTn0HGXVtMFKpoJnbL9TvcYFAlsizTIFCQAN
|
||||
MRcAv7QgBBkBCgAdFiEEJcoVUVJIk5RWj1c/o62jUpRPICQFAlsiyxsACgkQo62j
|
||||
UpRPICQq5gQApoWIigZxXFoM0uw4uJBS5JFZtirTANvirZV5RhndwHeMN6JttaBS
|
||||
YnjyA4+n1D+zB2VqliD2QrsX12KJN6rGOehCtEIClQ1Hodo9nC6kMzzAwW1O8bZs
|
||||
nRJmXV+bsvD4sidLZLjdwOVa3Cxh6pvq4Uur6a7/UYx121hEY0Qx0s8JEKaCZ2y/
|
||||
U73GGi0D/i20VW8AWYAPACm2zMlzExKTOAV01YTQH/3vW0WLrOse53WcIVZga6es
|
||||
HuO4So0SOEAvxKMe5HpRIu2dJxTvd99Bo9xk9xJU0AoFrO0vNCRnL+5y68xMlODK
|
||||
lEw5/kl0jeaTBp6xX0HDQOEVOpPGUwWV4Ij2EnvfNDXaE1vK1kffiQFrBBgBCgAg
|
||||
AhsCFiEEWbIsWTn0HGXVtMFKpoJnbL9TvcYFAlsi0AYAv7QgBBkBCgAdFiEEJcoV
|
||||
UVJIk5RWj1c/o62jUpRPICQFAlsiyxsACgkQo62jUpRPICQq5gQApoWIigZxXFoM
|
||||
0uw4uJBS5JFZtirTANvirZV5RhndwHeMN6JttaBSYnjyA4+n1D+zB2VqliD2QrsX
|
||||
12KJN6rGOehCtEIClQ1Hodo9nC6kMzzAwW1O8bZsnRJmXV+bsvD4sidLZLjdwOVa
|
||||
3Cxh6pvq4Uur6a7/UYx121hEY0Qx0s8JEKaCZ2y/U73GRl0EAJokkXmy4zKDHWWi
|
||||
wvK9gi2gQgRkVnu2AiONxJb5vjeLhM/07BRmH6K1o+w3fOeEQp4FjXj1eQ5fPSM6
|
||||
Hhwx2CTl9SDnPSBMiKXsEFRkmwQ2AAsQZLmQZvKBkLZYeBiwf+IY621eYDhZfo+G
|
||||
1dh1WoUCyREZsJQg2YoIpWIcvw+a
|
||||
=bNRo
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
`
|
||||
|
||||
const onlySubkeyNoPrivateKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
Version: GnuPG v1
|
||||
|
||||
lQCVBFggvocBBAC7vBsHn7MKmS6IiiZNTXdciplVgS9cqVd+RTdIAoyNTcsiV1H0
|
||||
GQ3QtodOPeDlQDNoqinqaobd7R9g3m3hS53Nor7yBZkCWQ5x9v9JxRtoAq0sklh1
|
||||
I1X2zEqZk2l6YrfBF/64zWrhjnW3j23szkrAIVu0faQXbQ4z56tmZrw11wARAQAB
|
||||
/gdlAkdOVQG0CUdOVSBEdW1teYi4BBMBAgAiBQJYIL6HAhsDBgsJCAcDAgYVCAIJ
|
||||
CgsEFgIDAQIeAQIXgAAKCRCd1xxWp1CYAnjGA/9synn6ZXJUKAXQzySgmCZvCIbl
|
||||
rqBfEpxwLG4Q/lONhm5vthAE0z49I8hj5Gc5e2tLYUtq0o0OCRdCrYHa/efOYWpJ
|
||||
6RsK99bePOisVzmOABLIgZkcr022kHoMCmkPgv9CUGKP1yqbGl+zzAwQfUjRUmvD
|
||||
ZIcWLHi2ge4GzPMPi50B2ARYIL6cAQQAxWHnicKejAFcFcF1/3gUSgSH7eiwuBPX
|
||||
M7vDdgGzlve1o1jbV4tzrjN9jsCl6r0nJPDMfBSzgLr1auNTRG6HpJ4abcOx86ED
|
||||
Ad+avDcQPZb7z3dPhH/gb2lQejZsHh7bbeOS8WMSzHV3RqCLd8J/xwWPNR5zKn1f
|
||||
yp4IGfopidMAEQEAAQAD+wQOelnR82+dxyM2IFmZdOB9wSXQeCVOvxSaNMh6Y3lk
|
||||
UOOkO8Nlic4x0ungQRvjoRs4wBmCuwFK/MII6jKui0B7dn/NDf51i7rGdNGuJXDH
|
||||
e676By1sEY/NGkc74jr74T+5GWNU64W0vkpfgVmjSAzsUtpmhJMXsc7beBhJdnVl
|
||||
AgDKCb8hZqj1alcdmLoNvb7ibA3K/V8J462CPD7bMySPBa/uayoFhNxibpoXml2r
|
||||
oOtHa5izF3b0/9JY97F6rqkdAgD6GdTJ+xmlCoz1Sewoif1I6krq6xoa7gOYpIXo
|
||||
UL1Afr+LiJeyAnF/M34j/kjIVmPanZJjry0kkjHE5ILjH3uvAf4/6n9np+Th8ujS
|
||||
YDCIzKwR7639+H+qccOaddCep8Y6KGUMVdD/vTKEx1rMtK+hK/CDkkkxnFslifMJ
|
||||
kqoqv3WUqCWJAT0EGAECAAkFAlggvpwCGwIAqAkQndccVqdQmAKdIAQZAQIABgUC
|
||||
WCC+nAAKCRDmGUholQPwvQk+A/9latnSsR5s5/1A9TFki11GzSEnfLbx46FYOdkW
|
||||
n3YBxZoPQGxNA1vIn8GmouxZInw9CF4jdOJxEdzLlYQJ9YLTLtN5tQEMl/19/bR8
|
||||
/qLacAZ9IOezYRWxxZsyn6//jfl7A0Y+FV59d4YajKkEfItcIIlgVBSW6T+TNQT3
|
||||
R+EH5HJ/A/4/AN0CmBhhE2vGzTnVU0VPrE4V64pjn1rufFdclgpixNZCuuqpKpoE
|
||||
VVHn6mnBf4njKjZrAGPs5kfQ+H4NsM7v3Zz4yV6deu9FZc4O6E+V1WJ38rO8eBix
|
||||
7G2jko106CC6vtxsCPVIzY7aaG3H5pjRtomw+pX7SzrQ7FUg2PGumg==
|
||||
=F/T0
|
||||
-----END PGP PRIVATE KEY BLOCK-----`
|
||||
|
||||
const ecdsaPrivateKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
|
||||
xaUEX1KsSRMIKoZIzj0DAQcCAwTpYqJsnJiFhKKh+8TulWD+lVmerBFNS+Ii
|
||||
B+nlG3T0xQQ4Sy5eIjJ0CExIQQzi3EElF/Z2l4F3WC5taFA11NgA/gkDCHSS
|
||||
PThf1M2K4LN8F1MRcvR+sb7i0nH55ojkwuVB1DE6jqIT9m9i+mX1tzjSAS+6
|
||||
lPQiweCJvG7xTC7Hs3AzRapf/r1At4TB+v+5G2/CKynNFEJpbGwgPGJpbGxA
|
||||
aG9tZS5jb20+wncEEBMIAB8FAl9SrEkGCwkHCAMCBBUICgIDFgIBAhkBAhsD
|
||||
Ah4BAAoJEMpwT3+q3+xqw5UBAMebZN9isEZ1ML+R/jWAAWMwa/knMugrEZ1v
|
||||
Bl9+ZwM0AQCZdf80/wYY4Nve01qSRFv8OmKswLli3TvDv6FKc4cLz8epBF9S
|
||||
rEkSCCqGSM49AwEHAgMEAjKnT9b5wY2bf9TpAV3d7OUfPOxKj9c4VzeVzSrH
|
||||
AtQgo/MuI1cdYVURicV4i76DNjFhQHQFTk7BrC+C2u1yqQMBCAf+CQMIHImA
|
||||
iYfzQtjgQWSFZYUkCFpbbwhNF0ch+3HNaZkaHCnZRIsWsRnc6FCb6lRQyK9+
|
||||
Dq59kHlduE5QgY40894jfmP2JdJHU6nBdYrivbEdbMJhBBgTCAAJBQJfUqxJ
|
||||
AhsMAAoJEMpwT3+q3+xqUI0BAMykhV08kQ4Ip9Qlbss6Jdufv7YrU0Vd5hou
|
||||
b5TmiPd0APoDBh3qIic+aLLUcAuG3+Gt1P1AbUlmqV61ozn1WfHxfw==
|
||||
=KLN8
|
||||
-----END PGP PRIVATE KEY BLOCK-----`
|
||||
|
||||
const dsaPrivateKeyWithElGamalSubkey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
|
||||
lQOBBF9/MLsRCACeaF6BI0jTgDAs86t8/kXPfwlPvR2MCYzB0BCqAdcq1hV/GTYd
|
||||
oNmJRna/ZJfsI/vf+d8Nv+EYOQkPheFS1MJVBitkAXjQPgm8i1tQWen1FCWZxqGk
|
||||
/vwZYF4yo8GhZ+Wxi3w09W9Cp9QM/CTmyE1Xe7wpPBGe+oD+me8Zxjyt8JBS4Qx+
|
||||
gvWbfHxfHnggh4pz7U8QkItlLsBNQEdX4R5+zwRN66g2ZSX/shaa/EkVnihUhD7r
|
||||
njP9I51ORWucTQD6OvgooaNQZCkQ/Se9TzdakwWKS2XSIFXiY/e2E5ZgKI/pfKDU
|
||||
iA/KessxddPb7nP/05OIJqg9AoDrD4vmehLzAQD+zsUS3LDU1m9/cG4LMsQbT2VK
|
||||
Te4HqbGIAle+eu/asQf8DDJMrbZpiJZvADum9j0TJ0oep6VdMbzo9RSDKvlLKT9m
|
||||
kG63H8oDWnCZm1a+HmGq9YIX+JHWmsLXXsFLeEouLzHO+mZo0X28eji3V2T87hyR
|
||||
MmUM0wFo4k7jK8uVmkDXv3XwNp2uByWxUKZd7EnWmcEZWqIiexJ7XpCS0Pg3tRaI
|
||||
zxve0SRe/dxfUPnTk/9KQ9hS6DWroBKquL182zx1Fggh4LIWWE2zq+UYn8BI0E8A
|
||||
rmIDFJdF8ymFQGRrEy6g79NnkPmkrZWsgMRYY65P6v4zLVmqohJKkpm3/Uxa6QAP
|
||||
CCoPh/JTOvPeCP2bOJH8z4Z9Py3ouMIjofQW8sXqRgf/RIHbh0KsINHrwwZ4gVIr
|
||||
MK3RofpaYxw1ztPIWb4cMWoWZHH1Pxh7ggTGSBpAhKXkiWw2Rxat8QF5aA7e962c
|
||||
bLvVv8dqsPrD/RnVJHag89cbPTzjn7gY9elE8EM8ithV3oQkwHTr4avYlpDZsgNd
|
||||
hUW3YgRwGo31tdzxoG04AcpV2t+07P8XMPr9hsfWs4rHohXPi38Hseu1Ji+dBoWQ
|
||||
3+1w/HH3o55s+jy4Ruaz78AIrjbmAJq+6rA2mIcCgrhw3DnzuwQAKeBvSeqn9zfS
|
||||
ZC812osMBVmkycwelpaIh64WZ0vWL3GvdXDctV2kXM+qVpDTLEny0LuiXxrwCKQL
|
||||
Ev4HAwK9uQBcreDEEud7pfRb8EYP5lzO2ZA7RaIvje6EWAGBvJGMRT0QQE5SGqc7
|
||||
Fw5geigBdt+vVyRuNNhg3c2fdn/OBQaYu0J/8AiOogG8EaM8tCFlbGdhbWFsQGRz
|
||||
YS5jb20gPGVsZ2FtYWxAZHNhLmNvbT6IkAQTEQgAOBYhBI+gnfiHQxB35/Dp0XAQ
|
||||
aE/rsWC5BQJffzC7AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEHAQaE/r
|
||||
sWC5A4EA/0GcJmyPtN+Klc7b9sVT3JgKTRnB/URxOJfYJofP0hZLAQCkqyMO+adV
|
||||
JvbgDH0zaITQWZSSXPqpgMpCA6juTrDsd50CawRffzC7EAgAxFFFSAAEQzWTgKU5
|
||||
EBtpxxoPzHqcChawTHRxHxjcELXzmUBS5PzfA1HXSPnNqK/x3Ut5ycC3CsW41Fnt
|
||||
Gm3706Wu9VFbFZVn55F9lPiplUo61n5pqMvOr1gmuQsdXiTa0t5FRa4TZ2VSiHFw
|
||||
vdAVSPTUsT4ZxJ1rPyFYRtq1n3pQcvdZowd07r0JnzTMjLLMFYCKhwIowoOC4zqJ
|
||||
iB8enjwOlpaqBATRm9xpVF7SJkroPF6/B1vdhj7E3c1aJyHlo0PYBAg756sSHWHg
|
||||
UuLyUQ4TA0hcCVenn/L/aSY2LnbdZB1EBhlYjA7dTCgwIqsQhfQmPkjz6g64A7+Y
|
||||
HbbrLwADBQgAk14QIEQ+J/VHetpQV/jt2pNsFK1kVK7mXK0spTExaC2yj2sXlHjL
|
||||
Ie3bO5T/KqmIaBEB5db5fA5xK9cZt79qrQHDKsEqUetUeMUWLBx77zBsus3grIgy
|
||||
bwDZKseRzQ715pwxquxQlScGoDIBKEh08HpwHkq140eIj3w+MAIfndaZaSCNaxaP
|
||||
Snky7BQmJ7Wc7qrIwoQP6yrnUqyW2yNi81nJYUhxjChqaFSlwzLs/iNGryBKo0ic
|
||||
BqVIRjikKHBlwBng6WyrltQo/Vt9GG8w+lqaAVXbJRlaBZJUR+2NKi/YhP3qQse3
|
||||
v8fi4kns0gh5LK+2C01RvdX4T49QSExuIf4HAwLJqYIGwadA2uem5v7/765ZtFWV
|
||||
oL0iZ0ueTJDby4wTFDpLVzzDi/uVcB0ZRFrGOp7w6OYcNYTtV8n3xmli2Q5Trw0c
|
||||
wZVzvg+ABKWiv7faBjMczIFF8y6WZKOIeAQYEQgAIBYhBI+gnfiHQxB35/Dp0XAQ
|
||||
aE/rsWC5BQJffzC7AhsMAAoJEHAQaE/rsWC5ZmIA/jhS4r4lClbvjuPWt0Yqdn7R
|
||||
fss2SPMYvMrrDh42aE0OAQD8xn4G6CN8UtW9xihXOY6FpxiJ/sMc2VaneeUd34oa
|
||||
4g==
|
||||
=XZm8
|
||||
-----END PGP PRIVATE KEY BLOCK-----`
|
||||
|
||||
// https://tests.sequoia-pgp.org/#Certificate_expiration
|
||||
// P _ U p
|
||||
const expiringPrimaryUIDKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
xsDNBF2lnPIBDAC5cL9PQoQLTMuhjbYvb4Ncuuo0bfmgPRFywX53jPhoFf4Zg6mv
|
||||
/seOXpgecTdOcVttfzC8ycIKrt3aQTiwOG/ctaR4Bk/t6ayNFfdUNxHWk4WCKzdz
|
||||
/56fW2O0F23qIRd8UUJp5IIlN4RDdRCtdhVQIAuzvp2oVy/LaS2kxQoKvph/5pQ/
|
||||
5whqsyroEWDJoSV0yOb25B/iwk/pLUFoyhDG9bj0kIzDxrEqW+7Ba8nocQlecMF3
|
||||
X5KMN5kp2zraLv9dlBBpWW43XktjcCZgMy20SouraVma8Je/ECwUWYUiAZxLIlMv
|
||||
9CurEOtxUw6N3RdOtLmYZS9uEnn5y1UkF88o8Nku890uk6BrewFzJyLAx5wRZ4F0
|
||||
qV/yq36UWQ0JB/AUGhHVPdFf6pl6eaxBwT5GXvbBUibtf8YI2og5RsgTWtXfU7eb
|
||||
SGXrl5ZMpbA6mbfhd0R8aPxWfmDWiIOhBufhMCvUHh1sApMKVZnvIff9/0Dca3wb
|
||||
vLIwa3T4CyshfT0AEQEAAc0hQm9iIEJhYmJhZ2UgPGJvYkBvcGVucGdwLmV4YW1w
|
||||
bGU+wsEUBBMBCgBIBYJfiWKKBYkBX+/UBQsJCAcCCRD7/MgqAV5zMAYVCgkICwIE
|
||||
FgIDAQIXgAIbAwIeARYhBNGmbhojsYLJmA94jPv8yCoBXnMwAAAf0wv/a++a3DkL
|
||||
CttbK4LRIiSry2wb97mxYQoWYzvkKYD1IP/KiamRwzjBKuRSE0qZ2uonQDRGc+zl
|
||||
1H9dwkDLL4T9uJngCCPCBgFW/hOFPvF+WYEKHtOzunqx6KwDHkpdH+hpzfFzIhDo
|
||||
aXiVnDGvJ3H/bVTKq1m2KPXO2ckkXPQXJX9Fx6kPHdvcq+3ZI75IzbD/ue5lBcsy
|
||||
OKLzVu+KLxzlzGui6v1V0fTvU/uqvHlvUxcDAqMnIsDUPakjK2RDeQ38qtN6+PQ5
|
||||
/dT7vx2Wtzesqn2eDbDf5uRfSgmp2hJLJniAKjMCBVAJiOgPb0LXUIcwCGxaiWOA
|
||||
g5ZvNWjX5bZ/FxqpLpOE9OReI5YY7ns7zqP4thLYYWe0Qdp9a2ezVrgzgrh/SLla
|
||||
d73x/S9TrmLtYGGlbVUByJW+GXjW2Tt6iaa/WDFzx8NvZ/wzIAdGSEfLcvS+JBSP
|
||||
2ppdY5Ac/2dK3PzYABkHvB/rhXIwlXnrFDU9efRHZfFqQqGauA64wfdIzsDNBF2l
|
||||
nPIBDADWML9cbGMrp12CtF9b2P6z9TTT74S8iyBOzaSvdGDQY/sUtZXRg21HWamX
|
||||
nn9sSXvIDEINOQ6A9QxdxoqWdCHrOuW3ofneYXoG+zeKc4dC86wa1TR2q9vW+RMX
|
||||
SO4uImA+Uzula/6k1DogDf28qhCxMwG/i/m9g1c/0aApuDyKdQ1PXsHHNlgd/Dn6
|
||||
rrd5y2AObaifV7wIhEJnvqgFXDN2RXGjLeCOHV4Q2WTYPg/S4k1nMXVDwZXrvIsA
|
||||
0YwIMgIT86Rafp1qKlgPNbiIlC1g9RY/iFaGN2b4Ir6GDohBQSfZW2+LXoPZuVE/
|
||||
wGlQ01rh827KVZW4lXvqsge+wtnWlszcselGATyzqOK9LdHPdZGzROZYI2e8c+pa
|
||||
LNDdVPL6vdRBUnkCaEkOtl1mr2JpQi5nTU+gTX4IeInC7E+1a9UDF/Y85ybUz8XV
|
||||
8rUnR76UqVC7KidNepdHbZjjXCt8/Zo+Tec9JNbYNQB/e9ExmDntmlHEsSEQzFwz
|
||||
j8sxH48AEQEAAcLA9gQYAQoAIBYhBNGmbhojsYLJmA94jPv8yCoBXnMwBQJdpZzy
|
||||
AhsMAAoJEPv8yCoBXnMw6f8L/26C34dkjBffTzMj5Bdzm8MtF67OYneJ4TQMw7+4
|
||||
1IL4rVcSKhIhk/3Ud5knaRtP2ef1+5F66h9/RPQOJ5+tvBwhBAcUWSupKnUrdVaZ
|
||||
QanYmtSxcVV2PL9+QEiNN3tzluhaWO//rACxJ+K/ZXQlIzwQVTpNhfGzAaMVV9zp
|
||||
f3u0k14itcv6alKY8+rLZvO1wIIeRZLmU0tZDD5HtWDvUV7rIFI1WuoLb+KZgbYn
|
||||
3OWjCPHVdTrdZ2CqnZbG3SXw6awH9bzRLV9EXkbhIMez0deCVdeo+wFFklh8/5VK
|
||||
2b0vk/+wqMJxfpa1lHvJLobzOP9fvrswsr92MA2+k901WeISR7qEzcI0Fdg8AyFA
|
||||
ExaEK6VyjP7SXGLwvfisw34OxuZr3qmx1Sufu4toH3XrB7QJN8XyqqbsGxUCBqWi
|
||||
f9RSK4xjzRTe56iPeiSJJOIciMP9i2ldI+KgLycyeDvGoBj0HCLO3gVaBe4ubVrj
|
||||
5KjhX2PVNEJd3XZRzaXZE2aAMQ==
|
||||
=522n
|
||||
-----END PGP PUBLIC KEY BLOCK-----`
|
56
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_config.go
generated
vendored
Normal file
56
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_config.go
generated
vendored
Normal file
|
@ -0,0 +1,56 @@
|
|||
// Copyright (C) 2019 ProtonTech AG
|
||||
|
||||
package packet
|
||||
|
||||
import "math/bits"
|
||||
|
||||
// AEADConfig collects a number of AEAD parameters along with sensible defaults.
|
||||
// A nil AEADConfig is valid and results in all default values.
|
||||
type AEADConfig struct {
|
||||
// The AEAD mode of operation.
|
||||
DefaultMode AEADMode
|
||||
// Amount of octets in each chunk of data
|
||||
ChunkSize uint64
|
||||
}
|
||||
|
||||
// Mode returns the AEAD mode of operation.
|
||||
func (conf *AEADConfig) Mode() AEADMode {
|
||||
if conf == nil || conf.DefaultMode == 0 {
|
||||
return AEADModeEAX
|
||||
}
|
||||
mode := conf.DefaultMode
|
||||
if mode != AEADModeEAX && mode != AEADModeOCB &&
|
||||
mode != AEADModeExperimentalGCM {
|
||||
panic("AEAD mode unsupported")
|
||||
}
|
||||
return mode
|
||||
}
|
||||
|
||||
// ChunkSizeByte returns the byte indicating the chunk size. The effective
|
||||
// chunk size is computed with the formula uint64(1) << (chunkSizeByte + 6)
|
||||
func (conf *AEADConfig) ChunkSizeByte() byte {
|
||||
if conf == nil || conf.ChunkSize == 0 {
|
||||
return 12 // 1 << (12 + 6) == 262144 bytes
|
||||
}
|
||||
|
||||
chunkSize := conf.ChunkSize
|
||||
exponent := bits.Len64(chunkSize) - 1
|
||||
switch {
|
||||
case exponent < 6:
|
||||
exponent = 6
|
||||
case exponent > 27:
|
||||
exponent = 27
|
||||
}
|
||||
|
||||
return byte(exponent - 6)
|
||||
}
|
||||
|
||||
// decodeAEADChunkSize returns the effective chunk size. In 32-bit systems, the
|
||||
// maximum returned value is 1 << 30.
|
||||
func decodeAEADChunkSize(c byte) int {
|
||||
size := uint64(1 << (c + 6))
|
||||
if size != uint64(int(size)) {
|
||||
return 1 << 30
|
||||
}
|
||||
return int(size)
|
||||
}
|
364
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_encrypted.go
generated
vendored
Normal file
364
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_encrypted.go
generated
vendored
Normal file
|
@ -0,0 +1,364 @@
|
|||
// Copyright (C) 2019 ProtonTech AG
|
||||
|
||||
package packet
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
|
||||
)
|
||||
|
||||
// AEADEncrypted represents an AEAD Encrypted Packet (tag 20, RFC4880bis-5.16).
|
||||
type AEADEncrypted struct {
|
||||
cipher CipherFunction
|
||||
mode AEADMode
|
||||
chunkSizeByte byte
|
||||
Contents io.Reader // Encrypted chunks and tags
|
||||
initialNonce []byte // Referred to as IV in RFC4880-bis
|
||||
}
|
||||
|
||||
// Only currently defined version
|
||||
const aeadEncryptedVersion = 1
|
||||
|
||||
// An AEAD opener/sealer, its configuration, and data for en/decryption.
|
||||
type aeadCrypter struct {
|
||||
aead cipher.AEAD
|
||||
chunkSize int
|
||||
initialNonce []byte
|
||||
associatedData []byte // Chunk-independent associated data
|
||||
chunkIndex []byte // Chunk counter
|
||||
bytesProcessed int // Amount of plaintext bytes encrypted/decrypted
|
||||
buffer bytes.Buffer // Buffered bytes accross chunks
|
||||
}
|
||||
|
||||
// aeadEncrypter encrypts and writes bytes. It encrypts when necessary according
|
||||
// to the AEAD block size, and buffers the extra encrypted bytes for next write.
|
||||
type aeadEncrypter struct {
|
||||
aeadCrypter // Embedded plaintext sealer
|
||||
writer io.WriteCloser // 'writer' is a partialLengthWriter
|
||||
}
|
||||
|
||||
// aeadDecrypter reads and decrypts bytes. It buffers extra decrypted bytes when
|
||||
// necessary, similar to aeadEncrypter.
|
||||
type aeadDecrypter struct {
|
||||
aeadCrypter // Embedded ciphertext opener
|
||||
reader io.Reader // 'reader' is a partialLengthReader
|
||||
peekedBytes []byte // Used to detect last chunk
|
||||
eof bool
|
||||
}
|
||||
|
||||
func (ae *AEADEncrypted) parse(buf io.Reader) error {
|
||||
headerData := make([]byte, 4)
|
||||
if n, err := io.ReadFull(buf, headerData); n < 4 {
|
||||
return errors.AEADError("could not read aead header:" + err.Error())
|
||||
}
|
||||
// Read initial nonce
|
||||
mode := AEADMode(headerData[2])
|
||||
nonceLen := mode.NonceLength()
|
||||
if nonceLen == 0 {
|
||||
return errors.AEADError("unknown mode")
|
||||
}
|
||||
initialNonce := make([]byte, nonceLen)
|
||||
if n, err := io.ReadFull(buf, initialNonce); n < nonceLen {
|
||||
return errors.AEADError("could not read aead nonce:" + err.Error())
|
||||
}
|
||||
ae.Contents = buf
|
||||
ae.initialNonce = initialNonce
|
||||
c := headerData[1]
|
||||
if _, ok := algorithm.CipherById[c]; !ok {
|
||||
return errors.UnsupportedError("unknown cipher: " + string(c))
|
||||
}
|
||||
ae.cipher = CipherFunction(c)
|
||||
ae.mode = mode
|
||||
ae.chunkSizeByte = byte(headerData[3])
|
||||
return nil
|
||||
}
|
||||
|
||||
// Decrypt returns a io.ReadCloser from which decrypted bytes can be read, or
|
||||
// an error.
|
||||
func (ae *AEADEncrypted) Decrypt(ciph CipherFunction, key []byte) (io.ReadCloser, error) {
|
||||
return ae.decrypt(key)
|
||||
}
|
||||
|
||||
// decrypt prepares an aeadCrypter and returns a ReadCloser from which
|
||||
// decrypted bytes can be read (see aeadDecrypter.Read()).
|
||||
func (ae *AEADEncrypted) decrypt(key []byte) (io.ReadCloser, error) {
|
||||
blockCipher := ae.cipher.new(key)
|
||||
aead := ae.mode.new(blockCipher)
|
||||
// Carry the first tagLen bytes
|
||||
tagLen := ae.mode.TagLength()
|
||||
peekedBytes := make([]byte, tagLen)
|
||||
n, err := io.ReadFull(ae.Contents, peekedBytes)
|
||||
if n < tagLen || (err != nil && err != io.EOF) {
|
||||
return nil, errors.AEADError("Not enough data to decrypt:" + err.Error())
|
||||
}
|
||||
chunkSize := decodeAEADChunkSize(ae.chunkSizeByte)
|
||||
return &aeadDecrypter{
|
||||
aeadCrypter: aeadCrypter{
|
||||
aead: aead,
|
||||
chunkSize: chunkSize,
|
||||
initialNonce: ae.initialNonce,
|
||||
associatedData: ae.associatedData(),
|
||||
chunkIndex: make([]byte, 8),
|
||||
},
|
||||
reader: ae.Contents,
|
||||
peekedBytes: peekedBytes}, nil
|
||||
}
|
||||
|
||||
// Read decrypts bytes and reads them into dst. It decrypts when necessary and
|
||||
// buffers extra decrypted bytes. It returns the number of bytes copied into dst
|
||||
// and an error.
|
||||
func (ar *aeadDecrypter) Read(dst []byte) (n int, err error) {
|
||||
// Return buffered plaintext bytes from previous calls
|
||||
if ar.buffer.Len() > 0 {
|
||||
return ar.buffer.Read(dst)
|
||||
}
|
||||
|
||||
// Return EOF if we've previously validated the final tag
|
||||
if ar.eof {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
// Read a chunk
|
||||
tagLen := ar.aead.Overhead()
|
||||
cipherChunkBuf := new(bytes.Buffer)
|
||||
_, errRead := io.CopyN(cipherChunkBuf, ar.reader, int64(ar.chunkSize + tagLen))
|
||||
cipherChunk := cipherChunkBuf.Bytes()
|
||||
if errRead != nil && errRead != io.EOF {
|
||||
return 0, errRead
|
||||
}
|
||||
decrypted, errChunk := ar.openChunk(cipherChunk)
|
||||
if errChunk != nil {
|
||||
return 0, errChunk
|
||||
}
|
||||
|
||||
// Return decrypted bytes, buffering if necessary
|
||||
if len(dst) < len(decrypted) {
|
||||
n = copy(dst, decrypted[:len(dst)])
|
||||
ar.buffer.Write(decrypted[len(dst):])
|
||||
} else {
|
||||
n = copy(dst, decrypted)
|
||||
}
|
||||
|
||||
// Check final authentication tag
|
||||
if errRead == io.EOF {
|
||||
errChunk := ar.validateFinalTag(ar.peekedBytes)
|
||||
if errChunk != nil {
|
||||
return n, errChunk
|
||||
}
|
||||
ar.eof = true // Mark EOF for when we've returned all buffered data
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Close is noOp. The final authentication tag of the stream was already
|
||||
// checked in the last Read call. In the future, this function could be used to
|
||||
// wipe the reader and peeked, decrypted bytes, if necessary.
|
||||
func (ar *aeadDecrypter) Close() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SerializeAEADEncrypted initializes the aeadCrypter and returns a writer.
|
||||
// This writer encrypts and writes bytes (see aeadEncrypter.Write()).
|
||||
func SerializeAEADEncrypted(w io.Writer, key []byte, cipher CipherFunction, mode AEADMode, config *Config) (io.WriteCloser, error) {
|
||||
writeCloser := noOpCloser{w}
|
||||
writer, err := serializeStreamHeader(writeCloser, packetTypeAEADEncrypted)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Data for en/decryption: tag, version, cipher, aead mode, chunk size
|
||||
aeadConf := config.AEAD()
|
||||
prefix := []byte{
|
||||
0xD4,
|
||||
aeadEncryptedVersion,
|
||||
byte(config.Cipher()),
|
||||
byte(aeadConf.Mode()),
|
||||
aeadConf.ChunkSizeByte(),
|
||||
}
|
||||
n, err := writer.Write(prefix[1:])
|
||||
if err != nil || n < 4 {
|
||||
return nil, errors.AEADError("could not write AEAD headers")
|
||||
}
|
||||
// Sample nonce
|
||||
nonceLen := aeadConf.Mode().NonceLength()
|
||||
nonce := make([]byte, nonceLen)
|
||||
n, err = rand.Read(nonce)
|
||||
if err != nil {
|
||||
panic("Could not sample random nonce")
|
||||
}
|
||||
_, err = writer.Write(nonce)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blockCipher := CipherFunction(config.Cipher()).new(key)
|
||||
alg := AEADMode(aeadConf.Mode()).new(blockCipher)
|
||||
|
||||
chunkSize := decodeAEADChunkSize(aeadConf.ChunkSizeByte())
|
||||
return &aeadEncrypter{
|
||||
aeadCrypter: aeadCrypter{
|
||||
aead: alg,
|
||||
chunkSize: chunkSize,
|
||||
associatedData: prefix,
|
||||
chunkIndex: make([]byte, 8),
|
||||
initialNonce: nonce,
|
||||
},
|
||||
writer: writer}, nil
|
||||
}
|
||||
|
||||
// Write encrypts and writes bytes. It encrypts when necessary and buffers extra
|
||||
// plaintext bytes for next call. When the stream is finished, Close() MUST be
|
||||
// called to append the final tag.
|
||||
func (aw *aeadEncrypter) Write(plaintextBytes []byte) (n int, err error) {
|
||||
// Append plaintextBytes to existing buffered bytes
|
||||
n, err = aw.buffer.Write(plaintextBytes)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
// Encrypt and write chunks
|
||||
for aw.buffer.Len() >= aw.chunkSize {
|
||||
plainChunk := aw.buffer.Next(aw.chunkSize)
|
||||
encryptedChunk, err := aw.sealChunk(plainChunk)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
_, err = aw.writer.Write(encryptedChunk)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Close encrypts and writes the remaining buffered plaintext if any, appends
|
||||
// the final authentication tag, and closes the embedded writer. This function
|
||||
// MUST be called at the end of a stream.
|
||||
func (aw *aeadEncrypter) Close() (err error) {
|
||||
// Encrypt and write a chunk if there's buffered data left, or if we haven't
|
||||
// written any chunks yet.
|
||||
if aw.buffer.Len() > 0 || aw.bytesProcessed == 0 {
|
||||
plainChunk := aw.buffer.Bytes()
|
||||
lastEncryptedChunk, err := aw.sealChunk(plainChunk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = aw.writer.Write(lastEncryptedChunk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Compute final tag (associated data: packet tag, version, cipher, aead,
|
||||
// chunk size, index, total number of encrypted octets).
|
||||
adata := append(aw.associatedData[:], aw.chunkIndex[:]...)
|
||||
adata = append(adata, make([]byte, 8)...)
|
||||
binary.BigEndian.PutUint64(adata[13:], uint64(aw.bytesProcessed))
|
||||
nonce := aw.computeNextNonce()
|
||||
finalTag := aw.aead.Seal(nil, nonce, nil, adata)
|
||||
_, err = aw.writer.Write(finalTag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return aw.writer.Close()
|
||||
}
|
||||
|
||||
// sealChunk Encrypts and authenticates the given chunk.
|
||||
func (aw *aeadEncrypter) sealChunk(data []byte) ([]byte, error) {
|
||||
if len(data) > aw.chunkSize {
|
||||
return nil, errors.AEADError("chunk exceeds maximum length")
|
||||
}
|
||||
if aw.associatedData == nil {
|
||||
return nil, errors.AEADError("can't seal without headers")
|
||||
}
|
||||
adata := append(aw.associatedData, aw.chunkIndex...)
|
||||
nonce := aw.computeNextNonce()
|
||||
encrypted := aw.aead.Seal(nil, nonce, data, adata)
|
||||
aw.bytesProcessed += len(data)
|
||||
if err := aw.aeadCrypter.incrementIndex(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return encrypted, nil
|
||||
}
|
||||
|
||||
// openChunk decrypts and checks integrity of an encrypted chunk, returning
|
||||
// the underlying plaintext and an error. It access peeked bytes from next
|
||||
// chunk, to identify the last chunk and decrypt/validate accordingly.
|
||||
func (ar *aeadDecrypter) openChunk(data []byte) ([]byte, error) {
|
||||
tagLen := ar.aead.Overhead()
|
||||
// Restore carried bytes from last call
|
||||
chunkExtra := append(ar.peekedBytes, data...)
|
||||
// 'chunk' contains encrypted bytes, followed by an authentication tag.
|
||||
chunk := chunkExtra[:len(chunkExtra)-tagLen]
|
||||
ar.peekedBytes = chunkExtra[len(chunkExtra)-tagLen:]
|
||||
adata := append(ar.associatedData, ar.chunkIndex...)
|
||||
nonce := ar.computeNextNonce()
|
||||
plainChunk, err := ar.aead.Open(nil, nonce, chunk, adata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ar.bytesProcessed += len(plainChunk)
|
||||
if err = ar.aeadCrypter.incrementIndex(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return plainChunk, nil
|
||||
}
|
||||
|
||||
// Checks the summary tag. It takes into account the total decrypted bytes into
|
||||
// the associated data. It returns an error, or nil if the tag is valid.
|
||||
func (ar *aeadDecrypter) validateFinalTag(tag []byte) error {
|
||||
// Associated: tag, version, cipher, aead, chunk size, index, and octets
|
||||
amountBytes := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(amountBytes, uint64(ar.bytesProcessed))
|
||||
adata := append(ar.associatedData, ar.chunkIndex...)
|
||||
adata = append(adata, amountBytes...)
|
||||
nonce := ar.computeNextNonce()
|
||||
_, err := ar.aead.Open(nil, nonce, tag, adata)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Associated data for chunks: tag, version, cipher, mode, chunk size byte
|
||||
func (ae *AEADEncrypted) associatedData() []byte {
|
||||
return []byte{
|
||||
0xD4,
|
||||
aeadEncryptedVersion,
|
||||
byte(ae.cipher),
|
||||
byte(ae.mode),
|
||||
ae.chunkSizeByte}
|
||||
}
|
||||
|
||||
// computeNonce takes the incremental index and computes an eXclusive OR with
|
||||
// the least significant 8 bytes of the receivers' initial nonce (see sec.
|
||||
// 5.16.1 and 5.16.2). It returns the resulting nonce.
|
||||
func (wo *aeadCrypter) computeNextNonce() (nonce []byte) {
|
||||
nonce = make([]byte, len(wo.initialNonce))
|
||||
copy(nonce, wo.initialNonce)
|
||||
offset := len(wo.initialNonce) - 8
|
||||
for i := 0; i < 8; i++ {
|
||||
nonce[i+offset] ^= wo.chunkIndex[i]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// incrementIndex perfoms an integer increment by 1 of the integer represented by the
|
||||
// slice, modifying it accordingly.
|
||||
func (wo *aeadCrypter) incrementIndex() error {
|
||||
index := wo.chunkIndex
|
||||
if len(index) == 0 {
|
||||
return errors.AEADError("Index has length 0")
|
||||
}
|
||||
for i := len(index) - 1; i >= 0; i-- {
|
||||
if index[i] < 255 {
|
||||
index[i]++
|
||||
return nil
|
||||
}
|
||||
index[i] = 0
|
||||
}
|
||||
return errors.AEADError("cannot further increment index")
|
||||
}
|
|
@ -8,7 +8,7 @@ import (
|
|||
"compress/bzip2"
|
||||
"compress/flate"
|
||||
"compress/zlib"
|
||||
"golang.org/x/crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"io"
|
||||
"strconv"
|
||||
)
|
|
@ -8,6 +8,7 @@ import (
|
|||
"crypto"
|
||||
"crypto/rand"
|
||||
"io"
|
||||
"math/big"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -46,6 +47,37 @@ type Config struct {
|
|||
// RSABits is the number of bits in new RSA keys made with NewEntity.
|
||||
// If zero, then 2048 bit keys are created.
|
||||
RSABits int
|
||||
// The public key algorithm to use - will always create a signing primary
|
||||
// key and encryption subkey.
|
||||
Algorithm PublicKeyAlgorithm
|
||||
// Some known primes that are optionally prepopulated by the caller
|
||||
RSAPrimes []*big.Int
|
||||
// AEADConfig configures the use of the new AEAD Encrypted Data Packet,
|
||||
// defined in the draft of the next version of the OpenPGP specification.
|
||||
// If a non-nil AEADConfig is passed, usage of this packet is enabled. By
|
||||
// default, it is disabled. See the documentation of AEADConfig for more
|
||||
// configuration options related to AEAD.
|
||||
// **Note: using this option may break compatibility with other OpenPGP
|
||||
// implementations, as well as future versions of this library.**
|
||||
AEADConfig *AEADConfig
|
||||
// V5Keys configures version 5 key generation. If false, this package still
|
||||
// supports version 5 keys, but produces version 4 keys.
|
||||
V5Keys bool
|
||||
// "The validity period of the key. This is the number of seconds after
|
||||
// the key creation time that the key expires. If this is not present
|
||||
// or has a value of zero, the key never expires. This is found only on
|
||||
// a self-signature.""
|
||||
// https://tools.ietf.org/html/rfc4880#section-5.2.3.6
|
||||
KeyLifetimeSecs uint32
|
||||
// "The validity period of the signature. This is the number of seconds
|
||||
// after the signature creation time that the signature expires. If
|
||||
// this is not present or has a value of zero, it never expires."
|
||||
// https://tools.ietf.org/html/rfc4880#section-5.2.3.10
|
||||
SigLifetimeSecs uint32
|
||||
// SigningKeyId is used to specify the signing key to use (by Key ID).
|
||||
// By default, the signing key is selected automatically, preferring
|
||||
// signing subkeys if available.
|
||||
SigningKeyId uint64
|
||||
}
|
||||
|
||||
func (c *Config) Random() io.Reader {
|
||||
|
@ -76,6 +108,22 @@ func (c *Config) Now() time.Time {
|
|||
return c.Time()
|
||||
}
|
||||
|
||||
// KeyLifetime returns the validity period of the key.
|
||||
func (c *Config) KeyLifetime() uint32 {
|
||||
if c == nil {
|
||||
return 0
|
||||
}
|
||||
return c.KeyLifetimeSecs
|
||||
}
|
||||
|
||||
// SigLifetime returns the validity period of the signature.
|
||||
func (c *Config) SigLifetime() uint32 {
|
||||
if c == nil {
|
||||
return 0
|
||||
}
|
||||
return c.SigLifetimeSecs
|
||||
}
|
||||
|
||||
func (c *Config) Compression() CompressionAlgo {
|
||||
if c == nil {
|
||||
return CompressionNone
|
||||
|
@ -89,3 +137,31 @@ func (c *Config) PasswordHashIterations() int {
|
|||
}
|
||||
return c.S2KCount
|
||||
}
|
||||
|
||||
func (c *Config) RSAModulusBits() int {
|
||||
if c == nil || c.RSABits == 0 {
|
||||
return 2048
|
||||
}
|
||||
return c.RSABits
|
||||
}
|
||||
|
||||
func (c *Config) PublicKeyAlgorithm() PublicKeyAlgorithm {
|
||||
if c == nil || c.Algorithm == 0 {
|
||||
return PubKeyAlgoRSA
|
||||
}
|
||||
return c.Algorithm
|
||||
}
|
||||
|
||||
func (c *Config) AEAD() *AEADConfig {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.AEADConfig
|
||||
}
|
||||
|
||||
func (c *Config) SigningKey() uint64 {
|
||||
if c == nil {
|
||||
return 0
|
||||
}
|
||||
return c.SigningKeyId
|
||||
}
|
|
@ -12,8 +12,10 @@ import (
|
|||
"math/big"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/crypto/openpgp/elgamal"
|
||||
"golang.org/x/crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/ecdh"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/elgamal"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
|
||||
)
|
||||
|
||||
const encryptedKeyVersion = 3
|
||||
|
@ -26,7 +28,7 @@ type EncryptedKey struct {
|
|||
CipherFunc CipherFunction // only valid after a successful Decrypt
|
||||
Key []byte // only valid after a successful Decrypt
|
||||
|
||||
encryptedMPI1, encryptedMPI2 parsedMPI
|
||||
encryptedMPI1, encryptedMPI2 encoding.Field
|
||||
}
|
||||
|
||||
func (e *EncryptedKey) parse(r io.Reader) (err error) {
|
||||
|
@ -42,17 +44,28 @@ func (e *EncryptedKey) parse(r io.Reader) (err error) {
|
|||
e.Algo = PublicKeyAlgorithm(buf[9])
|
||||
switch e.Algo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
|
||||
e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r)
|
||||
if err != nil {
|
||||
e.encryptedMPI1 = new(encoding.MPI)
|
||||
if _, err = e.encryptedMPI1.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
case PubKeyAlgoElGamal:
|
||||
e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r)
|
||||
if err != nil {
|
||||
e.encryptedMPI1 = new(encoding.MPI)
|
||||
if _, err = e.encryptedMPI1.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
e.encryptedMPI2.bytes, e.encryptedMPI2.bitLength, err = readMPI(r)
|
||||
if err != nil {
|
||||
|
||||
e.encryptedMPI2 = new(encoding.MPI)
|
||||
if _, err = e.encryptedMPI2.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
case PubKeyAlgoECDH:
|
||||
e.encryptedMPI1 = new(encoding.MPI)
|
||||
if _, err = e.encryptedMPI1.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
e.encryptedMPI2 = new(encoding.OID)
|
||||
if _, err = e.encryptedMPI2.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -72,6 +85,16 @@ func checksumKeyMaterial(key []byte) uint16 {
|
|||
// private key must have been decrypted first.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
|
||||
if e.KeyId != 0 && e.KeyId != priv.KeyId {
|
||||
return errors.InvalidArgumentError("cannot decrypt encrypted session key for key id " + strconv.FormatUint(e.KeyId, 16) + " with private key id " + strconv.FormatUint(priv.KeyId, 16))
|
||||
}
|
||||
if e.Algo != priv.PubKeyAlgo {
|
||||
return errors.InvalidArgumentError("cannot decrypt encrypted session key of type " + strconv.Itoa(int(e.Algo)) + " with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
|
||||
}
|
||||
if priv.Dummy() {
|
||||
return errors.ErrDummyPrivateKey("dummy key found")
|
||||
}
|
||||
|
||||
var err error
|
||||
var b []byte
|
||||
|
||||
|
@ -81,13 +104,18 @@ func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
|
|||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
|
||||
// Supports both *rsa.PrivateKey and crypto.Decrypter
|
||||
k := priv.PrivateKey.(crypto.Decrypter)
|
||||
b, err = k.Decrypt(config.Random(), padToKeySize(k.Public().(*rsa.PublicKey), e.encryptedMPI1.bytes), nil)
|
||||
b, err = k.Decrypt(config.Random(), padToKeySize(k.Public().(*rsa.PublicKey), e.encryptedMPI1.Bytes()), nil)
|
||||
case PubKeyAlgoElGamal:
|
||||
c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes)
|
||||
c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes)
|
||||
c1 := new(big.Int).SetBytes(e.encryptedMPI1.Bytes())
|
||||
c2 := new(big.Int).SetBytes(e.encryptedMPI2.Bytes())
|
||||
b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2)
|
||||
case PubKeyAlgoECDH:
|
||||
vsG := e.encryptedMPI1.Bytes()
|
||||
m := e.encryptedMPI2.Bytes()
|
||||
oid := priv.PublicKey.oid.EncodedBytes()
|
||||
b, err = ecdh.Decrypt(priv.PrivateKey.(*ecdh.PrivateKey), vsG, m, oid, priv.PublicKey.Fingerprint[:])
|
||||
default:
|
||||
err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
|
||||
err = errors.InvalidArgumentError("cannot decrypt encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
@ -110,14 +138,19 @@ func (e *EncryptedKey) Serialize(w io.Writer) error {
|
|||
var mpiLen int
|
||||
switch e.Algo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
|
||||
mpiLen = 2 + len(e.encryptedMPI1.bytes)
|
||||
mpiLen = int(e.encryptedMPI1.EncodedLength())
|
||||
case PubKeyAlgoElGamal:
|
||||
mpiLen = 2 + len(e.encryptedMPI1.bytes) + 2 + len(e.encryptedMPI2.bytes)
|
||||
mpiLen = int(e.encryptedMPI1.EncodedLength()) + int(e.encryptedMPI2.EncodedLength())
|
||||
case PubKeyAlgoECDH:
|
||||
mpiLen = int(e.encryptedMPI1.EncodedLength()) + int(e.encryptedMPI2.EncodedLength())
|
||||
default:
|
||||
return errors.InvalidArgumentError("don't know how to serialize encrypted key type " + strconv.Itoa(int(e.Algo)))
|
||||
}
|
||||
|
||||
serializeHeader(w, packetTypeEncryptedKey, 1 /* version */ +8 /* key id */ +1 /* algo */ +mpiLen)
|
||||
err := serializeHeader(w, packetTypeEncryptedKey, 1 /* version */ +8 /* key id */ +1 /* algo */ +mpiLen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w.Write([]byte{encryptedKeyVersion})
|
||||
binary.Write(w, binary.BigEndian, e.KeyId)
|
||||
|
@ -125,14 +158,23 @@ func (e *EncryptedKey) Serialize(w io.Writer) error {
|
|||
|
||||
switch e.Algo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
|
||||
writeMPIs(w, e.encryptedMPI1)
|
||||
_, err := w.Write(e.encryptedMPI1.EncodedBytes())
|
||||
return err
|
||||
case PubKeyAlgoElGamal:
|
||||
writeMPIs(w, e.encryptedMPI1, e.encryptedMPI2)
|
||||
if _, err := w.Write(e.encryptedMPI1.EncodedBytes()); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := w.Write(e.encryptedMPI2.EncodedBytes())
|
||||
return err
|
||||
case PubKeyAlgoECDH:
|
||||
if _, err := w.Write(e.encryptedMPI1.EncodedBytes()); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := w.Write(e.encryptedMPI2.EncodedBytes())
|
||||
return err
|
||||
default:
|
||||
panic("internal error")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SerializeEncryptedKey serializes an encrypted key packet to w that contains
|
||||
|
@ -156,6 +198,8 @@ func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunctio
|
|||
return serializeEncryptedKeyRSA(w, config.Random(), buf, pub.PublicKey.(*rsa.PublicKey), keyBlock)
|
||||
case PubKeyAlgoElGamal:
|
||||
return serializeEncryptedKeyElGamal(w, config.Random(), buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock)
|
||||
case PubKeyAlgoECDH:
|
||||
return serializeEncryptedKeyECDH(w, config.Random(), buf, pub.PublicKey.(*ecdh.PublicKey), keyBlock, pub.oid, pub.Fingerprint)
|
||||
case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly:
|
||||
return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
|
||||
}
|
||||
|
@ -169,7 +213,8 @@ func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub
|
|||
return errors.InvalidArgumentError("RSA encryption failed: " + err.Error())
|
||||
}
|
||||
|
||||
packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText)
|
||||
cipherMPI := encoding.NewMPI(cipherText)
|
||||
packetLen := 10 /* header length */ + int(cipherMPI.EncodedLength())
|
||||
|
||||
err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
|
||||
if err != nil {
|
||||
|
@ -179,7 +224,8 @@ func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return writeMPI(w, 8*uint16(len(cipherText)), cipherText)
|
||||
_, err = w.Write(cipherMPI.EncodedBytes())
|
||||
return err
|
||||
}
|
||||
|
||||
func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) error {
|
||||
|
@ -200,9 +246,37 @@ func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte,
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = writeBig(w, c1)
|
||||
if _, err = w.Write(new(encoding.MPI).SetBig(c1).EncodedBytes()); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = w.Write(new(encoding.MPI).SetBig(c2).EncodedBytes())
|
||||
return err
|
||||
}
|
||||
|
||||
func serializeEncryptedKeyECDH(w io.Writer, rand io.Reader, header [10]byte, pub *ecdh.PublicKey, keyBlock []byte, oid encoding.Field, fingerprint []byte) error {
|
||||
vsG, c, err := ecdh.Encrypt(rand, pub, keyBlock, oid.EncodedBytes(), fingerprint)
|
||||
if err != nil {
|
||||
return errors.InvalidArgumentError("ECDH encryption failed: " + err.Error())
|
||||
}
|
||||
|
||||
g := encoding.NewMPI(vsG)
|
||||
m := encoding.NewOID(c)
|
||||
|
||||
packetLen := 10 /* header length */
|
||||
packetLen += int(g.EncodedLength()) + int(m.EncodedLength())
|
||||
|
||||
err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return writeBig(w, c2)
|
||||
|
||||
_, err = w.Write(header[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = w.Write(g.EncodedBytes()); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = w.Write(m.EncodedBytes())
|
||||
return err
|
||||
}
|
|
@ -11,6 +11,7 @@ import (
|
|||
|
||||
// LiteralData represents an encrypted file. See RFC 4880, section 5.9.
|
||||
type LiteralData struct {
|
||||
Format uint8
|
||||
IsBinary bool
|
||||
FileName string
|
||||
Time uint32 // Unix epoch time. Either creation time or modification time. 0 means undefined.
|
||||
|
@ -31,7 +32,8 @@ func (l *LiteralData) parse(r io.Reader) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
l.IsBinary = buf[0] == 'b'
|
||||
l.Format = buf[0]
|
||||
l.IsBinary = l.Format == 'b'
|
||||
fileNameLen := int(buf[1])
|
||||
|
||||
_, err = readFull(r, buf[:fileNameLen])
|
|
@ -85,8 +85,7 @@ type ocfbDecrypter struct {
|
|||
// NewOCFBDecrypter returns a cipher.Stream which decrypts data with OpenPGP's
|
||||
// cipher feedback mode using the given cipher.Block. Prefix must be the first
|
||||
// blockSize + 2 bytes of the ciphertext, where blockSize is the cipher.Block's
|
||||
// block size. If an incorrect key is detected then nil is returned. On
|
||||
// successful exit, blockSize+2 bytes of decrypted data are written into
|
||||
// block size. On successful exit, blockSize+2 bytes of decrypted data are written into
|
||||
// prefix. Resync determines if the "resynchronization step" from RFC 4880,
|
||||
// 13.9 step 7 is performed. Different parts of OpenPGP vary on this point.
|
||||
func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption) cipher.Stream {
|
||||
|
@ -112,11 +111,6 @@ func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption
|
|||
prefixCopy[blockSize] ^= x.fre[0]
|
||||
prefixCopy[blockSize+1] ^= x.fre[1]
|
||||
|
||||
if prefixCopy[blockSize-2] != prefixCopy[blockSize] ||
|
||||
prefixCopy[blockSize-1] != prefixCopy[blockSize+1] {
|
||||
return nil
|
||||
}
|
||||
|
||||
if resync {
|
||||
block.Encrypt(x.fre, prefix[2:])
|
||||
} else {
|
|
@ -7,8 +7,8 @@ package packet
|
|||
import (
|
||||
"crypto"
|
||||
"encoding/binary"
|
||||
"golang.org/x/crypto/openpgp/errors"
|
||||
"golang.org/x/crypto/openpgp/s2k"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/s2k"
|
||||
"io"
|
||||
"strconv"
|
||||
)
|
|
@ -9,7 +9,7 @@ import (
|
|||
"io"
|
||||
"io/ioutil"
|
||||
|
||||
"golang.org/x/crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
)
|
||||
|
||||
// OpaquePacket represents an OpenPGP packet as raw, unparsed data. This is
|
|
@ -4,20 +4,16 @@
|
|||
|
||||
// Package packet implements parsing and serialization of OpenPGP packets, as
|
||||
// specified in RFC 4880.
|
||||
package packet // import "golang.org/x/crypto/openpgp/packet"
|
||||
package packet // import "github.com/ProtonMail/go-crypto/openpgp/packet"
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/aes"
|
||||
"bytes"
|
||||
"crypto/cipher"
|
||||
"crypto/des"
|
||||
"crypto/rsa"
|
||||
"io"
|
||||
"math/big"
|
||||
"math/bits"
|
||||
|
||||
"golang.org/x/crypto/cast5"
|
||||
"golang.org/x/crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
|
||||
)
|
||||
|
||||
// readFull is the same as io.ReadFull except that reading zero bytes returns
|
||||
|
@ -100,68 +96,43 @@ func (r *partialLengthReader) Read(p []byte) (n int, err error) {
|
|||
// See RFC 4880, section 4.2.2.4.
|
||||
type partialLengthWriter struct {
|
||||
w io.WriteCloser
|
||||
buf bytes.Buffer
|
||||
lengthByte [1]byte
|
||||
sentFirst bool
|
||||
buf []byte
|
||||
}
|
||||
|
||||
// RFC 4880 4.2.2.4: the first partial length MUST be at least 512 octets long.
|
||||
const minFirstPartialWrite = 512
|
||||
|
||||
func (w *partialLengthWriter) Write(p []byte) (n int, err error) {
|
||||
off := 0
|
||||
if !w.sentFirst {
|
||||
if len(w.buf) > 0 || len(p) < minFirstPartialWrite {
|
||||
off = len(w.buf)
|
||||
w.buf = append(w.buf, p...)
|
||||
if len(w.buf) < minFirstPartialWrite {
|
||||
return len(p), nil
|
||||
bufLen := w.buf.Len()
|
||||
if bufLen > 512 {
|
||||
for power := uint(30); ; power-- {
|
||||
l := 1 << power
|
||||
if bufLen >= l {
|
||||
w.lengthByte[0] = 224 + uint8(power)
|
||||
_, err = w.w.Write(w.lengthByte[:])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var m int
|
||||
m, err = w.w.Write(w.buf.Next(l))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if m != l {
|
||||
return 0, io.ErrShortWrite
|
||||
}
|
||||
break
|
||||
}
|
||||
p = w.buf
|
||||
w.buf = nil
|
||||
}
|
||||
w.sentFirst = true
|
||||
}
|
||||
|
||||
power := uint8(30)
|
||||
for len(p) > 0 {
|
||||
l := 1 << power
|
||||
if len(p) < l {
|
||||
power = uint8(bits.Len32(uint32(len(p)))) - 1
|
||||
l = 1 << power
|
||||
}
|
||||
w.lengthByte[0] = 224 + power
|
||||
_, err = w.w.Write(w.lengthByte[:])
|
||||
if err == nil {
|
||||
var m int
|
||||
m, err = w.w.Write(p[:l])
|
||||
n += m
|
||||
}
|
||||
if err != nil {
|
||||
if n < off {
|
||||
return 0, err
|
||||
}
|
||||
return n - off, err
|
||||
}
|
||||
p = p[l:]
|
||||
}
|
||||
return n - off, nil
|
||||
return w.buf.Write(p)
|
||||
}
|
||||
|
||||
func (w *partialLengthWriter) Close() error {
|
||||
if len(w.buf) > 0 {
|
||||
// In this case we can't send a 512 byte packet.
|
||||
// Just send what we have.
|
||||
p := w.buf
|
||||
w.sentFirst = true
|
||||
w.buf = nil
|
||||
if _, err := w.Write(p); err != nil {
|
||||
return err
|
||||
}
|
||||
func (w *partialLengthWriter) Close() (err error) {
|
||||
len := w.buf.Len()
|
||||
err = serializeLength(w.w, len)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w.lengthByte[0] = 0
|
||||
_, err := w.w.Write(w.lengthByte[:])
|
||||
_, err = w.buf.WriteTo(w.w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -246,25 +217,43 @@ func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader,
|
|||
// serializeHeader writes an OpenPGP packet header to w. See RFC 4880, section
|
||||
// 4.2.
|
||||
func serializeHeader(w io.Writer, ptype packetType, length int) (err error) {
|
||||
var buf [6]byte
|
||||
err = serializeType(w, ptype)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return serializeLength(w, length)
|
||||
}
|
||||
|
||||
// serializeType writes an OpenPGP packet type to w. See RFC 4880, section
|
||||
// 4.2.
|
||||
func serializeType(w io.Writer, ptype packetType) (err error) {
|
||||
var buf [1]byte
|
||||
buf[0] = 0x80 | 0x40 | byte(ptype)
|
||||
_, err = w.Write(buf[:])
|
||||
return
|
||||
}
|
||||
|
||||
// serializeLength writes an OpenPGP packet length to w. See RFC 4880, section
|
||||
// 4.2.2.
|
||||
func serializeLength(w io.Writer, length int) (err error) {
|
||||
var buf [5]byte
|
||||
var n int
|
||||
|
||||
buf[0] = 0x80 | 0x40 | byte(ptype)
|
||||
if length < 192 {
|
||||
buf[1] = byte(length)
|
||||
n = 2
|
||||
buf[0] = byte(length)
|
||||
n = 1
|
||||
} else if length < 8384 {
|
||||
length -= 192
|
||||
buf[1] = 192 + byte(length>>8)
|
||||
buf[2] = byte(length)
|
||||
n = 3
|
||||
buf[0] = 192 + byte(length>>8)
|
||||
buf[1] = byte(length)
|
||||
n = 2
|
||||
} else {
|
||||
buf[1] = 255
|
||||
buf[2] = byte(length >> 24)
|
||||
buf[3] = byte(length >> 16)
|
||||
buf[4] = byte(length >> 8)
|
||||
buf[5] = byte(length)
|
||||
n = 6
|
||||
buf[0] = 255
|
||||
buf[1] = byte(length >> 24)
|
||||
buf[2] = byte(length >> 16)
|
||||
buf[3] = byte(length >> 8)
|
||||
buf[4] = byte(length)
|
||||
n = 5
|
||||
}
|
||||
|
||||
_, err = w.Write(buf[:n])
|
||||
|
@ -275,9 +264,7 @@ func serializeHeader(w io.Writer, ptype packetType, length int) (err error) {
|
|||
// length of the packet is unknown. It returns a io.WriteCloser which can be
|
||||
// used to write the contents of the packet. See RFC 4880, section 4.2.
|
||||
func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err error) {
|
||||
var buf [1]byte
|
||||
buf[0] = 0x80 | 0x40 | byte(ptype)
|
||||
_, err = w.Write(buf[:])
|
||||
err = serializeType(w, ptype)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -329,19 +316,13 @@ const (
|
|||
packetTypePublicSubkey packetType = 14
|
||||
packetTypeUserAttribute packetType = 17
|
||||
packetTypeSymmetricallyEncryptedMDC packetType = 18
|
||||
packetTypeAEADEncrypted packetType = 20
|
||||
)
|
||||
|
||||
// peekVersion detects the version of a public key packet about to
|
||||
// be read. A bufio.Reader at the original position of the io.Reader
|
||||
// is returned.
|
||||
func peekVersion(r io.Reader) (bufr *bufio.Reader, ver byte, err error) {
|
||||
bufr = bufio.NewReader(r)
|
||||
var verBuf []byte
|
||||
if verBuf, err = bufr.Peek(1); err != nil {
|
||||
return
|
||||
}
|
||||
ver = verBuf[0]
|
||||
return
|
||||
// EncryptedDataPacket holds encrypted data. It is currently implemented by
|
||||
// SymmetricallyEncrypted and AEADEncrypted.
|
||||
type EncryptedDataPacket interface {
|
||||
Decrypt(CipherFunction, []byte) (io.ReadCloser, error)
|
||||
}
|
||||
|
||||
// Read reads a single OpenPGP packet from the given io.Reader. If there is an
|
||||
|
@ -356,16 +337,7 @@ func Read(r io.Reader) (p Packet, err error) {
|
|||
case packetTypeEncryptedKey:
|
||||
p = new(EncryptedKey)
|
||||
case packetTypeSignature:
|
||||
var version byte
|
||||
// Detect signature version
|
||||
if contents, version, err = peekVersion(contents); err != nil {
|
||||
return
|
||||
}
|
||||
if version < 4 {
|
||||
p = new(SignatureV3)
|
||||
} else {
|
||||
p = new(Signature)
|
||||
}
|
||||
p = new(Signature)
|
||||
case packetTypeSymmetricKeyEncrypted:
|
||||
p = new(SymmetricKeyEncrypted)
|
||||
case packetTypeOnePassSignature:
|
||||
|
@ -377,20 +349,12 @@ func Read(r io.Reader) (p Packet, err error) {
|
|||
}
|
||||
p = pk
|
||||
case packetTypePublicKey, packetTypePublicSubkey:
|
||||
var version byte
|
||||
if contents, version, err = peekVersion(contents); err != nil {
|
||||
return
|
||||
}
|
||||
isSubkey := tag == packetTypePublicSubkey
|
||||
if version < 4 {
|
||||
p = &PublicKeyV3{IsSubkey: isSubkey}
|
||||
} else {
|
||||
p = &PublicKey{IsSubkey: isSubkey}
|
||||
}
|
||||
p = &PublicKey{IsSubkey: isSubkey}
|
||||
case packetTypeCompressed:
|
||||
p = new(Compressed)
|
||||
case packetTypeSymmetricallyEncrypted:
|
||||
p = new(SymmetricallyEncrypted)
|
||||
err = errors.UnsupportedError("Symmetrically encrypted packets without MDC are not supported")
|
||||
case packetTypeLiteralData:
|
||||
p = new(LiteralData)
|
||||
case packetTypeUserId:
|
||||
|
@ -401,6 +365,8 @@ func Read(r io.Reader) (p Packet, err error) {
|
|||
se := new(SymmetricallyEncrypted)
|
||||
se.MDC = true
|
||||
p = se
|
||||
case packetTypeAEADEncrypted:
|
||||
p = new(AEADEncrypted)
|
||||
default:
|
||||
err = errors.UnknownPacketTypeError(tag)
|
||||
}
|
||||
|
@ -418,8 +384,8 @@ func Read(r io.Reader) (p Packet, err error) {
|
|||
type SignatureType uint8
|
||||
|
||||
const (
|
||||
SigTypeBinary SignatureType = 0
|
||||
SigTypeText = 1
|
||||
SigTypeBinary SignatureType = 0x00
|
||||
SigTypeText = 0x01
|
||||
SigTypeGenericCert = 0x10
|
||||
SigTypePersonaCert = 0x11
|
||||
SigTypeCasualCert = 0x12
|
||||
|
@ -443,6 +409,8 @@ const (
|
|||
// RFC 6637, Section 5.
|
||||
PubKeyAlgoECDH PublicKeyAlgorithm = 18
|
||||
PubKeyAlgoECDSA PublicKeyAlgorithm = 19
|
||||
// https://www.ietf.org/archive/id/draft-koch-eddsa-for-openpgp-04.txt
|
||||
PubKeyAlgoEdDSA PublicKeyAlgorithm = 22
|
||||
|
||||
// Deprecated in RFC 4880, Section 13.5. Use key flags instead.
|
||||
PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2
|
||||
|
@ -453,7 +421,7 @@ const (
|
|||
// key of the given type.
|
||||
func (pka PublicKeyAlgorithm) CanEncrypt() bool {
|
||||
switch pka {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal:
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal, PubKeyAlgoECDH:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -463,7 +431,7 @@ func (pka PublicKeyAlgorithm) CanEncrypt() bool {
|
|||
// sign a message.
|
||||
func (pka PublicKeyAlgorithm) CanSign() bool {
|
||||
switch pka {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA:
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA, PubKeyAlgoEdDSA:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -471,7 +439,7 @@ func (pka PublicKeyAlgorithm) CanSign() bool {
|
|||
|
||||
// CipherFunction represents the different block ciphers specified for OpenPGP. See
|
||||
// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13
|
||||
type CipherFunction uint8
|
||||
type CipherFunction algorithm.CipherFunction
|
||||
|
||||
const (
|
||||
Cipher3DES CipherFunction = 2
|
||||
|
@ -483,81 +451,17 @@ const (
|
|||
|
||||
// KeySize returns the key size, in bytes, of cipher.
|
||||
func (cipher CipherFunction) KeySize() int {
|
||||
switch cipher {
|
||||
case Cipher3DES:
|
||||
return 24
|
||||
case CipherCAST5:
|
||||
return cast5.KeySize
|
||||
case CipherAES128:
|
||||
return 16
|
||||
case CipherAES192:
|
||||
return 24
|
||||
case CipherAES256:
|
||||
return 32
|
||||
}
|
||||
return 0
|
||||
return algorithm.CipherFunction(cipher).KeySize()
|
||||
}
|
||||
|
||||
// blockSize returns the block size, in bytes, of cipher.
|
||||
func (cipher CipherFunction) blockSize() int {
|
||||
switch cipher {
|
||||
case Cipher3DES:
|
||||
return des.BlockSize
|
||||
case CipherCAST5:
|
||||
return 8
|
||||
case CipherAES128, CipherAES192, CipherAES256:
|
||||
return 16
|
||||
}
|
||||
return 0
|
||||
return algorithm.CipherFunction(cipher).BlockSize()
|
||||
}
|
||||
|
||||
// new returns a fresh instance of the given cipher.
|
||||
func (cipher CipherFunction) new(key []byte) (block cipher.Block) {
|
||||
switch cipher {
|
||||
case Cipher3DES:
|
||||
block, _ = des.NewTripleDESCipher(key)
|
||||
case CipherCAST5:
|
||||
block, _ = cast5.NewCipher(key)
|
||||
case CipherAES128, CipherAES192, CipherAES256:
|
||||
block, _ = aes.NewCipher(key)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// readMPI reads a big integer from r. The bit length returned is the bit
|
||||
// length that was specified in r. This is preserved so that the integer can be
|
||||
// reserialized exactly.
|
||||
func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err error) {
|
||||
var buf [2]byte
|
||||
_, err = readFull(r, buf[0:])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
bitLength = uint16(buf[0])<<8 | uint16(buf[1])
|
||||
numBytes := (int(bitLength) + 7) / 8
|
||||
mpi = make([]byte, numBytes)
|
||||
_, err = readFull(r, mpi)
|
||||
// According to RFC 4880 3.2. we should check that the MPI has no leading
|
||||
// zeroes (at least when not an encrypted MPI?), but this implementation
|
||||
// does generate leading zeroes, so we keep accepting them.
|
||||
return
|
||||
}
|
||||
|
||||
// writeMPI serializes a big integer to w.
|
||||
func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) {
|
||||
// Note that we can produce leading zeroes, in violation of RFC 4880 3.2.
|
||||
// Implementations seem to be tolerant of them, and stripping them would
|
||||
// make it complex to guarantee matching re-serialization.
|
||||
_, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)})
|
||||
if err == nil {
|
||||
_, err = w.Write(mpiBytes)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// writeBig serializes a *big.Int to w.
|
||||
func writeBig(w io.Writer, i *big.Int) error {
|
||||
return writeMPI(w, uint16(i.BitLen()), i.Bytes())
|
||||
return algorithm.CipherFunction(cipher).New(key)
|
||||
}
|
||||
|
||||
// padToKeySize left-pads a MPI with zeroes to match the length of the
|
||||
|
@ -582,3 +486,37 @@ const (
|
|||
CompressionZIP CompressionAlgo = 1
|
||||
CompressionZLIB CompressionAlgo = 2
|
||||
)
|
||||
|
||||
// AEADMode represents the different Authenticated Encryption with Associated
|
||||
// Data specified for OpenPGP.
|
||||
type AEADMode algorithm.AEADMode
|
||||
|
||||
const (
|
||||
AEADModeEAX AEADMode = 1
|
||||
AEADModeOCB AEADMode = 2
|
||||
AEADModeExperimentalGCM AEADMode = 100
|
||||
)
|
||||
|
||||
func (mode AEADMode) NonceLength() int {
|
||||
return algorithm.AEADMode(mode).NonceLength()
|
||||
}
|
||||
|
||||
func (mode AEADMode) TagLength() int {
|
||||
return algorithm.AEADMode(mode).TagLength()
|
||||
}
|
||||
|
||||
// new returns a fresh instance of the given mode.
|
||||
func (mode AEADMode) new(block cipher.Block) cipher.AEAD {
|
||||
return algorithm.AEADMode(mode).New(block)
|
||||
}
|
||||
|
||||
// ReasonForRevocation represents a revocation reason code as per RFC4880
|
||||
// section 5.2.3.23.
|
||||
type ReasonForRevocation uint8
|
||||
|
||||
const (
|
||||
NoReason ReasonForRevocation = 0
|
||||
KeySuperseded ReasonForRevocation = 1
|
||||
KeyCompromised ReasonForRevocation = 2
|
||||
KeyRetired ReasonForRevocation = 3
|
||||
)
|
780
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key.go
generated
vendored
Normal file
780
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key.go
generated
vendored
Normal file
|
@ -0,0 +1,780 @@
|
|||
// Copyright 2011 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 packet
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/cipher"
|
||||
"crypto/dsa"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
|
||||
"golang.org/x/crypto/curve25519"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/ecdh"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/elgamal"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/s2k"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
)
|
||||
|
||||
// PrivateKey represents a possibly encrypted private key. See RFC 4880,
|
||||
// section 5.5.3.
|
||||
type PrivateKey struct {
|
||||
PublicKey
|
||||
Encrypted bool // if true then the private key is unavailable until Decrypt has been called.
|
||||
encryptedData []byte
|
||||
cipher CipherFunction
|
||||
s2k func(out, in []byte)
|
||||
// An *{rsa|dsa|elgamal|ecdh|ecdsa|ed25519}.PrivateKey or
|
||||
// crypto.Signer/crypto.Decrypter (Decryptor RSA only).
|
||||
PrivateKey interface{}
|
||||
sha1Checksum bool
|
||||
iv []byte
|
||||
|
||||
// Type of encryption of the S2K packet
|
||||
// Allowed values are 0 (Not encrypted), 254 (SHA1), or
|
||||
// 255 (2-byte checksum)
|
||||
s2kType S2KType
|
||||
// Full parameters of the S2K packet
|
||||
s2kParams *s2k.Params
|
||||
}
|
||||
|
||||
//S2KType s2k packet type
|
||||
type S2KType uint8
|
||||
|
||||
const (
|
||||
// S2KNON unencrypt
|
||||
S2KNON S2KType = 0
|
||||
// S2KSHA1 sha1 sum check
|
||||
S2KSHA1 S2KType = 254
|
||||
// S2KCHECKSUM sum check
|
||||
S2KCHECKSUM S2KType = 255
|
||||
)
|
||||
|
||||
func NewRSAPrivateKey(creationTime time.Time, priv *rsa.PrivateKey) *PrivateKey {
|
||||
pk := new(PrivateKey)
|
||||
pk.PublicKey = *NewRSAPublicKey(creationTime, &priv.PublicKey)
|
||||
pk.PrivateKey = priv
|
||||
return pk
|
||||
}
|
||||
|
||||
func NewDSAPrivateKey(creationTime time.Time, priv *dsa.PrivateKey) *PrivateKey {
|
||||
pk := new(PrivateKey)
|
||||
pk.PublicKey = *NewDSAPublicKey(creationTime, &priv.PublicKey)
|
||||
pk.PrivateKey = priv
|
||||
return pk
|
||||
}
|
||||
|
||||
func NewElGamalPrivateKey(creationTime time.Time, priv *elgamal.PrivateKey) *PrivateKey {
|
||||
pk := new(PrivateKey)
|
||||
pk.PublicKey = *NewElGamalPublicKey(creationTime, &priv.PublicKey)
|
||||
pk.PrivateKey = priv
|
||||
return pk
|
||||
}
|
||||
|
||||
func NewECDSAPrivateKey(creationTime time.Time, priv *ecdsa.PrivateKey) *PrivateKey {
|
||||
pk := new(PrivateKey)
|
||||
pk.PublicKey = *NewECDSAPublicKey(creationTime, &priv.PublicKey)
|
||||
pk.PrivateKey = priv
|
||||
return pk
|
||||
}
|
||||
|
||||
func NewEdDSAPrivateKey(creationTime time.Time, priv *ed25519.PrivateKey) *PrivateKey {
|
||||
pk := new(PrivateKey)
|
||||
pub := priv.Public().(ed25519.PublicKey)
|
||||
pk.PublicKey = *NewEdDSAPublicKey(creationTime, &pub)
|
||||
pk.PrivateKey = priv
|
||||
return pk
|
||||
}
|
||||
|
||||
func NewECDHPrivateKey(creationTime time.Time, priv *ecdh.PrivateKey) *PrivateKey {
|
||||
pk := new(PrivateKey)
|
||||
pk.PublicKey = *NewECDHPublicKey(creationTime, &priv.PublicKey)
|
||||
pk.PrivateKey = priv
|
||||
return pk
|
||||
}
|
||||
|
||||
// NewSignerPrivateKey creates a PrivateKey from a crypto.Signer that
|
||||
// implements RSA, ECDSA or EdDSA.
|
||||
func NewSignerPrivateKey(creationTime time.Time, signer crypto.Signer) *PrivateKey {
|
||||
pk := new(PrivateKey)
|
||||
// In general, the public Keys should be used as pointers. We still
|
||||
// type-switch on the values, for backwards-compatibility.
|
||||
switch pubkey := signer.Public().(type) {
|
||||
case *rsa.PublicKey:
|
||||
pk.PublicKey = *NewRSAPublicKey(creationTime, pubkey)
|
||||
case rsa.PublicKey:
|
||||
pk.PublicKey = *NewRSAPublicKey(creationTime, &pubkey)
|
||||
case *ecdsa.PublicKey:
|
||||
pk.PublicKey = *NewECDSAPublicKey(creationTime, pubkey)
|
||||
case ecdsa.PublicKey:
|
||||
pk.PublicKey = *NewECDSAPublicKey(creationTime, &pubkey)
|
||||
case *ed25519.PublicKey:
|
||||
pk.PublicKey = *NewEdDSAPublicKey(creationTime, pubkey)
|
||||
case ed25519.PublicKey:
|
||||
pk.PublicKey = *NewEdDSAPublicKey(creationTime, &pubkey)
|
||||
default:
|
||||
panic("openpgp: unknown crypto.Signer type in NewSignerPrivateKey")
|
||||
}
|
||||
pk.PrivateKey = signer
|
||||
return pk
|
||||
}
|
||||
|
||||
// NewDecrypterPrivateKey creates a PrivateKey from a *{rsa|elgamal|ecdh}.PrivateKey.
|
||||
func NewDecrypterPrivateKey(creationTime time.Time, decrypter interface{}) *PrivateKey {
|
||||
pk := new(PrivateKey)
|
||||
switch priv := decrypter.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
pk.PublicKey = *NewRSAPublicKey(creationTime, &priv.PublicKey)
|
||||
case *elgamal.PrivateKey:
|
||||
pk.PublicKey = *NewElGamalPublicKey(creationTime, &priv.PublicKey)
|
||||
case *ecdh.PrivateKey:
|
||||
pk.PublicKey = *NewECDHPublicKey(creationTime, &priv.PublicKey)
|
||||
default:
|
||||
panic("openpgp: unknown decrypter type in NewDecrypterPrivateKey")
|
||||
}
|
||||
pk.PrivateKey = decrypter
|
||||
return pk
|
||||
}
|
||||
|
||||
func (pk *PrivateKey) parse(r io.Reader) (err error) {
|
||||
err = (&pk.PublicKey).parse(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
v5 := pk.PublicKey.Version == 5
|
||||
|
||||
var buf [1]byte
|
||||
_, err = readFull(r, buf[:])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
pk.s2kType = S2KType(buf[0])
|
||||
var optCount [1]byte
|
||||
if v5 {
|
||||
if _, err = readFull(r, optCount[:]); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
switch pk.s2kType {
|
||||
case S2KNON:
|
||||
pk.s2k = nil
|
||||
pk.Encrypted = false
|
||||
case S2KSHA1, S2KCHECKSUM:
|
||||
if v5 && pk.s2kType == S2KCHECKSUM {
|
||||
return errors.StructuralError("wrong s2k identifier for version 5")
|
||||
}
|
||||
_, err = readFull(r, buf[:])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
pk.cipher = CipherFunction(buf[0])
|
||||
pk.s2kParams, err = s2k.ParseIntoParams(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if pk.s2kParams.Dummy() {
|
||||
return
|
||||
}
|
||||
pk.s2k, err = pk.s2kParams.Function()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
pk.Encrypted = true
|
||||
if pk.s2kType == S2KSHA1 {
|
||||
pk.sha1Checksum = true
|
||||
}
|
||||
default:
|
||||
return errors.UnsupportedError("deprecated s2k function in private key")
|
||||
}
|
||||
|
||||
if pk.Encrypted {
|
||||
blockSize := pk.cipher.blockSize()
|
||||
if blockSize == 0 {
|
||||
return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher)))
|
||||
}
|
||||
pk.iv = make([]byte, blockSize)
|
||||
_, err = readFull(r, pk.iv)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var privateKeyData []byte
|
||||
if v5 {
|
||||
var n [4]byte /* secret material four octet count */
|
||||
_, err = readFull(r, n[:])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count := uint32(uint32(n[0])<<24 | uint32(n[1])<<16 | uint32(n[2])<<8 | uint32(n[3]))
|
||||
if !pk.Encrypted {
|
||||
count = count + 2 /* two octet checksum */
|
||||
}
|
||||
privateKeyData = make([]byte, count)
|
||||
_, err = readFull(r, privateKeyData)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
privateKeyData, err = ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if !pk.Encrypted {
|
||||
return pk.parsePrivateKey(privateKeyData)
|
||||
}
|
||||
|
||||
pk.encryptedData = privateKeyData
|
||||
return
|
||||
}
|
||||
|
||||
// Dummy returns true if the private key is a dummy key. This is a GNU extension.
|
||||
func (pk *PrivateKey) Dummy() bool {
|
||||
return pk.s2kParams.Dummy()
|
||||
}
|
||||
|
||||
func mod64kHash(d []byte) uint16 {
|
||||
var h uint16
|
||||
for _, b := range d {
|
||||
h += uint16(b)
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
|
||||
contents := bytes.NewBuffer(nil)
|
||||
err = pk.PublicKey.serializeWithoutHeaders(contents)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = contents.Write([]byte{uint8(pk.s2kType)}); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
optional := bytes.NewBuffer(nil)
|
||||
if pk.Encrypted || pk.Dummy() {
|
||||
optional.Write([]byte{uint8(pk.cipher)})
|
||||
if err := pk.s2kParams.Serialize(optional); err != nil {
|
||||
return err
|
||||
}
|
||||
if pk.Encrypted {
|
||||
optional.Write(pk.iv)
|
||||
}
|
||||
}
|
||||
if pk.Version == 5 {
|
||||
contents.Write([]byte{uint8(optional.Len())})
|
||||
}
|
||||
io.Copy(contents, optional)
|
||||
|
||||
if !pk.Dummy() {
|
||||
l := 0
|
||||
var priv []byte
|
||||
if !pk.Encrypted {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
err = pk.serializePrivateKey(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l = buf.Len()
|
||||
if pk.sha1Checksum {
|
||||
h := sha1.New()
|
||||
h.Write(buf.Bytes())
|
||||
buf.Write(h.Sum(nil))
|
||||
} else {
|
||||
checksum := mod64kHash(buf.Bytes())
|
||||
buf.Write([]byte{byte(checksum >> 8), byte(checksum)})
|
||||
}
|
||||
priv = buf.Bytes()
|
||||
} else {
|
||||
priv, l = pk.encryptedData, len(pk.encryptedData)
|
||||
}
|
||||
|
||||
if pk.Version == 5 {
|
||||
contents.Write([]byte{byte(l >> 24), byte(l >> 16), byte(l >> 8), byte(l)})
|
||||
}
|
||||
contents.Write(priv)
|
||||
}
|
||||
|
||||
ptype := packetTypePrivateKey
|
||||
if pk.IsSubkey {
|
||||
ptype = packetTypePrivateSubkey
|
||||
}
|
||||
err = serializeHeader(w, ptype, contents.Len())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, err = io.Copy(w, contents)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error {
|
||||
if _, err := w.Write(new(encoding.MPI).SetBig(priv.D).EncodedBytes()); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := w.Write(new(encoding.MPI).SetBig(priv.Primes[1]).EncodedBytes()); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := w.Write(new(encoding.MPI).SetBig(priv.Primes[0]).EncodedBytes()); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := w.Write(new(encoding.MPI).SetBig(priv.Precomputed.Qinv).EncodedBytes())
|
||||
return err
|
||||
}
|
||||
|
||||
func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error {
|
||||
_, err := w.Write(new(encoding.MPI).SetBig(priv.X).EncodedBytes())
|
||||
return err
|
||||
}
|
||||
|
||||
func serializeElGamalPrivateKey(w io.Writer, priv *elgamal.PrivateKey) error {
|
||||
_, err := w.Write(new(encoding.MPI).SetBig(priv.X).EncodedBytes())
|
||||
return err
|
||||
}
|
||||
|
||||
func serializeECDSAPrivateKey(w io.Writer, priv *ecdsa.PrivateKey) error {
|
||||
_, err := w.Write(new(encoding.MPI).SetBig(priv.D).EncodedBytes())
|
||||
return err
|
||||
}
|
||||
|
||||
func serializeEdDSAPrivateKey(w io.Writer, priv *ed25519.PrivateKey) error {
|
||||
keySize := ed25519.PrivateKeySize - ed25519.PublicKeySize
|
||||
_, err := w.Write(encoding.NewMPI((*priv)[:keySize]).EncodedBytes())
|
||||
return err
|
||||
}
|
||||
|
||||
func serializeECDHPrivateKey(w io.Writer, priv *ecdh.PrivateKey) error {
|
||||
_, err := w.Write(encoding.NewMPI(priv.D).EncodedBytes())
|
||||
return err
|
||||
}
|
||||
|
||||
// Decrypt decrypts an encrypted private key using a passphrase.
|
||||
func (pk *PrivateKey) Decrypt(passphrase []byte) error {
|
||||
if pk.Dummy() {
|
||||
return errors.ErrDummyPrivateKey("dummy key found")
|
||||
}
|
||||
if !pk.Encrypted {
|
||||
return nil
|
||||
}
|
||||
|
||||
key := make([]byte, pk.cipher.KeySize())
|
||||
pk.s2k(key, passphrase)
|
||||
block := pk.cipher.new(key)
|
||||
cfb := cipher.NewCFBDecrypter(block, pk.iv)
|
||||
|
||||
data := make([]byte, len(pk.encryptedData))
|
||||
cfb.XORKeyStream(data, pk.encryptedData)
|
||||
|
||||
if pk.sha1Checksum {
|
||||
if len(data) < sha1.Size {
|
||||
return errors.StructuralError("truncated private key data")
|
||||
}
|
||||
h := sha1.New()
|
||||
h.Write(data[:len(data)-sha1.Size])
|
||||
sum := h.Sum(nil)
|
||||
if !bytes.Equal(sum, data[len(data)-sha1.Size:]) {
|
||||
return errors.StructuralError("private key checksum failure")
|
||||
}
|
||||
data = data[:len(data)-sha1.Size]
|
||||
} else {
|
||||
if len(data) < 2 {
|
||||
return errors.StructuralError("truncated private key data")
|
||||
}
|
||||
var sum uint16
|
||||
for i := 0; i < len(data)-2; i++ {
|
||||
sum += uint16(data[i])
|
||||
}
|
||||
if data[len(data)-2] != uint8(sum>>8) ||
|
||||
data[len(data)-1] != uint8(sum) {
|
||||
return errors.StructuralError("private key checksum failure")
|
||||
}
|
||||
data = data[:len(data)-2]
|
||||
}
|
||||
|
||||
err := pk.parsePrivateKey(data)
|
||||
if _, ok := err.(errors.KeyInvalidError); ok {
|
||||
return errors.KeyInvalidError("invalid key parameters")
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Mark key as unencrypted
|
||||
pk.s2kType = S2KNON
|
||||
pk.s2k = nil
|
||||
pk.Encrypted = false
|
||||
pk.encryptedData = nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Encrypt encrypts an unencrypted private key using a passphrase.
|
||||
func (pk *PrivateKey) Encrypt(passphrase []byte) error {
|
||||
priv := bytes.NewBuffer(nil)
|
||||
err := pk.serializePrivateKey(priv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//Default config of private key encryption
|
||||
pk.cipher = CipherAES256
|
||||
s2kConfig := &s2k.Config{
|
||||
S2KMode: 3, //Iterated
|
||||
S2KCount: 65536,
|
||||
Hash: crypto.SHA256,
|
||||
}
|
||||
|
||||
pk.s2kParams, err = s2k.Generate(rand.Reader, s2kConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
privateKeyBytes := priv.Bytes()
|
||||
key := make([]byte, pk.cipher.KeySize())
|
||||
|
||||
pk.sha1Checksum = true
|
||||
pk.s2k, err = pk.s2kParams.Function()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pk.s2k(key, passphrase)
|
||||
block := pk.cipher.new(key)
|
||||
pk.iv = make([]byte, pk.cipher.blockSize())
|
||||
_, err = rand.Read(pk.iv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfb := cipher.NewCFBEncrypter(block, pk.iv)
|
||||
|
||||
if pk.sha1Checksum {
|
||||
pk.s2kType = S2KSHA1
|
||||
h := sha1.New()
|
||||
h.Write(privateKeyBytes)
|
||||
sum := h.Sum(nil)
|
||||
privateKeyBytes = append(privateKeyBytes, sum...)
|
||||
} else {
|
||||
pk.s2kType = S2KCHECKSUM
|
||||
var sum uint16
|
||||
for _, b := range privateKeyBytes {
|
||||
sum += uint16(b)
|
||||
}
|
||||
priv.Write([]byte{uint8(sum >> 8), uint8(sum)})
|
||||
}
|
||||
|
||||
pk.encryptedData = make([]byte, len(privateKeyBytes))
|
||||
cfb.XORKeyStream(pk.encryptedData, privateKeyBytes)
|
||||
pk.Encrypted = true
|
||||
pk.PrivateKey = nil
|
||||
return err
|
||||
}
|
||||
|
||||
func (pk *PrivateKey) serializePrivateKey(w io.Writer) (err error) {
|
||||
switch priv := pk.PrivateKey.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
err = serializeRSAPrivateKey(w, priv)
|
||||
case *dsa.PrivateKey:
|
||||
err = serializeDSAPrivateKey(w, priv)
|
||||
case *elgamal.PrivateKey:
|
||||
err = serializeElGamalPrivateKey(w, priv)
|
||||
case *ecdsa.PrivateKey:
|
||||
err = serializeECDSAPrivateKey(w, priv)
|
||||
case *ed25519.PrivateKey:
|
||||
err = serializeEdDSAPrivateKey(w, priv)
|
||||
case *ecdh.PrivateKey:
|
||||
err = serializeECDHPrivateKey(w, priv)
|
||||
default:
|
||||
err = errors.InvalidArgumentError("unknown private key type")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) {
|
||||
switch pk.PublicKey.PubKeyAlgo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly:
|
||||
return pk.parseRSAPrivateKey(data)
|
||||
case PubKeyAlgoDSA:
|
||||
return pk.parseDSAPrivateKey(data)
|
||||
case PubKeyAlgoElGamal:
|
||||
return pk.parseElGamalPrivateKey(data)
|
||||
case PubKeyAlgoECDSA:
|
||||
return pk.parseECDSAPrivateKey(data)
|
||||
case PubKeyAlgoECDH:
|
||||
return pk.parseECDHPrivateKey(data)
|
||||
case PubKeyAlgoEdDSA:
|
||||
return pk.parseEdDSAPrivateKey(data)
|
||||
}
|
||||
panic("impossible")
|
||||
}
|
||||
|
||||
func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) {
|
||||
rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey)
|
||||
rsaPriv := new(rsa.PrivateKey)
|
||||
rsaPriv.PublicKey = *rsaPub
|
||||
|
||||
buf := bytes.NewBuffer(data)
|
||||
d := new(encoding.MPI)
|
||||
if _, err := d.ReadFrom(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p := new(encoding.MPI)
|
||||
if _, err := p.ReadFrom(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
q := new(encoding.MPI)
|
||||
if _, err := q.ReadFrom(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rsaPriv.D = new(big.Int).SetBytes(d.Bytes())
|
||||
rsaPriv.Primes = make([]*big.Int, 2)
|
||||
rsaPriv.Primes[0] = new(big.Int).SetBytes(p.Bytes())
|
||||
rsaPriv.Primes[1] = new(big.Int).SetBytes(q.Bytes())
|
||||
if err := rsaPriv.Validate(); err != nil {
|
||||
return errors.KeyInvalidError(err.Error())
|
||||
}
|
||||
rsaPriv.Precompute()
|
||||
pk.PrivateKey = rsaPriv
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) {
|
||||
dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey)
|
||||
dsaPriv := new(dsa.PrivateKey)
|
||||
dsaPriv.PublicKey = *dsaPub
|
||||
|
||||
buf := bytes.NewBuffer(data)
|
||||
x := new(encoding.MPI)
|
||||
if _, err := x.ReadFrom(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dsaPriv.X = new(big.Int).SetBytes(x.Bytes())
|
||||
if err := validateDSAParameters(dsaPriv); err != nil {
|
||||
return err
|
||||
}
|
||||
pk.PrivateKey = dsaPriv
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) {
|
||||
pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey)
|
||||
priv := new(elgamal.PrivateKey)
|
||||
priv.PublicKey = *pub
|
||||
|
||||
buf := bytes.NewBuffer(data)
|
||||
x := new(encoding.MPI)
|
||||
if _, err := x.ReadFrom(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
priv.X = new(big.Int).SetBytes(x.Bytes())
|
||||
if err := validateElGamalParameters(priv); err != nil {
|
||||
return err
|
||||
}
|
||||
pk.PrivateKey = priv
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) {
|
||||
ecdsaPub := pk.PublicKey.PublicKey.(*ecdsa.PublicKey)
|
||||
ecdsaPriv := new(ecdsa.PrivateKey)
|
||||
ecdsaPriv.PublicKey = *ecdsaPub
|
||||
|
||||
buf := bytes.NewBuffer(data)
|
||||
d := new(encoding.MPI)
|
||||
if _, err := d.ReadFrom(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ecdsaPriv.D = new(big.Int).SetBytes(d.Bytes())
|
||||
if err := validateECDSAParameters(ecdsaPriv); err != nil {
|
||||
return err
|
||||
}
|
||||
pk.PrivateKey = ecdsaPriv
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pk *PrivateKey) parseECDHPrivateKey(data []byte) (err error) {
|
||||
ecdhPub := pk.PublicKey.PublicKey.(*ecdh.PublicKey)
|
||||
ecdhPriv := new(ecdh.PrivateKey)
|
||||
ecdhPriv.PublicKey = *ecdhPub
|
||||
|
||||
buf := bytes.NewBuffer(data)
|
||||
d := new(encoding.MPI)
|
||||
if _, err := d.ReadFrom(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ecdhPriv.D = d.Bytes()
|
||||
if err := validateECDHParameters(ecdhPriv); err != nil {
|
||||
return err
|
||||
}
|
||||
pk.PrivateKey = ecdhPriv
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pk *PrivateKey) parseEdDSAPrivateKey(data []byte) (err error) {
|
||||
eddsaPub := pk.PublicKey.PublicKey.(*ed25519.PublicKey)
|
||||
eddsaPriv := make(ed25519.PrivateKey, ed25519.PrivateKeySize)
|
||||
|
||||
buf := bytes.NewBuffer(data)
|
||||
d := new(encoding.MPI)
|
||||
if _, err := d.ReadFrom(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
priv := d.Bytes()
|
||||
copy(eddsaPriv[32-len(priv):32], priv)
|
||||
copy(eddsaPriv[32:], (*eddsaPub)[:])
|
||||
if err := validateEdDSAParameters(&eddsaPriv); err != nil {
|
||||
return err
|
||||
}
|
||||
pk.PrivateKey = &eddsaPriv
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateECDSAParameters(priv *ecdsa.PrivateKey) error {
|
||||
return validateCommonECC(priv.Curve, priv.D.Bytes(), priv.X, priv.Y)
|
||||
}
|
||||
|
||||
func validateECDHParameters(priv *ecdh.PrivateKey) error {
|
||||
if priv.CurveType != ecc.Curve25519 {
|
||||
return validateCommonECC(priv.Curve, priv.D, priv.X, priv.Y)
|
||||
}
|
||||
// Handle Curve25519
|
||||
Q := priv.X.Bytes()[1:]
|
||||
var d [32]byte
|
||||
// Copy reversed d
|
||||
l := len(priv.D)
|
||||
for i := 0; i < l; i++ {
|
||||
d[i] = priv.D[l-i-1]
|
||||
}
|
||||
var expectedQ [32]byte
|
||||
curve25519.ScalarBaseMult(&expectedQ, &d)
|
||||
if !bytes.Equal(Q, expectedQ[:]) {
|
||||
return errors.KeyInvalidError("ECDH curve25519: invalid point")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateCommonECC(curve elliptic.Curve, d []byte, X, Y *big.Int) error {
|
||||
// the public point should not be at infinity (0,0)
|
||||
zero := new(big.Int)
|
||||
if X.Cmp(zero) == 0 && Y.Cmp(zero) == 0 {
|
||||
return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): infinity point", curve.Params().Name))
|
||||
}
|
||||
// re-derive the public point Q' = (X,Y) = dG
|
||||
// to compare to declared Q in public key
|
||||
expectedX, expectedY := curve.ScalarBaseMult(d)
|
||||
if X.Cmp(expectedX) != 0 || Y.Cmp(expectedY) != 0 {
|
||||
return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): invalid point", curve.Params().Name))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateEdDSAParameters(priv *ed25519.PrivateKey) error {
|
||||
// In EdDSA, the serialized public point is stored as part of private key (together with the seed),
|
||||
// hence we can re-derive the key from the seed
|
||||
seed := priv.Seed()
|
||||
expectedPriv := ed25519.NewKeyFromSeed(seed)
|
||||
if !bytes.Equal(*priv, expectedPriv) {
|
||||
return errors.KeyInvalidError("eddsa: invalid point")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateDSAParameters(priv *dsa.PrivateKey) error {
|
||||
p := priv.P // group prime
|
||||
q := priv.Q // subgroup order
|
||||
g := priv.G // g has order q mod p
|
||||
x := priv.X // secret
|
||||
y := priv.Y // y == g**x mod p
|
||||
one := big.NewInt(1)
|
||||
// expect g, y >= 2 and g < p
|
||||
if g.Cmp(one) <= 0 || y.Cmp(one) <= 0 || g.Cmp(p) > 0 {
|
||||
return errors.KeyInvalidError("dsa: invalid group")
|
||||
}
|
||||
// expect p > q
|
||||
if p.Cmp(q) <= 0 {
|
||||
return errors.KeyInvalidError("dsa: invalid group prime")
|
||||
}
|
||||
// q should be large enough and divide p-1
|
||||
pSub1 := new(big.Int).Sub(p, one)
|
||||
if q.BitLen() < 150 || new(big.Int).Mod(pSub1, q).Cmp(big.NewInt(0)) != 0 {
|
||||
return errors.KeyInvalidError("dsa: invalid order")
|
||||
}
|
||||
// confirm that g has order q mod p
|
||||
if !q.ProbablyPrime(32) || new(big.Int).Exp(g, q, p).Cmp(one) != 0 {
|
||||
return errors.KeyInvalidError("dsa: invalid order")
|
||||
}
|
||||
// check y
|
||||
if new(big.Int).Exp(g, x, p).Cmp(y) != 0 {
|
||||
return errors.KeyInvalidError("dsa: mismatching values")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateElGamalParameters(priv *elgamal.PrivateKey) error {
|
||||
p := priv.P // group prime
|
||||
g := priv.G // g has order p-1 mod p
|
||||
x := priv.X // secret
|
||||
y := priv.Y // y == g**x mod p
|
||||
one := big.NewInt(1)
|
||||
// Expect g, y >= 2 and g < p
|
||||
if g.Cmp(one) <= 0 || y.Cmp(one) <= 0 || g.Cmp(p) > 0 {
|
||||
return errors.KeyInvalidError("elgamal: invalid group")
|
||||
}
|
||||
if p.BitLen() < 1024 {
|
||||
return errors.KeyInvalidError("elgamal: group order too small")
|
||||
}
|
||||
pSub1 := new(big.Int).Sub(p, one)
|
||||
if new(big.Int).Exp(g, pSub1, p).Cmp(one) != 0 {
|
||||
return errors.KeyInvalidError("elgamal: invalid group")
|
||||
}
|
||||
// Since p-1 is not prime, g might have a smaller order that divides p-1.
|
||||
// We cannot confirm the exact order of g, but we make sure it is not too small.
|
||||
gExpI := new(big.Int).Set(g)
|
||||
i := 1
|
||||
threshold := 2 << 17 // we want order > threshold
|
||||
for i < threshold {
|
||||
i++ // we check every order to make sure key validation is not easily bypassed by guessing y'
|
||||
gExpI.Mod(new(big.Int).Mul(gExpI, g), p)
|
||||
if gExpI.Cmp(one) == 0 {
|
||||
return errors.KeyInvalidError("elgamal: order too small")
|
||||
}
|
||||
}
|
||||
// Check y
|
||||
if new(big.Int).Exp(g, x, p).Cmp(y) != 0 {
|
||||
return errors.KeyInvalidError("elgamal: mismatching values")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
12
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key_test_data.go
generated
vendored
Normal file
12
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key_test_data.go
generated
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
package packet
|
||||
|
||||
// Generated with `gpg --export-secret-keys "Test Key 2"`
|
||||
const privKeyRSAHex = "9501fe044cc349a8010400b70ca0010e98c090008d45d1ee8f9113bd5861fd57b88bacb7c68658747663f1e1a3b5a98f32fda6472373c024b97359cd2efc88ff60f77751adfbf6af5e615e6a1408cfad8bf0cea30b0d5f53aa27ad59089ba9b15b7ebc2777a25d7b436144027e3bcd203909f147d0e332b240cf63d3395f5dfe0df0a6c04e8655af7eacdf0011010001fe0303024a252e7d475fd445607de39a265472aa74a9320ba2dac395faa687e9e0336aeb7e9a7397e511b5afd9dc84557c80ac0f3d4d7bfec5ae16f20d41c8c84a04552a33870b930420e230e179564f6d19bb153145e76c33ae993886c388832b0fa042ddda7f133924f3854481533e0ede31d51278c0519b29abc3bf53da673e13e3e1214b52413d179d7f66deee35cac8eacb060f78379d70ef4af8607e68131ff529439668fc39c9ce6dfef8a5ac234d234802cbfb749a26107db26406213ae5c06d4673253a3cbee1fcbae58d6ab77e38d6e2c0e7c6317c48e054edadb5a40d0d48acb44643d998139a8a66bb820be1f3f80185bc777d14b5954b60effe2448a036d565c6bc0b915fcea518acdd20ab07bc1529f561c58cd044f723109b93f6fd99f876ff891d64306b5d08f48bab59f38695e9109c4dec34013ba3153488ce070268381ba923ee1eb77125b36afcb4347ec3478c8f2735b06ef17351d872e577fa95d0c397c88c71b59629a36aec"
|
||||
|
||||
// Generated by `gpg --export-secret-keys` followed by a manual extraction of
|
||||
// the ElGamal subkey from the packets.
|
||||
const privKeyElGamalHex = "9d0157044df9ee1a100400eb8e136a58ec39b582629cdadf830bc64e0a94ed8103ca8bb247b27b11b46d1d25297ef4bcc3071785ba0c0bedfe89eabc5287fcc0edf81ab5896c1c8e4b20d27d79813c7aede75320b33eaeeaa586edc00fd1036c10133e6ba0ff277245d0d59d04b2b3421b7244aca5f4a8d870c6f1c1fbff9e1c26699a860b9504f35ca1d700030503fd1ededd3b840795be6d9ccbe3c51ee42e2f39233c432b831ddd9c4e72b7025a819317e47bf94f9ee316d7273b05d5fcf2999c3a681f519b1234bbfa6d359b4752bd9c3f77d6b6456cde152464763414ca130f4e91d91041432f90620fec0e6d6b5116076c2985d5aeaae13be492b9b329efcaf7ee25120159a0a30cd976b42d7afe030302dae7eb80db744d4960c4df930d57e87fe81412eaace9f900e6c839817a614ddb75ba6603b9417c33ea7b6c93967dfa2bcff3fa3c74a5ce2c962db65b03aece14c96cbd0038fc"
|
||||
|
||||
// pkcs1PrivKeyHex is a PKCS#1, RSA private key.
|
||||
// Generated by `openssl genrsa 1024 | openssl rsa -outform DER | xxd -p`
|
||||
const pkcs1PrivKeyHex = "3082025d02010002818100e98edfa1c3b35884a54d0b36a6a603b0290fa85e49e30fa23fc94fef9c6790bc4849928607aa48d809da326fb42a969d06ad756b98b9c1a90f5d4a2b6d0ac05953c97f4da3120164a21a679793ce181c906dc01d235cc085ddcdf6ea06c389b6ab8885dfd685959e693138856a68a7e5db263337ff82a088d583a897cf2d59e9020301000102818100b6d5c9eb70b02d5369b3ee5b520a14490b5bde8a317d36f7e4c74b7460141311d1e5067735f8f01d6f5908b2b96fbd881f7a1ab9a84d82753e39e19e2d36856be960d05ac9ef8e8782ea1b6d65aee28fdfe1d61451e8cff0adfe84322f12cf455028b581cf60eb9e0e140ba5d21aeba6c2634d7c65318b9a665fc01c3191ca21024100fa5e818da3705b0fa33278bb28d4b6f6050388af2d4b75ec9375dd91ccf2e7d7068086a8b82a8f6282e4fbbdb8a7f2622eb97295249d87acea7f5f816f54d347024100eecf9406d7dc49cdfb95ab1eff4064de84c7a30f64b2798936a0d2018ba9eb52e4b636f82e96c49cc63b80b675e91e40d1b2e4017d4b9adaf33ab3d9cf1c214f024100c173704ace742c082323066226a4655226819a85304c542b9dacbeacbf5d1881ee863485fcf6f59f3a604f9b42289282067447f2b13dfeed3eab7851fc81e0550240741fc41f3fc002b382eed8730e33c5d8de40256e4accee846667f536832f711ab1d4590e7db91a8a116ac5bff3be13d3f9243ff2e976662aa9b395d907f8e9c9024046a5696c9ef882363e06c9fa4e2f5b580906452befba03f4a99d0f873697ef1f851d2226ca7934b30b7c3e80cb634a67172bbbf4781735fe3e09263e2dd723e7"
|
825
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go
generated
vendored
Normal file
825
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go
generated
vendored
Normal file
|
@ -0,0 +1,825 @@
|
|||
// Copyright 2011 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 packet
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/dsa"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
_ "crypto/sha512"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/ecdh"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/elgamal"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
)
|
||||
|
||||
type kdfHashFunction byte
|
||||
type kdfAlgorithm byte
|
||||
|
||||
// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
|
||||
type PublicKey struct {
|
||||
Version int
|
||||
CreationTime time.Time
|
||||
PubKeyAlgo PublicKeyAlgorithm
|
||||
PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey or *eddsa.PublicKey
|
||||
Fingerprint []byte
|
||||
KeyId uint64
|
||||
IsSubkey bool
|
||||
|
||||
// RFC 4880 fields
|
||||
n, e, p, q, g, y encoding.Field
|
||||
|
||||
// RFC 6637 fields
|
||||
// oid contains the OID byte sequence identifying the elliptic curve used
|
||||
oid encoding.Field
|
||||
|
||||
// kdf stores key derivation function parameters
|
||||
// used for ECDH encryption. See RFC 6637, Section 9.
|
||||
kdf encoding.Field
|
||||
}
|
||||
|
||||
// UpgradeToV5 updates the version of the key to v5, and updates all necessary
|
||||
// fields.
|
||||
func (pk *PublicKey) UpgradeToV5() {
|
||||
pk.Version = 5
|
||||
pk.setFingerprintAndKeyId()
|
||||
}
|
||||
|
||||
// signingKey provides a convenient abstraction over signature verification
|
||||
// for v3 and v4 public keys.
|
||||
type signingKey interface {
|
||||
SerializeForHash(io.Writer) error
|
||||
SerializeSignaturePrefix(io.Writer)
|
||||
serializeWithoutHeaders(io.Writer) error
|
||||
}
|
||||
|
||||
// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
|
||||
func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey {
|
||||
pk := &PublicKey{
|
||||
Version: 4,
|
||||
CreationTime: creationTime,
|
||||
PubKeyAlgo: PubKeyAlgoRSA,
|
||||
PublicKey: pub,
|
||||
n: new(encoding.MPI).SetBig(pub.N),
|
||||
e: new(encoding.MPI).SetBig(big.NewInt(int64(pub.E))),
|
||||
}
|
||||
|
||||
pk.setFingerprintAndKeyId()
|
||||
return pk
|
||||
}
|
||||
|
||||
// NewDSAPublicKey returns a PublicKey that wraps the given dsa.PublicKey.
|
||||
func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey {
|
||||
pk := &PublicKey{
|
||||
Version: 4,
|
||||
CreationTime: creationTime,
|
||||
PubKeyAlgo: PubKeyAlgoDSA,
|
||||
PublicKey: pub,
|
||||
p: new(encoding.MPI).SetBig(pub.P),
|
||||
q: new(encoding.MPI).SetBig(pub.Q),
|
||||
g: new(encoding.MPI).SetBig(pub.G),
|
||||
y: new(encoding.MPI).SetBig(pub.Y),
|
||||
}
|
||||
|
||||
pk.setFingerprintAndKeyId()
|
||||
return pk
|
||||
}
|
||||
|
||||
// NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey.
|
||||
func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey {
|
||||
pk := &PublicKey{
|
||||
Version: 4,
|
||||
CreationTime: creationTime,
|
||||
PubKeyAlgo: PubKeyAlgoElGamal,
|
||||
PublicKey: pub,
|
||||
p: new(encoding.MPI).SetBig(pub.P),
|
||||
g: new(encoding.MPI).SetBig(pub.G),
|
||||
y: new(encoding.MPI).SetBig(pub.Y),
|
||||
}
|
||||
|
||||
pk.setFingerprintAndKeyId()
|
||||
return pk
|
||||
}
|
||||
|
||||
func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey {
|
||||
pk := &PublicKey{
|
||||
Version: 4,
|
||||
CreationTime: creationTime,
|
||||
PubKeyAlgo: PubKeyAlgoECDSA,
|
||||
PublicKey: pub,
|
||||
p: encoding.NewMPI(elliptic.Marshal(pub.Curve, pub.X, pub.Y)),
|
||||
}
|
||||
|
||||
curveInfo := ecc.FindByCurve(pub.Curve)
|
||||
if curveInfo == nil {
|
||||
panic("unknown elliptic curve")
|
||||
}
|
||||
pk.oid = curveInfo.Oid
|
||||
pk.setFingerprintAndKeyId()
|
||||
return pk
|
||||
}
|
||||
|
||||
func NewECDHPublicKey(creationTime time.Time, pub *ecdh.PublicKey) *PublicKey {
|
||||
var pk *PublicKey
|
||||
var curveInfo *ecc.CurveInfo
|
||||
var kdf = encoding.NewOID([]byte{0x1, pub.Hash.Id(), pub.Cipher.Id()})
|
||||
if pub.CurveType == ecc.Curve25519 {
|
||||
pk = &PublicKey{
|
||||
Version: 4,
|
||||
CreationTime: creationTime,
|
||||
PubKeyAlgo: PubKeyAlgoECDH,
|
||||
PublicKey: pub,
|
||||
p: encoding.NewMPI(pub.X.Bytes()),
|
||||
kdf: kdf,
|
||||
}
|
||||
curveInfo = ecc.FindByName("Curve25519")
|
||||
} else {
|
||||
pk = &PublicKey{
|
||||
Version: 4,
|
||||
CreationTime: creationTime,
|
||||
PubKeyAlgo: PubKeyAlgoECDH,
|
||||
PublicKey: pub,
|
||||
p: encoding.NewMPI(elliptic.Marshal(pub.Curve, pub.X, pub.Y)),
|
||||
kdf: kdf,
|
||||
}
|
||||
curveInfo = ecc.FindByCurve(pub.Curve)
|
||||
}
|
||||
if curveInfo == nil {
|
||||
panic("unknown elliptic curve")
|
||||
}
|
||||
pk.oid = curveInfo.Oid
|
||||
pk.setFingerprintAndKeyId()
|
||||
return pk
|
||||
}
|
||||
|
||||
func NewEdDSAPublicKey(creationTime time.Time, pub *ed25519.PublicKey) *PublicKey {
|
||||
curveInfo := ecc.FindByName("Ed25519")
|
||||
pk := &PublicKey{
|
||||
Version: 4,
|
||||
CreationTime: creationTime,
|
||||
PubKeyAlgo: PubKeyAlgoEdDSA,
|
||||
PublicKey: pub,
|
||||
oid: curveInfo.Oid,
|
||||
// Native point format, see draft-koch-eddsa-for-openpgp-04, Appendix B
|
||||
p: encoding.NewMPI(append([]byte{0x40}, *pub...)),
|
||||
}
|
||||
|
||||
pk.setFingerprintAndKeyId()
|
||||
return pk
|
||||
}
|
||||
|
||||
func (pk *PublicKey) parse(r io.Reader) (err error) {
|
||||
// RFC 4880, section 5.5.2
|
||||
var buf [6]byte
|
||||
_, err = readFull(r, buf[:])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if buf[0] != 4 && buf[0] != 5 {
|
||||
return errors.UnsupportedError("public key version " + strconv.Itoa(int(buf[0])))
|
||||
}
|
||||
|
||||
pk.Version = int(buf[0])
|
||||
if pk.Version == 5 {
|
||||
var n [4]byte
|
||||
_, err = readFull(r, n[:])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
|
||||
pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5])
|
||||
switch pk.PubKeyAlgo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
|
||||
err = pk.parseRSA(r)
|
||||
case PubKeyAlgoDSA:
|
||||
err = pk.parseDSA(r)
|
||||
case PubKeyAlgoElGamal:
|
||||
err = pk.parseElGamal(r)
|
||||
case PubKeyAlgoECDSA:
|
||||
err = pk.parseECDSA(r)
|
||||
case PubKeyAlgoECDH:
|
||||
err = pk.parseECDH(r)
|
||||
case PubKeyAlgoEdDSA:
|
||||
err = pk.parseEdDSA(r)
|
||||
default:
|
||||
err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
pk.setFingerprintAndKeyId()
|
||||
return
|
||||
}
|
||||
|
||||
func (pk *PublicKey) setFingerprintAndKeyId() {
|
||||
// RFC 4880, section 12.2
|
||||
if pk.Version == 5 {
|
||||
fingerprint := sha256.New()
|
||||
pk.SerializeForHash(fingerprint)
|
||||
pk.Fingerprint = make([]byte, 32)
|
||||
copy(pk.Fingerprint, fingerprint.Sum(nil))
|
||||
pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[:8])
|
||||
} else {
|
||||
fingerprint := sha1.New()
|
||||
pk.SerializeForHash(fingerprint)
|
||||
pk.Fingerprint = make([]byte, 20)
|
||||
copy(pk.Fingerprint, fingerprint.Sum(nil))
|
||||
pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20])
|
||||
}
|
||||
}
|
||||
|
||||
// parseRSA parses RSA public key material from the given Reader. See RFC 4880,
|
||||
// section 5.5.2.
|
||||
func (pk *PublicKey) parseRSA(r io.Reader) (err error) {
|
||||
pk.n = new(encoding.MPI)
|
||||
if _, err = pk.n.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
pk.e = new(encoding.MPI)
|
||||
if _, err = pk.e.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if len(pk.e.Bytes()) > 3 {
|
||||
err = errors.UnsupportedError("large public exponent")
|
||||
return
|
||||
}
|
||||
rsa := &rsa.PublicKey{
|
||||
N: new(big.Int).SetBytes(pk.n.Bytes()),
|
||||
E: 0,
|
||||
}
|
||||
for i := 0; i < len(pk.e.Bytes()); i++ {
|
||||
rsa.E <<= 8
|
||||
rsa.E |= int(pk.e.Bytes()[i])
|
||||
}
|
||||
pk.PublicKey = rsa
|
||||
return
|
||||
}
|
||||
|
||||
// parseDSA parses DSA public key material from the given Reader. See RFC 4880,
|
||||
// section 5.5.2.
|
||||
func (pk *PublicKey) parseDSA(r io.Reader) (err error) {
|
||||
pk.p = new(encoding.MPI)
|
||||
if _, err = pk.p.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
pk.q = new(encoding.MPI)
|
||||
if _, err = pk.q.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
pk.g = new(encoding.MPI)
|
||||
if _, err = pk.g.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
pk.y = new(encoding.MPI)
|
||||
if _, err = pk.y.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
dsa := new(dsa.PublicKey)
|
||||
dsa.P = new(big.Int).SetBytes(pk.p.Bytes())
|
||||
dsa.Q = new(big.Int).SetBytes(pk.q.Bytes())
|
||||
dsa.G = new(big.Int).SetBytes(pk.g.Bytes())
|
||||
dsa.Y = new(big.Int).SetBytes(pk.y.Bytes())
|
||||
pk.PublicKey = dsa
|
||||
return
|
||||
}
|
||||
|
||||
// parseElGamal parses ElGamal public key material from the given Reader. See
|
||||
// RFC 4880, section 5.5.2.
|
||||
func (pk *PublicKey) parseElGamal(r io.Reader) (err error) {
|
||||
pk.p = new(encoding.MPI)
|
||||
if _, err = pk.p.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
pk.g = new(encoding.MPI)
|
||||
if _, err = pk.g.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
pk.y = new(encoding.MPI)
|
||||
if _, err = pk.y.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
elgamal := new(elgamal.PublicKey)
|
||||
elgamal.P = new(big.Int).SetBytes(pk.p.Bytes())
|
||||
elgamal.G = new(big.Int).SetBytes(pk.g.Bytes())
|
||||
elgamal.Y = new(big.Int).SetBytes(pk.y.Bytes())
|
||||
pk.PublicKey = elgamal
|
||||
return
|
||||
}
|
||||
|
||||
// parseECDSA parses ECDSA public key material from the given Reader. See
|
||||
// RFC 6637, Section 9.
|
||||
func (pk *PublicKey) parseECDSA(r io.Reader) (err error) {
|
||||
pk.oid = new(encoding.OID)
|
||||
if _, err = pk.oid.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
pk.p = new(encoding.MPI)
|
||||
if _, err = pk.p.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var c elliptic.Curve
|
||||
curveInfo := ecc.FindByOid(pk.oid)
|
||||
if curveInfo == nil || curveInfo.SigAlgorithm != ecc.ECDSA {
|
||||
return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid))
|
||||
}
|
||||
c = curveInfo.Curve
|
||||
x, y := elliptic.Unmarshal(c, pk.p.Bytes())
|
||||
if x == nil {
|
||||
return errors.UnsupportedError("failed to parse EC point")
|
||||
}
|
||||
pk.PublicKey = &ecdsa.PublicKey{Curve: c, X: x, Y: y}
|
||||
return
|
||||
}
|
||||
|
||||
// parseECDH parses ECDH public key material from the given Reader. See
|
||||
// RFC 6637, Section 9.
|
||||
func (pk *PublicKey) parseECDH(r io.Reader) (err error) {
|
||||
pk.oid = new(encoding.OID)
|
||||
if _, err = pk.oid.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
pk.p = new(encoding.MPI)
|
||||
if _, err = pk.p.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
pk.kdf = new(encoding.OID)
|
||||
if _, err = pk.kdf.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
curveInfo := ecc.FindByOid(pk.oid)
|
||||
if curveInfo == nil {
|
||||
return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid))
|
||||
}
|
||||
|
||||
c := curveInfo.Curve
|
||||
cType := curveInfo.CurveType
|
||||
|
||||
var x, y *big.Int
|
||||
if cType == ecc.Curve25519 {
|
||||
x = new(big.Int)
|
||||
x.SetBytes(pk.p.Bytes())
|
||||
} else {
|
||||
x, y = elliptic.Unmarshal(c, pk.p.Bytes())
|
||||
}
|
||||
if x == nil {
|
||||
return errors.UnsupportedError("failed to parse EC point")
|
||||
}
|
||||
|
||||
if kdfLen := len(pk.kdf.Bytes()); kdfLen < 3 {
|
||||
return errors.UnsupportedError("unsupported ECDH KDF length: " + strconv.Itoa(kdfLen))
|
||||
}
|
||||
if reserved := pk.kdf.Bytes()[0]; reserved != 0x01 {
|
||||
return errors.UnsupportedError("unsupported KDF reserved field: " + strconv.Itoa(int(reserved)))
|
||||
}
|
||||
kdfHash, ok := algorithm.HashById[pk.kdf.Bytes()[1]]
|
||||
if !ok {
|
||||
return errors.UnsupportedError("unsupported ECDH KDF hash: " + strconv.Itoa(int(pk.kdf.Bytes()[1])))
|
||||
}
|
||||
kdfCipher, ok := algorithm.CipherById[pk.kdf.Bytes()[2]]
|
||||
if !ok {
|
||||
return errors.UnsupportedError("unsupported ECDH KDF cipher: " + strconv.Itoa(int(pk.kdf.Bytes()[2])))
|
||||
}
|
||||
|
||||
pk.PublicKey = &ecdh.PublicKey{
|
||||
CurveType: cType,
|
||||
Curve: c,
|
||||
X: x,
|
||||
Y: y,
|
||||
KDF: ecdh.KDF{
|
||||
Hash: kdfHash,
|
||||
Cipher: kdfCipher,
|
||||
},
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (pk *PublicKey) parseEdDSA(r io.Reader) (err error) {
|
||||
pk.oid = new(encoding.OID)
|
||||
if _, err = pk.oid.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
curveInfo := ecc.FindByOid(pk.oid)
|
||||
if curveInfo == nil || curveInfo.SigAlgorithm != ecc.EdDSA {
|
||||
return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid))
|
||||
}
|
||||
pk.p = new(encoding.MPI)
|
||||
if _, err = pk.p.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
eddsa := make(ed25519.PublicKey, ed25519.PublicKeySize)
|
||||
switch flag := pk.p.Bytes()[0]; flag {
|
||||
case 0x04:
|
||||
// TODO: see _grcy_ecc_eddsa_ensure_compact in grcypt
|
||||
return errors.UnsupportedError("unsupported EdDSA compression: " + strconv.Itoa(int(flag)))
|
||||
case 0x40:
|
||||
copy(eddsa[:], pk.p.Bytes()[1:])
|
||||
default:
|
||||
return errors.UnsupportedError("unsupported EdDSA compression: " + strconv.Itoa(int(flag)))
|
||||
}
|
||||
|
||||
pk.PublicKey = &eddsa
|
||||
return
|
||||
}
|
||||
|
||||
// SerializeForHash serializes the PublicKey to w with the special packet
|
||||
// header format needed for hashing.
|
||||
func (pk *PublicKey) SerializeForHash(w io.Writer) error {
|
||||
pk.SerializeSignaturePrefix(w)
|
||||
return pk.serializeWithoutHeaders(w)
|
||||
}
|
||||
|
||||
// SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
|
||||
// The prefix is used when calculating a signature over this public key. See
|
||||
// RFC 4880, section 5.2.4.
|
||||
func (pk *PublicKey) SerializeSignaturePrefix(w io.Writer) {
|
||||
var pLength = pk.algorithmSpecificByteCount()
|
||||
if pk.Version == 5 {
|
||||
pLength += 10 // version, timestamp (4), algorithm, key octet count (4).
|
||||
w.Write([]byte{
|
||||
0x9A,
|
||||
byte(pLength >> 24),
|
||||
byte(pLength >> 16),
|
||||
byte(pLength >> 8),
|
||||
byte(pLength),
|
||||
})
|
||||
return
|
||||
}
|
||||
pLength += 6
|
||||
w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
|
||||
}
|
||||
|
||||
func (pk *PublicKey) Serialize(w io.Writer) (err error) {
|
||||
length := 6 // 6 byte header
|
||||
length += pk.algorithmSpecificByteCount()
|
||||
if pk.Version == 5 {
|
||||
length += 4 // octet key count
|
||||
}
|
||||
packetType := packetTypePublicKey
|
||||
if pk.IsSubkey {
|
||||
packetType = packetTypePublicSubkey
|
||||
}
|
||||
err = serializeHeader(w, packetType, length)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return pk.serializeWithoutHeaders(w)
|
||||
}
|
||||
|
||||
func (pk *PublicKey) algorithmSpecificByteCount() int {
|
||||
length := 0
|
||||
switch pk.PubKeyAlgo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
|
||||
length += int(pk.n.EncodedLength())
|
||||
length += int(pk.e.EncodedLength())
|
||||
case PubKeyAlgoDSA:
|
||||
length += int(pk.p.EncodedLength())
|
||||
length += int(pk.q.EncodedLength())
|
||||
length += int(pk.g.EncodedLength())
|
||||
length += int(pk.y.EncodedLength())
|
||||
case PubKeyAlgoElGamal:
|
||||
length += int(pk.p.EncodedLength())
|
||||
length += int(pk.g.EncodedLength())
|
||||
length += int(pk.y.EncodedLength())
|
||||
case PubKeyAlgoECDSA:
|
||||
length += int(pk.oid.EncodedLength())
|
||||
length += int(pk.p.EncodedLength())
|
||||
case PubKeyAlgoECDH:
|
||||
length += int(pk.oid.EncodedLength())
|
||||
length += int(pk.p.EncodedLength())
|
||||
length += int(pk.kdf.EncodedLength())
|
||||
case PubKeyAlgoEdDSA:
|
||||
length += int(pk.oid.EncodedLength())
|
||||
length += int(pk.p.EncodedLength())
|
||||
default:
|
||||
panic("unknown public key algorithm")
|
||||
}
|
||||
return length
|
||||
}
|
||||
|
||||
// serializeWithoutHeaders marshals the PublicKey to w in the form of an
|
||||
// OpenPGP public key packet, not including the packet header.
|
||||
func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
|
||||
t := uint32(pk.CreationTime.Unix())
|
||||
if _, err = w.Write([]byte{
|
||||
byte(pk.Version),
|
||||
byte(t >> 24), byte(t >> 16), byte(t >> 8), byte(t),
|
||||
byte(pk.PubKeyAlgo),
|
||||
}); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if pk.Version == 5 {
|
||||
n := pk.algorithmSpecificByteCount()
|
||||
if _, err = w.Write([]byte{
|
||||
byte(n >> 24), byte(n >> 16), byte(n >> 8), byte(n),
|
||||
}); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
switch pk.PubKeyAlgo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
|
||||
if _, err = w.Write(pk.n.EncodedBytes()); err != nil {
|
||||
return
|
||||
}
|
||||
_, err = w.Write(pk.e.EncodedBytes())
|
||||
return
|
||||
case PubKeyAlgoDSA:
|
||||
if _, err = w.Write(pk.p.EncodedBytes()); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = w.Write(pk.q.EncodedBytes()); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = w.Write(pk.g.EncodedBytes()); err != nil {
|
||||
return
|
||||
}
|
||||
_, err = w.Write(pk.y.EncodedBytes())
|
||||
return
|
||||
case PubKeyAlgoElGamal:
|
||||
if _, err = w.Write(pk.p.EncodedBytes()); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = w.Write(pk.g.EncodedBytes()); err != nil {
|
||||
return
|
||||
}
|
||||
_, err = w.Write(pk.y.EncodedBytes())
|
||||
return
|
||||
case PubKeyAlgoECDSA:
|
||||
if _, err = w.Write(pk.oid.EncodedBytes()); err != nil {
|
||||
return
|
||||
}
|
||||
_, err = w.Write(pk.p.EncodedBytes())
|
||||
return
|
||||
case PubKeyAlgoECDH:
|
||||
if _, err = w.Write(pk.oid.EncodedBytes()); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = w.Write(pk.p.EncodedBytes()); err != nil {
|
||||
return
|
||||
}
|
||||
_, err = w.Write(pk.kdf.EncodedBytes())
|
||||
return
|
||||
case PubKeyAlgoEdDSA:
|
||||
if _, err = w.Write(pk.oid.EncodedBytes()); err != nil {
|
||||
return
|
||||
}
|
||||
_, err = w.Write(pk.p.EncodedBytes())
|
||||
return
|
||||
}
|
||||
return errors.InvalidArgumentError("bad public-key algorithm")
|
||||
}
|
||||
|
||||
// CanSign returns true iff this public key can generate signatures
|
||||
func (pk *PublicKey) CanSign() bool {
|
||||
return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal && pk.PubKeyAlgo != PubKeyAlgoECDH
|
||||
}
|
||||
|
||||
// VerifySignature returns nil iff sig is a valid signature, made by this
|
||||
// public key, of the data hashed into signed. signed is mutated by this call.
|
||||
func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) {
|
||||
if !pk.CanSign() {
|
||||
return errors.InvalidArgumentError("public key cannot generate signatures")
|
||||
}
|
||||
if sig.Version == 5 && (sig.SigType == 0x00 || sig.SigType == 0x01) {
|
||||
sig.AddMetadataToHashSuffix()
|
||||
}
|
||||
signed.Write(sig.HashSuffix)
|
||||
hashBytes := signed.Sum(nil)
|
||||
if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
|
||||
return errors.SignatureError("hash tag doesn't match")
|
||||
}
|
||||
|
||||
if pk.PubKeyAlgo != sig.PubKeyAlgo {
|
||||
return errors.InvalidArgumentError("public key and signature use different algorithms")
|
||||
}
|
||||
|
||||
switch pk.PubKeyAlgo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
|
||||
rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey)
|
||||
err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.Bytes()))
|
||||
if err != nil {
|
||||
return errors.SignatureError("RSA verification failure")
|
||||
}
|
||||
return nil
|
||||
case PubKeyAlgoDSA:
|
||||
dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey)
|
||||
// Need to truncate hashBytes to match FIPS 186-3 section 4.6.
|
||||
subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8
|
||||
if len(hashBytes) > subgroupSize {
|
||||
hashBytes = hashBytes[:subgroupSize]
|
||||
}
|
||||
if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.Bytes()), new(big.Int).SetBytes(sig.DSASigS.Bytes())) {
|
||||
return errors.SignatureError("DSA verification failure")
|
||||
}
|
||||
return nil
|
||||
case PubKeyAlgoECDSA:
|
||||
ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey)
|
||||
if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.Bytes()), new(big.Int).SetBytes(sig.ECDSASigS.Bytes())) {
|
||||
return errors.SignatureError("ECDSA verification failure")
|
||||
}
|
||||
return nil
|
||||
case PubKeyAlgoEdDSA:
|
||||
eddsaPublicKey := pk.PublicKey.(*ed25519.PublicKey)
|
||||
|
||||
sigR := sig.EdDSASigR.Bytes()
|
||||
sigS := sig.EdDSASigS.Bytes()
|
||||
|
||||
eddsaSig := make([]byte, ed25519.SignatureSize)
|
||||
copy(eddsaSig[32-len(sigR):32], sigR)
|
||||
copy(eddsaSig[64-len(sigS):], sigS)
|
||||
|
||||
if !ed25519.Verify(*eddsaPublicKey, hashBytes, eddsaSig) {
|
||||
return errors.SignatureError("EdDSA verification failure")
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return errors.SignatureError("Unsupported public key algorithm used in signature")
|
||||
}
|
||||
}
|
||||
|
||||
// keySignatureHash returns a Hash of the message that needs to be signed for
|
||||
// pk to assert a subkey relationship to signed.
|
||||
func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
|
||||
if !hashFunc.Available() {
|
||||
return nil, errors.UnsupportedError("hash function")
|
||||
}
|
||||
h = hashFunc.New()
|
||||
|
||||
// RFC 4880, section 5.2.4
|
||||
err = pk.SerializeForHash(h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = signed.SerializeForHash(h)
|
||||
return
|
||||
}
|
||||
|
||||
// VerifyKeySignature returns nil iff sig is a valid signature, made by this
|
||||
// public key, of signed.
|
||||
func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error {
|
||||
h, err := keySignatureHash(pk, signed, sig.Hash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = pk.VerifySignature(h, sig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if sig.FlagSign {
|
||||
// Signing subkeys must be cross-signed. See
|
||||
// https://www.gnupg.org/faq/subkey-cross-certify.html.
|
||||
if sig.EmbeddedSignature == nil {
|
||||
return errors.StructuralError("signing subkey is missing cross-signature")
|
||||
}
|
||||
// Verify the cross-signature. This is calculated over the same
|
||||
// data as the main signature, so we cannot just recursively
|
||||
// call signed.VerifyKeySignature(...)
|
||||
if h, err = keySignatureHash(pk, signed, sig.EmbeddedSignature.Hash); err != nil {
|
||||
return errors.StructuralError("error while hashing for cross-signature: " + err.Error())
|
||||
}
|
||||
if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil {
|
||||
return errors.StructuralError("error while verifying cross-signature: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
|
||||
if !hashFunc.Available() {
|
||||
return nil, errors.UnsupportedError("hash function")
|
||||
}
|
||||
h = hashFunc.New()
|
||||
|
||||
// RFC 4880, section 5.2.4
|
||||
err = pk.SerializeForHash(h)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this
|
||||
// public key.
|
||||
func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) {
|
||||
h, err := keyRevocationHash(pk, sig.Hash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return pk.VerifySignature(h, sig)
|
||||
}
|
||||
|
||||
// VerifySubkeyRevocationSignature returns nil iff sig is a valid subkey revocation signature,
|
||||
// made by the passed in signingKey.
|
||||
func (pk *PublicKey) VerifySubkeyRevocationSignature(sig *Signature, signingKey *PublicKey) (err error) {
|
||||
h, err := keyRevocationHash(pk, sig.Hash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return signingKey.VerifySignature(h, sig)
|
||||
}
|
||||
|
||||
// userIdSignatureHash returns a Hash of the message that needs to be signed
|
||||
// to assert that pk is a valid key for id.
|
||||
func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
|
||||
if !hashFunc.Available() {
|
||||
return nil, errors.UnsupportedError("hash function")
|
||||
}
|
||||
h = hashFunc.New()
|
||||
|
||||
// RFC 4880, section 5.2.4
|
||||
pk.SerializeSignaturePrefix(h)
|
||||
pk.serializeWithoutHeaders(h)
|
||||
|
||||
var buf [5]byte
|
||||
buf[0] = 0xb4
|
||||
buf[1] = byte(len(id) >> 24)
|
||||
buf[2] = byte(len(id) >> 16)
|
||||
buf[3] = byte(len(id) >> 8)
|
||||
buf[4] = byte(len(id))
|
||||
h.Write(buf[:])
|
||||
h.Write([]byte(id))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this
|
||||
// public key, that id is the identity of pub.
|
||||
func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) {
|
||||
h, err := userIdSignatureHash(id, pub, sig.Hash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return pk.VerifySignature(h, sig)
|
||||
}
|
||||
|
||||
// KeyIdString returns the public key's fingerprint in capital hex
|
||||
// (e.g. "6C7EE1B8621CC013").
|
||||
func (pk *PublicKey) KeyIdString() string {
|
||||
return fmt.Sprintf("%X", pk.Fingerprint[12:20])
|
||||
}
|
||||
|
||||
// KeyIdShortString returns the short form of public key's fingerprint
|
||||
// in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
|
||||
func (pk *PublicKey) KeyIdShortString() string {
|
||||
return fmt.Sprintf("%X", pk.Fingerprint[16:20])
|
||||
}
|
||||
|
||||
// BitLength returns the bit length for the given public key.
|
||||
func (pk *PublicKey) BitLength() (bitLength uint16, err error) {
|
||||
switch pk.PubKeyAlgo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
|
||||
bitLength = pk.n.BitLength()
|
||||
case PubKeyAlgoDSA:
|
||||
bitLength = pk.p.BitLength()
|
||||
case PubKeyAlgoElGamal:
|
||||
bitLength = pk.p.BitLength()
|
||||
case PubKeyAlgoECDSA:
|
||||
bitLength = pk.p.BitLength()
|
||||
case PubKeyAlgoECDH:
|
||||
bitLength = pk.p.BitLength()
|
||||
case PubKeyAlgoEdDSA:
|
||||
bitLength = pk.p.BitLength()
|
||||
default:
|
||||
err = errors.InvalidArgumentError("bad public-key algorithm")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// KeyExpired returns whether sig is a self-signature of a key that has
|
||||
// expired or is created in the future.
|
||||
func (pk *PublicKey) KeyExpired(sig *Signature, currentTime time.Time) bool {
|
||||
if pk.CreationTime.After(currentTime) {
|
||||
return true
|
||||
}
|
||||
if sig.KeyLifetimeSecs == nil || *sig.KeyLifetimeSecs == 0 {
|
||||
return false
|
||||
}
|
||||
expiry := pk.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second)
|
||||
return currentTime.After(expiry)
|
||||
}
|
24
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key_test_data.go
generated
vendored
Normal file
24
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key_test_data.go
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
package packet
|
||||
|
||||
const rsaFingerprintHex = "5fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb"
|
||||
|
||||
const rsaPkDataHex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001"
|
||||
|
||||
const dsaFingerprintHex = "eece4c094db002103714c63c8e8fbe54062f19ed"
|
||||
|
||||
const dsaPkDataHex = "9901a2044d432f89110400cd581334f0d7a1e1bdc8b9d6d8c0baf68793632735d2bb0903224cbaa1dfbf35a60ee7a13b92643421e1eb41aa8d79bea19a115a677f6b8ba3c7818ce53a6c2a24a1608bd8b8d6e55c5090cbde09dd26e356267465ae25e69ec8bdd57c7bbb2623e4d73336f73a0a9098f7f16da2e25252130fd694c0e8070c55a812a423ae7f00a0ebf50e70c2f19c3520a551bd4b08d30f23530d3d03ff7d0bf4a53a64a09dc5e6e6e35854b7d70c882b0c60293401958b1bd9e40abec3ea05ba87cf64899299d4bd6aa7f459c201d3fbbd6c82004bdc5e8a9eb8082d12054cc90fa9d4ec251a843236a588bf49552441817436c4f43326966fe85447d4e6d0acf8fa1ef0f014730770603ad7634c3088dc52501c237328417c31c89ed70400b2f1a98b0bf42f11fefc430704bebbaa41d9f355600c3facee1e490f64208e0e094ea55e3a598a219a58500bf78ac677b670a14f4e47e9cf8eab4f368cc1ddcaa18cc59309d4cc62dd4f680e73e6cc3e1ce87a84d0925efbcb26c575c093fc42eecf45135fabf6403a25c2016e1774c0484e440a18319072c617cc97ac0a3bb0"
|
||||
|
||||
const ecdsaFingerprintHex = "9892270b38b8980b05c8d56d43fe956c542ca00b"
|
||||
|
||||
const ecdsaPkDataHex = "9893045071c29413052b8104002304230401f4867769cedfa52c325018896245443968e52e51d0c2df8d939949cb5b330f2921711fbee1c9b9dddb95d15cb0255e99badeddda7cc23d9ddcaacbc290969b9f24019375d61c2e4e3b36953a28d8b2bc95f78c3f1d592fb24499be348656a7b17e3963187b4361afe497bc5f9f81213f04069f8e1fb9e6a6290ae295ca1a92b894396cb4"
|
||||
|
||||
const ecdhFingerprintHex = "722354df2475a42164d1d49faa8b938f9a201946"
|
||||
|
||||
const ecdhPkDataHex = "b90073044d53059212052b810400220303042faa84024a20b6735c4897efa5bfb41bf85b7eefeab5ca0cb9ffc8ea04a46acb25534a577694f9e25340a4ab5223a9dd1eda530c8aa2e6718db10d7e672558c7736fe09369ea5739a2a3554bf16d41faa50562f11c6d39bbd5dffb6b9a9ec91803010909"
|
||||
|
||||
const eddsaFingerprintHex = "b2d5e5ec0e6deca6bc8eeeb00907e75e1dd99ad8"
|
||||
|
||||
const eddsaPkDataHex = "98330456e2132b16092b06010401da470f01010740bbda39266affa511a8c2d02edf690fb784b0499c4406185811a163539ef11dc1b41d74657374696e67203c74657374696e674074657374696e672e636f6d3e8879041316080021050256e2132b021b03050b09080702061508090a0b020416020301021e01021780000a09100907e75e1dd99ad86d0c00fe39d2008359352782bc9b61ac382584cd8eff3f57a18c2287e3afeeb05d1f04ba00fe2d0bc1ddf3ff8adb9afa3e7d9287244b4ec567f3db4d60b74a9b5465ed528203"
|
||||
|
||||
// Source: https://sites.google.com/site/brainhub/pgpecckeys#TOC-ECC-NIST-P-384-key
|
||||
const ecc384PubHex = `99006f044d53059213052b81040022030304f6b8c5aced5b84ef9f4a209db2e4a9dfb70d28cb8c10ecd57674a9fa5a67389942b62d5e51367df4c7bfd3f8e500feecf07ed265a621a8ebbbe53e947ec78c677eba143bd1533c2b350e1c29f82313e1e1108eba063be1e64b10e6950e799c2db42465635f6473615f64685f333834203c6f70656e70677040627261696e6875622e6f72673e8900cb04101309005305024d530592301480000000002000077072656665727265642d656d61696c2d656e636f64696e67407067702e636f6d7067706d696d65040b090807021901051b03000000021602051e010000000415090a08000a0910098033880f54719fca2b0180aa37350968bd5f115afd8ce7bc7b103822152dbff06d0afcda835329510905b98cb469ba208faab87c7412b799e7b633017f58364ea480e8a1a3f253a0c5f22c446e8be9a9fce6210136ee30811abbd49139de28b5bdf8dc36d06ae748579e9ff503b90073044d53059212052b810400220303042faa84024a20b6735c4897efa5bfb41bf85b7eefeab5ca0cb9ffc8ea04a46acb25534a577694f9e25340a4ab5223a9dd1eda530c8aa2e6718db10d7e672558c7736fe09369ea5739a2a3554bf16d41faa50562f11c6d39bbd5dffb6b9a9ec9180301090989008404181309000c05024d530592051b0c000000000a0910098033880f54719f80970180eee7a6d8fcee41ee4f9289df17f9bcf9d955dca25c583b94336f3a2b2d4986dc5cf417b8d2dc86f741a9e1a6d236c0e3017d1c76575458a0cfb93ae8a2b274fcc65ceecd7a91eec83656ba13219969f06945b48c56bd04152c3a0553c5f2f4bd1267`
|
|
@ -5,8 +5,9 @@
|
|||
package packet
|
||||
|
||||
import (
|
||||
"golang.org/x/crypto/openpgp/errors"
|
||||
"io"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
)
|
||||
|
||||
// Reader reads packets from an io.Reader and allows packets to be 'unread' so
|
||||
|
@ -42,6 +43,7 @@ func (r *Reader) Next() (p Packet, err error) {
|
|||
r.readers = r.readers[:len(r.readers)-1]
|
||||
continue
|
||||
}
|
||||
// TODO: Add strict mode that rejects unknown packets, instead of ignoring them.
|
||||
if _, ok := err.(errors.UnknownPacketTypeError); !ok {
|
||||
return nil, err
|
||||
}
|
|
@ -17,8 +17,9 @@ import (
|
|||
"strconv"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/openpgp/errors"
|
||||
"golang.org/x/crypto/openpgp/s2k"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/s2k"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -31,6 +32,7 @@ const (
|
|||
|
||||
// Signature represents a signature. See RFC 4880, section 5.2.
|
||||
type Signature struct {
|
||||
Version int
|
||||
SigType SignatureType
|
||||
PubKeyAlgo PublicKeyAlgorithm
|
||||
Hash crypto.Hash
|
||||
|
@ -39,12 +41,19 @@ type Signature struct {
|
|||
HashSuffix []byte
|
||||
// HashTag contains the first two bytes of the hash for fast rejection
|
||||
// of bad signed data.
|
||||
HashTag [2]byte
|
||||
HashTag [2]byte
|
||||
|
||||
// Metadata includes format, filename and time, and is protected by v5
|
||||
// signatures of type 0x00 or 0x01. This metadata is included into the hash
|
||||
// computation; if nil, six 0x00 bytes are used instead. See section 5.2.4.
|
||||
Metadata *LiteralData
|
||||
|
||||
CreationTime time.Time
|
||||
|
||||
RSASignature parsedMPI
|
||||
DSASigR, DSASigS parsedMPI
|
||||
ECDSASigR, ECDSASigS parsedMPI
|
||||
RSASignature encoding.Field
|
||||
DSASigR, DSASigS encoding.Field
|
||||
ECDSASigR, ECDSASigS encoding.Field
|
||||
EdDSASigR, EdDSASigS encoding.Field
|
||||
|
||||
// rawSubpackets contains the unparsed subpackets, in order.
|
||||
rawSubpackets []outputSubpacket
|
||||
|
@ -54,9 +63,16 @@ type Signature struct {
|
|||
|
||||
SigLifetimeSecs, KeyLifetimeSecs *uint32
|
||||
PreferredSymmetric, PreferredHash, PreferredCompression []uint8
|
||||
PreferredAEAD []uint8
|
||||
IssuerKeyId *uint64
|
||||
IssuerFingerprint []byte
|
||||
IsPrimaryId *bool
|
||||
|
||||
// PolicyURI can be set to the URI of a document that describes the
|
||||
// policy under which the signature was issued. See RFC 4880, section
|
||||
// 5.2.3.20 for details.
|
||||
PolicyURI string
|
||||
|
||||
// FlagsValid is set if any flags were given. See RFC 4880, section
|
||||
// 5.2.3.21 for details.
|
||||
FlagsValid bool
|
||||
|
@ -67,9 +83,10 @@ type Signature struct {
|
|||
RevocationReason *uint8
|
||||
RevocationReasonText string
|
||||
|
||||
// MDC is set if this signature has a feature packet that indicates
|
||||
// support for MDC subpackets.
|
||||
MDC bool
|
||||
// In a self-signature, these flags are set there is a features subpacket
|
||||
// indicating that the issuer implementation supports these features
|
||||
// (section 5.2.5.25).
|
||||
MDC, AEAD, V5Keys bool
|
||||
|
||||
// EmbeddedSignature, if non-nil, is a signature of the parent key, by
|
||||
// this key. This prevents an attacker from claiming another's signing
|
||||
|
@ -86,11 +103,11 @@ func (sig *Signature) parse(r io.Reader) (err error) {
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
if buf[0] != 4 {
|
||||
if buf[0] != 4 && buf[0] != 5 {
|
||||
err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
|
||||
return
|
||||
}
|
||||
|
||||
sig.Version = int(buf[0])
|
||||
_, err = readFull(r, buf[:5])
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -98,7 +115,7 @@ func (sig *Signature) parse(r io.Reader) (err error) {
|
|||
sig.SigType = SignatureType(buf[0])
|
||||
sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1])
|
||||
switch sig.PubKeyAlgo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA:
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA, PubKeyAlgoEdDSA:
|
||||
default:
|
||||
err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
|
||||
return
|
||||
|
@ -111,24 +128,12 @@ func (sig *Signature) parse(r io.Reader) (err error) {
|
|||
}
|
||||
|
||||
hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4])
|
||||
l := 6 + hashedSubpacketsLength
|
||||
sig.HashSuffix = make([]byte, l+6)
|
||||
sig.HashSuffix[0] = 4
|
||||
copy(sig.HashSuffix[1:], buf[:5])
|
||||
hashedSubpackets := sig.HashSuffix[6:l]
|
||||
hashedSubpackets := make([]byte, hashedSubpacketsLength)
|
||||
_, err = readFull(r, hashedSubpackets)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// See RFC 4880, section 5.2.4
|
||||
trailer := sig.HashSuffix[l:]
|
||||
trailer[0] = 4
|
||||
trailer[1] = 0xff
|
||||
trailer[2] = uint8(l >> 24)
|
||||
trailer[3] = uint8(l >> 16)
|
||||
trailer[4] = uint8(l >> 8)
|
||||
trailer[5] = uint8(l)
|
||||
|
||||
sig.buildHashSuffix(hashedSubpackets)
|
||||
err = parseSignatureSubpackets(sig, hashedSubpackets, true)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -156,16 +161,33 @@ func (sig *Signature) parse(r io.Reader) (err error) {
|
|||
|
||||
switch sig.PubKeyAlgo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
|
||||
sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r)
|
||||
sig.RSASignature = new(encoding.MPI)
|
||||
_, err = sig.RSASignature.ReadFrom(r)
|
||||
case PubKeyAlgoDSA:
|
||||
sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r)
|
||||
if err == nil {
|
||||
sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r)
|
||||
sig.DSASigR = new(encoding.MPI)
|
||||
if _, err = sig.DSASigR.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
sig.DSASigS = new(encoding.MPI)
|
||||
_, err = sig.DSASigS.ReadFrom(r)
|
||||
case PubKeyAlgoECDSA:
|
||||
sig.ECDSASigR.bytes, sig.ECDSASigR.bitLength, err = readMPI(r)
|
||||
if err == nil {
|
||||
sig.ECDSASigS.bytes, sig.ECDSASigS.bitLength, err = readMPI(r)
|
||||
sig.ECDSASigR = new(encoding.MPI)
|
||||
if _, err = sig.ECDSASigR.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
sig.ECDSASigS = new(encoding.MPI)
|
||||
_, err = sig.ECDSASigS.ReadFrom(r)
|
||||
case PubKeyAlgoEdDSA:
|
||||
sig.EdDSASigR = new(encoding.MPI)
|
||||
if _, err = sig.EdDSASigR.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
sig.EdDSASigS = new(encoding.MPI)
|
||||
if _, err = sig.EdDSASigS.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
default:
|
||||
panic("unreachable")
|
||||
|
@ -201,10 +223,13 @@ const (
|
|||
prefHashAlgosSubpacket signatureSubpacketType = 21
|
||||
prefCompressionSubpacket signatureSubpacketType = 22
|
||||
primaryUserIdSubpacket signatureSubpacketType = 25
|
||||
policyUriSubpacket signatureSubpacketType = 26
|
||||
keyFlagsSubpacket signatureSubpacketType = 27
|
||||
reasonForRevocationSubpacket signatureSubpacketType = 29
|
||||
featuresSubpacket signatureSubpacketType = 30
|
||||
embeddedSignatureSubpacket signatureSubpacketType = 32
|
||||
issuerFingerprintSubpacket signatureSubpacketType = 33
|
||||
prefAeadAlgosSubpacket signatureSubpacketType = 34
|
||||
)
|
||||
|
||||
// parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1.
|
||||
|
@ -290,6 +315,9 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
|
|||
sig.PreferredSymmetric = make([]byte, len(subpacket))
|
||||
copy(sig.PreferredSymmetric, subpacket)
|
||||
case issuerSubpacket:
|
||||
if sig.Version > 4 {
|
||||
err = errors.StructuralError("issuer subpacket found in v5 key")
|
||||
}
|
||||
// Issuer, section 5.2.3.5
|
||||
if len(subpacket) != 8 {
|
||||
err = errors.StructuralError("issuer subpacket with bad length")
|
||||
|
@ -361,9 +389,21 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
|
|||
case featuresSubpacket:
|
||||
// Features subpacket, section 5.2.3.24 specifies a very general
|
||||
// mechanism for OpenPGP implementations to signal support for new
|
||||
// features. In practice, the subpacket is used exclusively to
|
||||
// indicate support for MDC-protected encryption.
|
||||
sig.MDC = len(subpacket) >= 1 && subpacket[0]&1 == 1
|
||||
// features.
|
||||
if !isHashed {
|
||||
return
|
||||
}
|
||||
if len(subpacket) > 0 {
|
||||
if subpacket[0]&0x01 != 0 {
|
||||
sig.MDC = true
|
||||
}
|
||||
if subpacket[0]&0x02 != 0 {
|
||||
sig.AEAD = true
|
||||
}
|
||||
if subpacket[0]&0x04 != 0 {
|
||||
sig.V5Keys = true
|
||||
}
|
||||
}
|
||||
case embeddedSignatureSubpacket:
|
||||
// Only usage is in signatures that cross-certify
|
||||
// signing subkeys. section 5.2.3.26 describes the
|
||||
|
@ -382,6 +422,32 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
|
|||
if sigType := sig.EmbeddedSignature.SigType; sigType != SigTypePrimaryKeyBinding {
|
||||
return nil, errors.StructuralError("cross-signature has unexpected type " + strconv.Itoa(int(sigType)))
|
||||
}
|
||||
case policyUriSubpacket:
|
||||
// Policy URI, section 5.2.3.20
|
||||
if !isHashed {
|
||||
return
|
||||
}
|
||||
sig.PolicyURI = string(subpacket)
|
||||
case issuerFingerprintSubpacket:
|
||||
v, l := subpacket[0], len(subpacket[1:])
|
||||
if v == 5 && l != 32 || v != 5 && l != 20 {
|
||||
return nil, errors.StructuralError("bad fingerprint length")
|
||||
}
|
||||
sig.IssuerFingerprint = make([]byte, l)
|
||||
copy(sig.IssuerFingerprint, subpacket[1:])
|
||||
sig.IssuerKeyId = new(uint64)
|
||||
if v == 5 {
|
||||
*sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket[1:9])
|
||||
} else {
|
||||
*sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket[13:21])
|
||||
}
|
||||
case prefAeadAlgosSubpacket:
|
||||
// Preferred symmetric algorithms, section 5.2.3.8
|
||||
if !isHashed {
|
||||
return
|
||||
}
|
||||
sig.PreferredAEAD = make([]byte, len(subpacket))
|
||||
copy(sig.PreferredAEAD, subpacket)
|
||||
default:
|
||||
if isCritical {
|
||||
err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType)))
|
||||
|
@ -406,6 +472,13 @@ func subpacketLengthLength(length int) int {
|
|||
return 5
|
||||
}
|
||||
|
||||
func (sig *Signature) CheckKeyIdOrFingerprint(pk *PublicKey) bool {
|
||||
if sig.IssuerFingerprint != nil && len(sig.IssuerFingerprint) >= 20 {
|
||||
return bytes.Equal(sig.IssuerFingerprint, pk.Fingerprint)
|
||||
}
|
||||
return sig.IssuerKeyId != nil && *sig.IssuerKeyId == pk.KeyId
|
||||
}
|
||||
|
||||
// serializeSubpacketLength marshals the given length into to.
|
||||
func serializeSubpacketLength(to []byte, length int) int {
|
||||
// RFC 4880, Section 4.2.2.
|
||||
|
@ -446,6 +519,9 @@ func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) {
|
|||
if subpacket.hashed == hashed {
|
||||
n := serializeSubpacketLength(to, len(subpacket.contents)+1)
|
||||
to[n] = byte(subpacket.subpacketType)
|
||||
if subpacket.isCritical {
|
||||
to[n] |= 0x80
|
||||
}
|
||||
to = to[1+n:]
|
||||
n = copy(to, subpacket.contents)
|
||||
to = to[n:]
|
||||
|
@ -454,49 +530,66 @@ func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) {
|
|||
return
|
||||
}
|
||||
|
||||
// KeyExpired returns whether sig is a self-signature of a key that has
|
||||
// expired.
|
||||
func (sig *Signature) KeyExpired(currentTime time.Time) bool {
|
||||
if sig.KeyLifetimeSecs == nil {
|
||||
// SigExpired returns whether sig is a signature that has expired or is created
|
||||
// in the future.
|
||||
func (sig *Signature) SigExpired(currentTime time.Time) bool {
|
||||
if sig.CreationTime.After(currentTime) {
|
||||
return true
|
||||
}
|
||||
if sig.SigLifetimeSecs == nil || *sig.SigLifetimeSecs == 0 {
|
||||
return false
|
||||
}
|
||||
expiry := sig.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second)
|
||||
expiry := sig.CreationTime.Add(time.Duration(*sig.SigLifetimeSecs) * time.Second)
|
||||
return currentTime.After(expiry)
|
||||
}
|
||||
|
||||
// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing.
|
||||
func (sig *Signature) buildHashSuffix() (err error) {
|
||||
hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true)
|
||||
|
||||
var ok bool
|
||||
l := 6 + hashedSubpacketsLen
|
||||
sig.HashSuffix = make([]byte, l+6)
|
||||
sig.HashSuffix[0] = 4
|
||||
sig.HashSuffix[1] = uint8(sig.SigType)
|
||||
sig.HashSuffix[2] = uint8(sig.PubKeyAlgo)
|
||||
sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash)
|
||||
func (sig *Signature) buildHashSuffix(hashedSubpackets []byte) (err error) {
|
||||
hash, ok := s2k.HashToHashId(sig.Hash)
|
||||
if !ok {
|
||||
sig.HashSuffix = nil
|
||||
return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash)))
|
||||
}
|
||||
sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8)
|
||||
sig.HashSuffix[5] = byte(hashedSubpacketsLen)
|
||||
serializeSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true)
|
||||
trailer := sig.HashSuffix[l:]
|
||||
trailer[0] = 4
|
||||
trailer[1] = 0xff
|
||||
trailer[2] = byte(l >> 24)
|
||||
trailer[3] = byte(l >> 16)
|
||||
trailer[4] = byte(l >> 8)
|
||||
trailer[5] = byte(l)
|
||||
|
||||
hashedFields := bytes.NewBuffer([]byte{
|
||||
uint8(sig.Version),
|
||||
uint8(sig.SigType),
|
||||
uint8(sig.PubKeyAlgo),
|
||||
uint8(hash),
|
||||
uint8(len(hashedSubpackets) >> 8),
|
||||
uint8(len(hashedSubpackets)),
|
||||
})
|
||||
hashedFields.Write(hashedSubpackets)
|
||||
|
||||
var l uint64 = uint64(6 + len(hashedSubpackets))
|
||||
if sig.Version == 5 {
|
||||
hashedFields.Write([]byte{0x05, 0xff})
|
||||
hashedFields.Write([]byte{
|
||||
uint8(l >> 56), uint8(l >> 48), uint8(l >> 40), uint8(l >> 32),
|
||||
uint8(l >> 24), uint8(l >> 16), uint8(l >> 8), uint8(l),
|
||||
})
|
||||
} else {
|
||||
hashedFields.Write([]byte{0x04, 0xff})
|
||||
hashedFields.Write([]byte{
|
||||
uint8(l >> 24), uint8(l >> 16), uint8(l >> 8), uint8(l),
|
||||
})
|
||||
}
|
||||
sig.HashSuffix = make([]byte, hashedFields.Len())
|
||||
copy(sig.HashSuffix, hashedFields.Bytes())
|
||||
return
|
||||
}
|
||||
|
||||
func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) {
|
||||
err = sig.buildHashSuffix()
|
||||
hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true)
|
||||
hashedSubpackets := make([]byte, hashedSubpacketsLen)
|
||||
serializeSubpackets(hashedSubpackets, sig.outSubpackets, true)
|
||||
err = sig.buildHashSuffix(hashedSubpackets)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if sig.Version == 5 && (sig.SigType == 0x00 || sig.SigType == 0x01) {
|
||||
sig.AddMetadataToHashSuffix()
|
||||
}
|
||||
|
||||
h.Write(sig.HashSuffix)
|
||||
digest = h.Sum(nil)
|
||||
|
@ -509,17 +602,26 @@ func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) {
|
|||
// On success, the signature is stored in sig. Call Serialize to write it out.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) {
|
||||
sig.outSubpackets = sig.buildSubpackets()
|
||||
if priv.Dummy() {
|
||||
return errors.ErrDummyPrivateKey("dummy key found")
|
||||
}
|
||||
sig.Version = priv.PublicKey.Version
|
||||
sig.IssuerFingerprint = priv.PublicKey.Fingerprint
|
||||
sig.outSubpackets, err = sig.buildSubpackets(priv.PublicKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
digest, err := sig.signPrepareHash(h)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
switch priv.PubKeyAlgo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
|
||||
// supports both *rsa.PrivateKey and crypto.Signer
|
||||
sig.RSASignature.bytes, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash)
|
||||
sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes))
|
||||
sigdata, err := priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash)
|
||||
if err == nil {
|
||||
sig.RSASignature = encoding.NewMPI(sigdata)
|
||||
}
|
||||
case PubKeyAlgoDSA:
|
||||
dsaPriv := priv.PrivateKey.(*dsa.PrivateKey)
|
||||
|
||||
|
@ -530,10 +632,8 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e
|
|||
}
|
||||
r, s, err := dsa.Sign(config.Random(), dsaPriv, digest)
|
||||
if err == nil {
|
||||
sig.DSASigR.bytes = r.Bytes()
|
||||
sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes))
|
||||
sig.DSASigS.bytes = s.Bytes()
|
||||
sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
|
||||
sig.DSASigR = new(encoding.MPI).SetBig(r)
|
||||
sig.DSASigS = new(encoding.MPI).SetBig(s)
|
||||
}
|
||||
case PubKeyAlgoECDSA:
|
||||
var r, s *big.Int
|
||||
|
@ -548,8 +648,14 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e
|
|||
}
|
||||
}
|
||||
if err == nil {
|
||||
sig.ECDSASigR = fromBig(r)
|
||||
sig.ECDSASigS = fromBig(s)
|
||||
sig.ECDSASigR = new(encoding.MPI).SetBig(r)
|
||||
sig.ECDSASigS = new(encoding.MPI).SetBig(s)
|
||||
}
|
||||
case PubKeyAlgoEdDSA:
|
||||
sigdata, err := priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, crypto.Hash(0))
|
||||
if err == nil {
|
||||
sig.EdDSASigR = encoding.NewMPI(sigdata[:32])
|
||||
sig.EdDSASigS = encoding.NewMPI(sigdata[32:])
|
||||
}
|
||||
default:
|
||||
err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
|
||||
|
@ -576,6 +682,9 @@ func unwrapECDSASig(b []byte) (r, s *big.Int, err error) {
|
|||
// Serialize to write it out.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error {
|
||||
if priv.Dummy() {
|
||||
return errors.ErrDummyPrivateKey("dummy key found")
|
||||
}
|
||||
h, err := userIdSignatureHash(id, pub, sig.Hash)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -583,10 +692,25 @@ func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, co
|
|||
return sig.Sign(h, priv, config)
|
||||
}
|
||||
|
||||
// CrossSignKey computes a signature from signingKey on pub hashed using hashKey. On success,
|
||||
// the signature is stored in sig. Call Serialize to write it out.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func (sig *Signature) CrossSignKey(pub *PublicKey, hashKey *PublicKey, signingKey *PrivateKey,
|
||||
config *Config) error {
|
||||
h, err := keySignatureHash(hashKey, pub, sig.Hash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return sig.Sign(h, signingKey, config)
|
||||
}
|
||||
|
||||
// SignKey computes a signature from priv, asserting that pub is a subkey. On
|
||||
// success, the signature is stored in sig. Call Serialize to write it out.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config) error {
|
||||
if priv.Dummy() {
|
||||
return errors.ErrDummyPrivateKey("dummy key found")
|
||||
}
|
||||
h, err := keySignatureHash(&priv.PublicKey, pub, sig.Hash)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -594,26 +718,40 @@ func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config)
|
|||
return sig.Sign(h, priv, config)
|
||||
}
|
||||
|
||||
// RevokeKey computes a revocation signature of pub using priv. On success, the signature is
|
||||
// stored in sig. Call Serialize to write it out.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func (sig *Signature) RevokeKey(pub *PublicKey, priv *PrivateKey, config *Config) error {
|
||||
h, err := keyRevocationHash(pub, sig.Hash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return sig.Sign(h, priv, config)
|
||||
}
|
||||
|
||||
// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been
|
||||
// called first.
|
||||
func (sig *Signature) Serialize(w io.Writer) (err error) {
|
||||
if len(sig.outSubpackets) == 0 {
|
||||
sig.outSubpackets = sig.rawSubpackets
|
||||
}
|
||||
if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil && sig.ECDSASigR.bytes == nil {
|
||||
if sig.RSASignature == nil && sig.DSASigR == nil && sig.ECDSASigR == nil && sig.EdDSASigR == nil {
|
||||
return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize")
|
||||
}
|
||||
|
||||
sigLength := 0
|
||||
switch sig.PubKeyAlgo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
|
||||
sigLength = 2 + len(sig.RSASignature.bytes)
|
||||
sigLength = int(sig.RSASignature.EncodedLength())
|
||||
case PubKeyAlgoDSA:
|
||||
sigLength = 2 + len(sig.DSASigR.bytes)
|
||||
sigLength += 2 + len(sig.DSASigS.bytes)
|
||||
sigLength = int(sig.DSASigR.EncodedLength())
|
||||
sigLength += int(sig.DSASigS.EncodedLength())
|
||||
case PubKeyAlgoECDSA:
|
||||
sigLength = 2 + len(sig.ECDSASigR.bytes)
|
||||
sigLength += 2 + len(sig.ECDSASigS.bytes)
|
||||
sigLength = int(sig.ECDSASigR.EncodedLength())
|
||||
sigLength += int(sig.ECDSASigS.EncodedLength())
|
||||
case PubKeyAlgoEdDSA:
|
||||
sigLength = int(sig.EdDSASigR.EncodedLength())
|
||||
sigLength += int(sig.EdDSASigS.EncodedLength())
|
||||
default:
|
||||
panic("impossible")
|
||||
}
|
||||
|
@ -622,16 +760,29 @@ func (sig *Signature) Serialize(w io.Writer) (err error) {
|
|||
length := len(sig.HashSuffix) - 6 /* trailer not included */ +
|
||||
2 /* length of unhashed subpackets */ + unhashedSubpacketsLen +
|
||||
2 /* hash tag */ + sigLength
|
||||
if sig.Version == 5 {
|
||||
length -= 4 // eight-octet instead of four-octet big endian
|
||||
}
|
||||
err = serializeHeader(w, packetTypeSignature, length)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = sig.serializeBody(w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
_, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6])
|
||||
func (sig *Signature) serializeBody(w io.Writer) (err error) {
|
||||
hashedSubpacketsLen := uint16(uint16(sig.HashSuffix[4])<<8) | uint16(sig.HashSuffix[5])
|
||||
fields := sig.HashSuffix[:6+hashedSubpacketsLen]
|
||||
_, err = w.Write(fields)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false)
|
||||
unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen)
|
||||
unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8)
|
||||
unhashedSubpackets[1] = byte(unhashedSubpacketsLen)
|
||||
|
@ -648,11 +799,22 @@ func (sig *Signature) Serialize(w io.Writer) (err error) {
|
|||
|
||||
switch sig.PubKeyAlgo {
|
||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
|
||||
err = writeMPIs(w, sig.RSASignature)
|
||||
_, err = w.Write(sig.RSASignature.EncodedBytes())
|
||||
case PubKeyAlgoDSA:
|
||||
err = writeMPIs(w, sig.DSASigR, sig.DSASigS)
|
||||
if _, err = w.Write(sig.DSASigR.EncodedBytes()); err != nil {
|
||||
return
|
||||
}
|
||||
_, err = w.Write(sig.DSASigS.EncodedBytes())
|
||||
case PubKeyAlgoECDSA:
|
||||
err = writeMPIs(w, sig.ECDSASigR, sig.ECDSASigS)
|
||||
if _, err = w.Write(sig.ECDSASigR.EncodedBytes()); err != nil {
|
||||
return
|
||||
}
|
||||
_, err = w.Write(sig.ECDSASigS.EncodedBytes())
|
||||
case PubKeyAlgoEdDSA:
|
||||
if _, err = w.Write(sig.EdDSASigR.EncodedBytes()); err != nil {
|
||||
return
|
||||
}
|
||||
_, err = w.Write(sig.EdDSASigS.EncodedBytes())
|
||||
default:
|
||||
panic("impossible")
|
||||
}
|
||||
|
@ -667,17 +829,20 @@ type outputSubpacket struct {
|
|||
contents []byte
|
||||
}
|
||||
|
||||
func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) {
|
||||
func (sig *Signature) buildSubpackets(issuer PublicKey) (subpackets []outputSubpacket, err error) {
|
||||
creationTime := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix()))
|
||||
subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime})
|
||||
|
||||
if sig.IssuerKeyId != nil {
|
||||
if sig.IssuerKeyId != nil && sig.Version == 4 {
|
||||
keyId := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId)
|
||||
subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId})
|
||||
subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, true, keyId})
|
||||
}
|
||||
if sig.IssuerFingerprint != nil {
|
||||
contents := append([]uint8{uint8(issuer.Version)}, sig.IssuerFingerprint...)
|
||||
subpackets = append(subpackets, outputSubpacket{true, issuerFingerprintSubpacket, true, contents})
|
||||
}
|
||||
|
||||
if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 {
|
||||
sigLifetime := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs)
|
||||
|
@ -703,7 +868,22 @@ func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) {
|
|||
subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}})
|
||||
}
|
||||
|
||||
// The following subpackets may only appear in self-signatures
|
||||
// The following subpackets may only appear in self-signatures.
|
||||
|
||||
var features = byte(0x00)
|
||||
if sig.MDC {
|
||||
features |= 0x01
|
||||
}
|
||||
if sig.AEAD {
|
||||
features |= 0x02
|
||||
}
|
||||
if sig.V5Keys {
|
||||
features |= 0x04
|
||||
}
|
||||
|
||||
if features != 0x00 {
|
||||
subpackets = append(subpackets, outputSubpacket{true, featuresSubpacket, false, []byte{features}})
|
||||
}
|
||||
|
||||
if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 {
|
||||
keyLifetime := make([]byte, 4)
|
||||
|
@ -727,5 +907,77 @@ func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) {
|
|||
subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression})
|
||||
}
|
||||
|
||||
if len(sig.PolicyURI) > 0 {
|
||||
subpackets = append(subpackets, outputSubpacket{true, policyUriSubpacket, false, []uint8(sig.PolicyURI)})
|
||||
}
|
||||
|
||||
if len(sig.PreferredAEAD) > 0 {
|
||||
subpackets = append(subpackets, outputSubpacket{true, prefAeadAlgosSubpacket, false, sig.PreferredAEAD})
|
||||
}
|
||||
|
||||
// Revocation reason appears only in revocation signatures and is serialized as per section 5.2.3.23.
|
||||
if sig.RevocationReason != nil {
|
||||
subpackets = append(subpackets, outputSubpacket{true, reasonForRevocationSubpacket, true,
|
||||
append([]uint8{*sig.RevocationReason}, []uint8(sig.RevocationReasonText)...)})
|
||||
}
|
||||
|
||||
// EmbeddedSignature appears only in subkeys capable of signing and is serialized as per section 5.2.3.26.
|
||||
if sig.EmbeddedSignature != nil {
|
||||
var buf bytes.Buffer
|
||||
err = sig.EmbeddedSignature.serializeBody(&buf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
subpackets = append(subpackets, outputSubpacket{true, embeddedSignatureSubpacket, true, buf.Bytes()})
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// AddMetadataToHashSuffix modifies the current hash suffix to include metadata
|
||||
// (format, filename, and time). Version 5 keys protect this data including it
|
||||
// in the hash computation. See section 5.2.4.
|
||||
func (sig *Signature) AddMetadataToHashSuffix() {
|
||||
if sig == nil || sig.Version != 5 {
|
||||
return
|
||||
}
|
||||
if sig.SigType != 0x00 && sig.SigType != 0x01 {
|
||||
return
|
||||
}
|
||||
lit := sig.Metadata
|
||||
if lit == nil {
|
||||
// This will translate into six 0x00 bytes.
|
||||
lit = &LiteralData{}
|
||||
}
|
||||
|
||||
// Extract the current byte count
|
||||
n := sig.HashSuffix[len(sig.HashSuffix)-8:]
|
||||
l := uint64(
|
||||
uint64(n[0])<<56 | uint64(n[1])<<48 | uint64(n[2])<<40 | uint64(n[3])<<32 |
|
||||
uint64(n[4])<<24 | uint64(n[5])<<16 | uint64(n[6])<<8 | uint64(n[7]))
|
||||
|
||||
suffix := bytes.NewBuffer(nil)
|
||||
suffix.Write(sig.HashSuffix[:l])
|
||||
|
||||
// Add the metadata
|
||||
var buf [4]byte
|
||||
buf[0] = lit.Format
|
||||
fileName := lit.FileName
|
||||
if len(lit.FileName) > 255 {
|
||||
fileName = fileName[:255]
|
||||
}
|
||||
buf[1] = byte(len(fileName))
|
||||
suffix.Write(buf[:2])
|
||||
suffix.Write([]byte(lit.FileName))
|
||||
binary.BigEndian.PutUint32(buf[:], lit.Time)
|
||||
suffix.Write(buf[:])
|
||||
|
||||
// Update the counter and restore trailing bytes
|
||||
l = uint64(suffix.Len())
|
||||
suffix.Write([]byte{0x05, 0xff})
|
||||
suffix.Write([]byte{
|
||||
uint8(l >> 56), uint8(l >> 48), uint8(l >> 40), uint8(l >> 32),
|
||||
uint8(l >> 24), uint8(l >> 16), uint8(l >> 8), uint8(l),
|
||||
})
|
||||
sig.HashSuffix = suffix.Bytes()
|
||||
}
|
267
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetric_key_encrypted.go
generated
vendored
Normal file
267
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetric_key_encrypted.go
generated
vendored
Normal file
|
@ -0,0 +1,267 @@
|
|||
// Copyright 2011 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 packet
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/cipher"
|
||||
"io"
|
||||
"strconv"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/s2k"
|
||||
)
|
||||
|
||||
// This is the largest session key that we'll support. Since no 512-bit cipher
|
||||
// has even been seriously used, this is comfortably large.
|
||||
const maxSessionKeySizeInBytes = 64
|
||||
|
||||
// SymmetricKeyEncrypted represents a passphrase protected session key. See RFC
|
||||
// 4880, section 5.3.
|
||||
type SymmetricKeyEncrypted struct {
|
||||
Version int
|
||||
CipherFunc CipherFunction
|
||||
Mode AEADMode
|
||||
s2k func(out, in []byte)
|
||||
aeadNonce []byte
|
||||
encryptedKey []byte
|
||||
}
|
||||
|
||||
func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error {
|
||||
// RFC 4880, section 5.3.
|
||||
var buf [2]byte
|
||||
if _, err := readFull(r, buf[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
ske.Version = int(buf[0])
|
||||
if ske.Version != 4 && ske.Version != 5 {
|
||||
return errors.UnsupportedError("unknown SymmetricKeyEncrypted version")
|
||||
}
|
||||
ske.CipherFunc = CipherFunction(buf[1])
|
||||
if ske.CipherFunc.KeySize() == 0 {
|
||||
return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1])))
|
||||
}
|
||||
|
||||
if ske.Version == 5 {
|
||||
mode := make([]byte, 1)
|
||||
if _, err := r.Read(mode); err != nil {
|
||||
return errors.StructuralError("cannot read AEAD octect from packet")
|
||||
}
|
||||
ske.Mode = AEADMode(mode[0])
|
||||
}
|
||||
|
||||
var err error
|
||||
if ske.s2k, err = s2k.Parse(r); err != nil {
|
||||
if _, ok := err.(errors.ErrDummyPrivateKey); ok {
|
||||
return errors.UnsupportedError("missing key GNU extension in session key")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if ske.Version == 5 {
|
||||
// AEAD nonce
|
||||
nonce := make([]byte, ske.Mode.NonceLength())
|
||||
_, err := readFull(r, nonce)
|
||||
if err != nil && err != io.ErrUnexpectedEOF {
|
||||
return err
|
||||
}
|
||||
ske.aeadNonce = nonce
|
||||
}
|
||||
|
||||
encryptedKey := make([]byte, maxSessionKeySizeInBytes)
|
||||
// The session key may follow. We just have to try and read to find
|
||||
// out. If it exists then we limit it to maxSessionKeySizeInBytes.
|
||||
n, err := readFull(r, encryptedKey)
|
||||
if err != nil && err != io.ErrUnexpectedEOF {
|
||||
return err
|
||||
}
|
||||
|
||||
if n != 0 {
|
||||
if n == maxSessionKeySizeInBytes {
|
||||
return errors.UnsupportedError("oversized encrypted session key")
|
||||
}
|
||||
ske.encryptedKey = encryptedKey[:n]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Decrypt attempts to decrypt an encrypted session key and returns the key and
|
||||
// the cipher to use when decrypting a subsequent Symmetrically Encrypted Data
|
||||
// packet.
|
||||
func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) ([]byte, CipherFunction, error) {
|
||||
key := make([]byte, ske.CipherFunc.KeySize())
|
||||
ske.s2k(key, passphrase)
|
||||
if len(ske.encryptedKey) == 0 {
|
||||
return key, ske.CipherFunc, nil
|
||||
}
|
||||
switch ske.Version {
|
||||
case 4:
|
||||
plaintextKey, cipherFunc, err := ske.decryptV4(key)
|
||||
return plaintextKey, cipherFunc, err
|
||||
case 5:
|
||||
plaintextKey, err := ske.decryptV5(key)
|
||||
return plaintextKey, CipherFunction(0), err
|
||||
}
|
||||
err := errors.UnsupportedError("unknown SymmetricKeyEncrypted version")
|
||||
return nil, CipherFunction(0), err
|
||||
}
|
||||
|
||||
func (ske *SymmetricKeyEncrypted) decryptV4(key []byte) ([]byte, CipherFunction, error) {
|
||||
// the IV is all zeros
|
||||
iv := make([]byte, ske.CipherFunc.blockSize())
|
||||
c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv)
|
||||
plaintextKey := make([]byte, len(ske.encryptedKey))
|
||||
c.XORKeyStream(plaintextKey, ske.encryptedKey)
|
||||
cipherFunc := CipherFunction(plaintextKey[0])
|
||||
if cipherFunc.blockSize() == 0 {
|
||||
return nil, ske.CipherFunc, errors.UnsupportedError(
|
||||
"unknown cipher: " + strconv.Itoa(int(cipherFunc)))
|
||||
}
|
||||
plaintextKey = plaintextKey[1:]
|
||||
if len(plaintextKey) != cipherFunc.KeySize() {
|
||||
return nil, cipherFunc, errors.StructuralError(
|
||||
"length of decrypted key not equal to cipher keysize")
|
||||
}
|
||||
return plaintextKey, cipherFunc, nil
|
||||
}
|
||||
|
||||
func (ske *SymmetricKeyEncrypted) decryptV5(key []byte) ([]byte, error) {
|
||||
blockCipher := CipherFunction(ske.CipherFunc).new(key)
|
||||
aead := ske.Mode.new(blockCipher)
|
||||
|
||||
adata := []byte{0xc3, byte(5), byte(ske.CipherFunc), byte(ske.Mode)}
|
||||
plaintextKey, err := aead.Open(nil, ske.aeadNonce, ske.encryptedKey, adata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return plaintextKey, nil
|
||||
}
|
||||
|
||||
// SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w.
|
||||
// The packet contains a random session key, encrypted by a key derived from
|
||||
// the given passphrase. The session key is returned and must be passed to
|
||||
// SerializeSymmetricallyEncrypted or SerializeAEADEncrypted, depending on
|
||||
// whether config.AEADConfig != nil.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Config) (key []byte, err error) {
|
||||
cipherFunc := config.Cipher()
|
||||
keySize := cipherFunc.KeySize()
|
||||
if keySize == 0 {
|
||||
return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
|
||||
}
|
||||
|
||||
sessionKey := make([]byte, keySize)
|
||||
_, err = io.ReadFull(config.Random(), sessionKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = SerializeSymmetricKeyEncryptedReuseKey(w, sessionKey, passphrase, config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
key = sessionKey
|
||||
return
|
||||
}
|
||||
|
||||
// SerializeSymmetricKeyEncryptedReuseKey serializes a symmetric key packet to w.
|
||||
// The packet contains the given session key, encrypted by a key derived from
|
||||
// the given passphrase. The session key must be passed to
|
||||
// SerializeSymmetricallyEncrypted or SerializeAEADEncrypted, depending on
|
||||
// whether config.AEADConfig != nil.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func SerializeSymmetricKeyEncryptedReuseKey(w io.Writer, sessionKey []byte, passphrase []byte, config *Config) (err error) {
|
||||
var version int
|
||||
if config.AEAD() != nil {
|
||||
version = 5
|
||||
} else {
|
||||
version = 4
|
||||
}
|
||||
cipherFunc := config.Cipher()
|
||||
keySize := cipherFunc.KeySize()
|
||||
if keySize == 0 {
|
||||
return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
|
||||
}
|
||||
|
||||
s2kBuf := new(bytes.Buffer)
|
||||
keyEncryptingKey := make([]byte, keySize)
|
||||
// s2k.Serialize salts and stretches the passphrase, and writes the
|
||||
// resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf.
|
||||
err = s2k.Serialize(s2kBuf, keyEncryptingKey, config.Random(), passphrase, &s2k.Config{Hash: config.Hash(), S2KCount: config.PasswordHashIterations()})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
s2kBytes := s2kBuf.Bytes()
|
||||
|
||||
var packetLength int
|
||||
switch version {
|
||||
case 4:
|
||||
packetLength = 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize
|
||||
case 5:
|
||||
nonceLen := config.AEAD().Mode().NonceLength()
|
||||
tagLen := config.AEAD().Mode().TagLength()
|
||||
packetLength = 3 + len(s2kBytes) + nonceLen + keySize + tagLen
|
||||
}
|
||||
err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf := make([]byte, 2)
|
||||
// Symmetric Key Encrypted Version
|
||||
buf[0] = byte(version)
|
||||
// Cipher function
|
||||
buf[1] = byte(cipherFunc)
|
||||
|
||||
if version == 5 {
|
||||
// AEAD mode
|
||||
buf = append(buf, byte(config.AEAD().Mode()))
|
||||
}
|
||||
_, err = w.Write(buf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, err = w.Write(s2kBytes)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
switch version {
|
||||
case 4:
|
||||
iv := make([]byte, cipherFunc.blockSize())
|
||||
c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv)
|
||||
encryptedCipherAndKey := make([]byte, keySize+1)
|
||||
c.XORKeyStream(encryptedCipherAndKey, buf[1:])
|
||||
c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey)
|
||||
_, err = w.Write(encryptedCipherAndKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
case 5:
|
||||
blockCipher := cipherFunc.new(keyEncryptingKey)
|
||||
mode := config.AEAD().Mode()
|
||||
aead := mode.new(blockCipher)
|
||||
// Sample nonce using random reader
|
||||
nonce := make([]byte, config.AEAD().Mode().NonceLength())
|
||||
_, err = io.ReadFull(config.Random(), nonce)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// Seal and write (encryptedData includes auth. tag)
|
||||
adata := []byte{0xc3, byte(5), byte(cipherFunc), byte(mode)}
|
||||
encryptedData := aead.Seal(nil, nonce, sessionKey, adata)
|
||||
_, err = w.Write(nonce)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, err = w.Write(encryptedData)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
|
@ -8,18 +8,19 @@ import (
|
|||
"crypto/cipher"
|
||||
"crypto/sha1"
|
||||
"crypto/subtle"
|
||||
"golang.org/x/crypto/openpgp/errors"
|
||||
"hash"
|
||||
"io"
|
||||
"strconv"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
)
|
||||
|
||||
// SymmetricallyEncrypted represents a symmetrically encrypted byte string. The
|
||||
// encrypted contents will consist of more OpenPGP packets. See RFC 4880,
|
||||
// encrypted Contents will consist of more OpenPGP packets. See RFC 4880,
|
||||
// sections 5.7 and 5.13.
|
||||
type SymmetricallyEncrypted struct {
|
||||
MDC bool // true iff this is a type 18 packet and thus has an embedded MAC.
|
||||
contents io.Reader
|
||||
Contents io.Reader
|
||||
prefix []byte
|
||||
}
|
||||
|
||||
|
@ -37,13 +38,13 @@ func (se *SymmetricallyEncrypted) parse(r io.Reader) error {
|
|||
return errors.UnsupportedError("unknown SymmetricallyEncrypted version")
|
||||
}
|
||||
}
|
||||
se.contents = r
|
||||
se.Contents = r
|
||||
return nil
|
||||
}
|
||||
|
||||
// Decrypt returns a ReadCloser, from which the decrypted contents of the
|
||||
// packet can be read. An incorrect key can, with high probability, be detected
|
||||
// immediately and this will result in a KeyIncorrect error being returned.
|
||||
// Decrypt returns a ReadCloser, from which the decrypted Contents of the
|
||||
// packet can be read. An incorrect key will only be detected after trying
|
||||
// to decrypt the entire data.
|
||||
func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.ReadCloser, error) {
|
||||
keySize := c.KeySize()
|
||||
if keySize == 0 {
|
||||
|
@ -55,7 +56,7 @@ func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.Read
|
|||
|
||||
if se.prefix == nil {
|
||||
se.prefix = make([]byte, c.blockSize()+2)
|
||||
_, err := readFull(se.contents, se.prefix)
|
||||
_, err := readFull(se.Contents, se.prefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -70,11 +71,8 @@ func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.Read
|
|||
}
|
||||
|
||||
s := NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync)
|
||||
if s == nil {
|
||||
return nil, errors.ErrKeyIncorrect
|
||||
}
|
||||
|
||||
plaintext := cipher.StreamReader{S: s, R: se.contents}
|
||||
plaintext := cipher.StreamReader{S: s, R: se.Contents}
|
||||
|
||||
if se.MDC {
|
||||
// MDC packets have an embedded hash that we need to check.
|
||||
|
@ -104,7 +102,7 @@ const mdcTrailerSize = 1 /* tag byte */ + 1 /* length byte */ + sha1.Size
|
|||
|
||||
// An seMDCReader wraps an io.Reader, maintains a running hash and keeps hold
|
||||
// of the most recent 22 bytes (mdcTrailerSize). Upon EOF, those bytes form an
|
||||
// MDC packet containing a hash of the previous contents which is checked
|
||||
// MDC packet containing a hash of the previous Contents which is checked
|
||||
// against the running hash. See RFC 4880, section 5.13.
|
||||
type seMDCReader struct {
|
||||
in io.Reader
|
||||
|
@ -180,7 +178,7 @@ const mdcPacketTagByte = byte(0x80) | 0x40 | 19
|
|||
|
||||
func (ser *seMDCReader) Close() error {
|
||||
if ser.error {
|
||||
return errors.SignatureError("error during reading")
|
||||
return errors.ErrMDCMissing
|
||||
}
|
||||
|
||||
for !ser.eof {
|
||||
|
@ -191,18 +189,20 @@ func (ser *seMDCReader) Close() error {
|
|||
break
|
||||
}
|
||||
if err != nil {
|
||||
return errors.SignatureError("error during reading")
|
||||
return errors.ErrMDCMissing
|
||||
}
|
||||
}
|
||||
|
||||
if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size {
|
||||
return errors.SignatureError("MDC packet not found")
|
||||
}
|
||||
ser.h.Write(ser.trailer[:2])
|
||||
|
||||
final := ser.h.Sum(nil)
|
||||
if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 {
|
||||
return errors.SignatureError("hash mismatch")
|
||||
return errors.ErrMDCHashMismatch
|
||||
}
|
||||
// The hash already includes the MDC header, but we still check its value
|
||||
// to confirm encryption correctness
|
||||
if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size {
|
||||
return errors.ErrMDCMissing
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -253,7 +253,7 @@ func (c noOpCloser) Close() error {
|
|||
// to w and returns a WriteCloser to which the to-be-encrypted packets can be
|
||||
// written.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte, config *Config) (contents io.WriteCloser, err error) {
|
||||
func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte, config *Config) (Contents io.WriteCloser, err error) {
|
||||
if c.KeySize() != len(key) {
|
||||
return nil, errors.InvalidArgumentError("SymmetricallyEncrypted.Serialize: bad key length")
|
||||
}
|
||||
|
@ -285,6 +285,6 @@ func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte,
|
|||
h := sha1.New()
|
||||
h.Write(iv)
|
||||
h.Write(iv[blockSize-2:])
|
||||
contents = &seMDCWriter{w: plaintext, h: h}
|
||||
Contents = &seMDCWriter{w: plaintext, h: h}
|
||||
return
|
||||
}
|
|
@ -69,7 +69,10 @@ func (uat *UserAttribute) parse(r io.Reader) (err error) {
|
|||
func (uat *UserAttribute) Serialize(w io.Writer) (err error) {
|
||||
var buf bytes.Buffer
|
||||
for _, sp := range uat.Contents {
|
||||
sp.Serialize(&buf)
|
||||
err = sp.Serialize(&buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err = serializeHeader(w, packetTypeUserAttribute, buf.Len()); err != nil {
|
||||
return err
|
|
@ -3,7 +3,7 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package openpgp implements high level operations on OpenPGP messages.
|
||||
package openpgp // import "golang.org/x/crypto/openpgp"
|
||||
package openpgp // import "github.com/ProtonMail/go-crypto/openpgp"
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
|
@ -12,9 +12,9 @@ import (
|
|||
"io"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/crypto/openpgp/armor"
|
||||
"golang.org/x/crypto/openpgp/errors"
|
||||
"golang.org/x/crypto/openpgp/packet"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/armor"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/packet"
|
||||
)
|
||||
|
||||
// SignatureType is the armor type for a PGP signature.
|
||||
|
@ -56,9 +56,9 @@ type MessageDetails struct {
|
|||
// been consumed. Once EOF has been seen, the following fields are
|
||||
// valid. (An authentication code failure is reported as a
|
||||
// SignatureError error when reading from UnverifiedBody.)
|
||||
SignatureError error // nil if the signature is good.
|
||||
Signature *packet.Signature // the signature packet itself, if v4 (default)
|
||||
SignatureV3 *packet.SignatureV3 // the signature packet if it is a v2 or v3 signature
|
||||
Signature *packet.Signature // the signature packet itself.
|
||||
SignatureError error // nil if the signature is good.
|
||||
UnverifiedSignatures []*packet.Signature // all other unverified signature packets.
|
||||
|
||||
decrypted io.ReadCloser
|
||||
}
|
||||
|
@ -88,7 +88,8 @@ func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction, config *pa
|
|||
|
||||
var symKeys []*packet.SymmetricKeyEncrypted
|
||||
var pubKeys []keyEnvelopePair
|
||||
var se *packet.SymmetricallyEncrypted
|
||||
// Integrity protected encrypted packet: SymmetricallyEncrypted or AEADEncrypted
|
||||
var edp packet.EncryptedDataPacket
|
||||
|
||||
packets := packet.NewReader(r)
|
||||
md = new(MessageDetails)
|
||||
|
@ -113,7 +114,7 @@ ParsePackets:
|
|||
// This packet contains the decryption key encrypted to a public key.
|
||||
md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId)
|
||||
switch p.Algo {
|
||||
case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal:
|
||||
case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal, packet.PubKeyAlgoECDH:
|
||||
break
|
||||
default:
|
||||
continue
|
||||
|
@ -127,8 +128,8 @@ ParsePackets:
|
|||
for _, k := range keys {
|
||||
pubKeys = append(pubKeys, keyEnvelopePair{k, p})
|
||||
}
|
||||
case *packet.SymmetricallyEncrypted:
|
||||
se = p
|
||||
case *packet.SymmetricallyEncrypted, *packet.AEADEncrypted:
|
||||
edp = p.(packet.EncryptedDataPacket)
|
||||
break ParsePackets
|
||||
case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature:
|
||||
// This message isn't encrypted.
|
||||
|
@ -136,7 +137,7 @@ ParsePackets:
|
|||
return nil, errors.StructuralError("key material not followed by encrypted message")
|
||||
}
|
||||
packets.Unread(p)
|
||||
return readSignedMessage(packets, nil, keyring)
|
||||
return readSignedMessage(packets, nil, keyring, config)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,12 +159,13 @@ FindKey:
|
|||
}
|
||||
if !pk.key.PrivateKey.Encrypted {
|
||||
if len(pk.encryptedKey.Key) == 0 {
|
||||
pk.encryptedKey.Decrypt(pk.key.PrivateKey, config)
|
||||
errDec := pk.encryptedKey.Decrypt(pk.key.PrivateKey, config)
|
||||
if errDec != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if len(pk.encryptedKey.Key) == 0 {
|
||||
continue
|
||||
}
|
||||
decrypted, err = se.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key)
|
||||
// Try to decrypt symmetrically encrypted
|
||||
decrypted, err = edp.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key)
|
||||
if err != nil && err != errors.ErrKeyIncorrect {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -198,8 +200,12 @@ FindKey:
|
|||
if len(symKeys) != 0 && passphrase != nil {
|
||||
for _, s := range symKeys {
|
||||
key, cipherFunc, err := s.Decrypt(passphrase)
|
||||
// On wrong passphrase, session key decryption is very likely to result in an invalid cipherFunc:
|
||||
// only for < 5% of cases we will proceed to decrypt the data
|
||||
if err == nil {
|
||||
decrypted, err = se.Decrypt(cipherFunc, key)
|
||||
decrypted, err = edp.Decrypt(cipherFunc, key)
|
||||
// TODO: ErrKeyIncorrect is no longer thrown on SEIP decryption,
|
||||
// but it might still be relevant for when we implement AEAD decryption (otherwise, remove?)
|
||||
if err != nil && err != errors.ErrKeyIncorrect {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -207,7 +213,6 @@ FindKey:
|
|||
break FindKey
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -216,13 +221,17 @@ FindKey:
|
|||
if err := packets.Push(decrypted); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return readSignedMessage(packets, md, keyring)
|
||||
mdFinal, sensitiveParsingErr := readSignedMessage(packets, md, keyring, config)
|
||||
if sensitiveParsingErr != nil {
|
||||
return nil, errors.StructuralError("parsing error")
|
||||
}
|
||||
return mdFinal, nil
|
||||
}
|
||||
|
||||
// readSignedMessage reads a possibly signed message if mdin is non-zero then
|
||||
// that structure is updated and returned. Otherwise a fresh MessageDetails is
|
||||
// used.
|
||||
func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing) (md *MessageDetails, err error) {
|
||||
func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing, config *packet.Config) (md *MessageDetails, err error) {
|
||||
if mdin == nil {
|
||||
mdin = new(MessageDetails)
|
||||
}
|
||||
|
@ -231,6 +240,7 @@ func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring Key
|
|||
var p packet.Packet
|
||||
var h hash.Hash
|
||||
var wrappedHash hash.Hash
|
||||
var prevLast bool
|
||||
FindLiteralData:
|
||||
for {
|
||||
p, err = packets.Next()
|
||||
|
@ -243,14 +253,17 @@ FindLiteralData:
|
|||
return nil, err
|
||||
}
|
||||
case *packet.OnePassSignature:
|
||||
if !p.IsLast {
|
||||
return nil, errors.UnsupportedError("nested signatures")
|
||||
if prevLast {
|
||||
return nil, errors.UnsupportedError("nested signature packets")
|
||||
}
|
||||
|
||||
if p.IsLast {
|
||||
prevLast = true
|
||||
}
|
||||
|
||||
h, wrappedHash, err = hashForSignature(p.Hash, p.SigType)
|
||||
if err != nil {
|
||||
md = nil
|
||||
return
|
||||
md.SignatureError = err
|
||||
}
|
||||
|
||||
md.IsSigned = true
|
||||
|
@ -265,8 +278,8 @@ FindLiteralData:
|
|||
}
|
||||
}
|
||||
|
||||
if md.SignedBy != nil {
|
||||
md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md}
|
||||
if md.IsSigned && md.SignatureError == nil {
|
||||
md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md, config}
|
||||
} else if md.decrypted != nil {
|
||||
md.UnverifiedBody = checkReader{md}
|
||||
} else {
|
||||
|
@ -282,6 +295,9 @@ FindLiteralData:
|
|||
// returns two hashes. The second should be used to hash the message itself and
|
||||
// performs any needed preprocessing.
|
||||
func hashForSignature(hashId crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, error) {
|
||||
if hashId == crypto.MD5 {
|
||||
return nil, nil, errors.UnsupportedError("insecure hash algorithm: MD5")
|
||||
}
|
||||
if !hashId.Available() {
|
||||
return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashId)))
|
||||
}
|
||||
|
@ -304,15 +320,21 @@ type checkReader struct {
|
|||
md *MessageDetails
|
||||
}
|
||||
|
||||
func (cr checkReader) Read(buf []byte) (n int, err error) {
|
||||
n, err = cr.md.LiteralData.Body.Read(buf)
|
||||
if err == io.EOF {
|
||||
func (cr checkReader) Read(buf []byte) (int, error) {
|
||||
n, sensitiveParsingError := cr.md.LiteralData.Body.Read(buf)
|
||||
if sensitiveParsingError == io.EOF {
|
||||
mdcErr := cr.md.decrypted.Close()
|
||||
if mdcErr != nil {
|
||||
err = mdcErr
|
||||
return n, mdcErr
|
||||
}
|
||||
return n, io.EOF
|
||||
}
|
||||
return
|
||||
|
||||
if sensitiveParsingError != nil {
|
||||
return n, errors.StructuralError("parsing error")
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes
|
||||
|
@ -322,26 +344,51 @@ type signatureCheckReader struct {
|
|||
packets *packet.Reader
|
||||
h, wrappedHash hash.Hash
|
||||
md *MessageDetails
|
||||
config *packet.Config
|
||||
}
|
||||
|
||||
func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) {
|
||||
n, err = scr.md.LiteralData.Body.Read(buf)
|
||||
scr.wrappedHash.Write(buf[:n])
|
||||
if err == io.EOF {
|
||||
func (scr *signatureCheckReader) Read(buf []byte) (int, error) {
|
||||
n, sensitiveParsingError := scr.md.LiteralData.Body.Read(buf)
|
||||
|
||||
// Hash only if required
|
||||
if scr.md.SignedBy != nil {
|
||||
scr.wrappedHash.Write(buf[:n])
|
||||
}
|
||||
|
||||
if sensitiveParsingError == io.EOF {
|
||||
var p packet.Packet
|
||||
p, scr.md.SignatureError = scr.packets.Next()
|
||||
if scr.md.SignatureError != nil {
|
||||
return
|
||||
var readError error
|
||||
var sig *packet.Signature
|
||||
|
||||
p, readError = scr.packets.Next()
|
||||
for readError == nil {
|
||||
var ok bool
|
||||
if sig, ok = p.(*packet.Signature); ok {
|
||||
if sig.Version == 5 && (sig.SigType == 0x00 || sig.SigType == 0x01) {
|
||||
sig.Metadata = scr.md.LiteralData
|
||||
}
|
||||
|
||||
// If signature KeyID matches
|
||||
if scr.md.SignedBy != nil && *sig.IssuerKeyId == scr.md.SignedByKeyId {
|
||||
scr.md.Signature = sig
|
||||
scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature)
|
||||
if scr.md.SignatureError == nil && scr.md.Signature.SigExpired(scr.config.Now()) {
|
||||
scr.md.SignatureError = errors.ErrSignatureExpired
|
||||
}
|
||||
} else {
|
||||
scr.md.UnverifiedSignatures = append(scr.md.UnverifiedSignatures, sig)
|
||||
}
|
||||
}
|
||||
|
||||
p, readError = scr.packets.Next()
|
||||
}
|
||||
|
||||
var ok bool
|
||||
if scr.md.Signature, ok = p.(*packet.Signature); ok {
|
||||
scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature)
|
||||
} else if scr.md.SignatureV3, ok = p.(*packet.SignatureV3); ok {
|
||||
scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignatureV3(scr.h, scr.md.SignatureV3)
|
||||
} else {
|
||||
scr.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature")
|
||||
return
|
||||
if scr.md.SignedBy != nil && scr.md.Signature == nil {
|
||||
if scr.md.UnverifiedSignatures == nil {
|
||||
scr.md.SignatureError = errors.StructuralError("LiteralData not followed by signature")
|
||||
} else {
|
||||
scr.md.SignatureError = errors.StructuralError("No matching signature found")
|
||||
}
|
||||
}
|
||||
|
||||
// The SymmetricallyEncrypted packet, if any, might have an
|
||||
|
@ -350,24 +397,39 @@ func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) {
|
|||
if scr.md.decrypted != nil {
|
||||
mdcErr := scr.md.decrypted.Close()
|
||||
if mdcErr != nil {
|
||||
err = mdcErr
|
||||
return n, mdcErr
|
||||
}
|
||||
}
|
||||
return n, io.EOF
|
||||
}
|
||||
return
|
||||
|
||||
if sensitiveParsingError != nil {
|
||||
return n, errors.StructuralError("parsing error")
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// CheckDetachedSignature takes a signed file and a detached signature and
|
||||
// returns the signer if the signature is valid. If the signer isn't known,
|
||||
// ErrUnknownIssuer is returned.
|
||||
func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) {
|
||||
func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader, config *packet.Config) (signer *Entity, err error) {
|
||||
var expectedHashes []crypto.Hash
|
||||
return CheckDetachedSignatureAndHash(keyring, signed, signature, expectedHashes, config)
|
||||
}
|
||||
|
||||
// CheckDetachedSignatureAndHash performs the same actions as
|
||||
// CheckDetachedSignature and checks that the expected hash functions were used.
|
||||
func CheckDetachedSignatureAndHash(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, config *packet.Config) (signer *Entity, err error) {
|
||||
var issuerKeyId uint64
|
||||
var hashFunc crypto.Hash
|
||||
var sigType packet.SignatureType
|
||||
var keys []Key
|
||||
var p packet.Packet
|
||||
|
||||
expectedHashesLen := len(expectedHashes)
|
||||
packets := packet.NewReader(signature)
|
||||
var sig *packet.Signature
|
||||
for {
|
||||
p, err = packets.Next()
|
||||
if err == io.EOF {
|
||||
|
@ -377,21 +439,26 @@ func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signe
|
|||
return nil, err
|
||||
}
|
||||
|
||||
switch sig := p.(type) {
|
||||
case *packet.Signature:
|
||||
if sig.IssuerKeyId == nil {
|
||||
return nil, errors.StructuralError("signature doesn't have an issuer")
|
||||
}
|
||||
issuerKeyId = *sig.IssuerKeyId
|
||||
hashFunc = sig.Hash
|
||||
sigType = sig.SigType
|
||||
case *packet.SignatureV3:
|
||||
issuerKeyId = sig.IssuerKeyId
|
||||
hashFunc = sig.Hash
|
||||
sigType = sig.SigType
|
||||
default:
|
||||
var ok bool
|
||||
sig, ok = p.(*packet.Signature)
|
||||
if !ok {
|
||||
return nil, errors.StructuralError("non signature packet found")
|
||||
}
|
||||
if sig.IssuerKeyId == nil {
|
||||
return nil, errors.StructuralError("signature doesn't have an issuer")
|
||||
}
|
||||
issuerKeyId = *sig.IssuerKeyId
|
||||
hashFunc = sig.Hash
|
||||
sigType = sig.SigType
|
||||
|
||||
for i, expectedHash := range expectedHashes {
|
||||
if hashFunc == expectedHash {
|
||||
break
|
||||
}
|
||||
if i+1 == expectedHashesLen {
|
||||
return nil, errors.StructuralError("hash algorithm mismatch with cleartext message headers")
|
||||
}
|
||||
}
|
||||
|
||||
keys = keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign)
|
||||
if len(keys) > 0 {
|
||||
|
@ -413,16 +480,15 @@ func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signe
|
|||
}
|
||||
|
||||
for _, key := range keys {
|
||||
switch sig := p.(type) {
|
||||
case *packet.Signature:
|
||||
err = key.PublicKey.VerifySignature(h, sig)
|
||||
case *packet.SignatureV3:
|
||||
err = key.PublicKey.VerifySignatureV3(h, sig)
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
err = key.PublicKey.VerifySignature(h, sig)
|
||||
if err == nil {
|
||||
now := config.Now()
|
||||
if sig.SigExpired(now) {
|
||||
return key.Entity, errors.ErrSignatureExpired
|
||||
}
|
||||
if key.PublicKey.KeyExpired(key.SelfSignature, now) {
|
||||
return key.Entity, errors.ErrKeyExpired
|
||||
}
|
||||
return key.Entity, nil
|
||||
}
|
||||
}
|
||||
|
@ -432,11 +498,11 @@ func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signe
|
|||
|
||||
// CheckArmoredDetachedSignature performs the same actions as
|
||||
// CheckDetachedSignature but expects the signature to be armored.
|
||||
func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) {
|
||||
func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader, config *packet.Config) (signer *Entity, err error) {
|
||||
body, err := readArmored(signature, SignatureType)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return CheckDetachedSignature(keyring, signed, body)
|
||||
return CheckDetachedSignature(keyring, signed, body, config)
|
||||
}
|
173
vendor/github.com/ProtonMail/go-crypto/openpgp/read_write_test_data.go
generated
vendored
Normal file
173
vendor/github.com/ProtonMail/go-crypto/openpgp/read_write_test_data.go
generated
vendored
Normal file
|
@ -0,0 +1,173 @@
|
|||
package openpgp
|
||||
|
||||
const testKey1KeyId = 0xA34D7E18C20C31BB
|
||||
const testKey3KeyId = 0x338934250CCC0360
|
||||
const testKeyP256KeyId = 0xd44a2c495918513e
|
||||
|
||||
const signedInput = "Signed message\nline 2\nline 3\n"
|
||||
const signedTextInput = "Signed message\r\nline 2\r\nline 3\r\n"
|
||||
|
||||
const recipientUnspecifiedHex = "848c0300000000000000000103ff62d4d578d03cf40c3da998dfe216c074fa6ddec5e31c197c9666ba292830d91d18716a80f699f9d897389a90e6d62d0238f5f07a5248073c0f24920e4bc4a30c2d17ee4e0cae7c3d4aaa4e8dced50e3010a80ee692175fa0385f62ecca4b56ee6e9980aa3ec51b61b077096ac9e800edaf161268593eedb6cc7027ff5cb32745d250010d407a6221ae22ef18469b444f2822478c4d190b24d36371a95cb40087cdd42d9399c3d06a53c0673349bfb607927f20d1e122bde1e2bf3aa6cae6edf489629bcaa0689539ae3b718914d88ededc3b"
|
||||
|
||||
const detachedSignatureHex = "889c04000102000605024d449cd1000a0910a34d7e18c20c31bb167603ff57718d09f28a519fdc7b5a68b6a3336da04df85e38c5cd5d5bd2092fa4629848a33d85b1729402a2aab39c3ac19f9d573f773cc62c264dc924c067a79dfd8a863ae06c7c8686120760749f5fd9b1e03a64d20a7df3446ddc8f0aeadeaeba7cbaee5c1e366d65b6a0c6cc749bcb912d2f15013f812795c2e29eb7f7b77f39ce77"
|
||||
|
||||
const detachedSignatureTextHex = "889c04010102000605024d449d21000a0910a34d7e18c20c31bbc8c60400a24fbef7342603a41cb1165767bd18985d015fb72fe05db42db36cfb2f1d455967f1e491194fbf6cf88146222b23bf6ffbd50d17598d976a0417d3192ff9cc0034fd00f287b02e90418bbefe609484b09231e4e7a5f3562e199bf39909ab5276c4d37382fe088f6b5c3426fc1052865da8b3ab158672d58b6264b10823dc4b39"
|
||||
|
||||
const detachedSignatureDSAHex = "884604001102000605024d6c4eac000a0910338934250ccc0360f18d00a087d743d6405ed7b87755476629600b8b694a39e900a0abff8126f46faf1547c1743c37b21b4ea15b8f83"
|
||||
|
||||
const detachedSignatureP256Hex = "885e0400130a0006050256e5bb00000a0910d44a2c495918513edef001009841a4f792beb0befccb35c8838a6a87d9b936beaa86db6745ddc7b045eee0cf00fd1ac1f78306b17e965935dd3f8bae4587a76587e4af231efe19cc4011a8434817"
|
||||
|
||||
// The plaintext is https://www.gutenberg.org/cache/epub/1080/pg1080.txt
|
||||
const modestProposalSha512 = "lbbrB1+WP3T9AaC9OQqBdOcCjgeEQadlulXsNPgVx0tyqPzDHwUugZ2gE7V0ESKAw6kAVfgkcuvfgxAAGaeHtw=="
|
||||
|
||||
const testKeys1And2Hex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b0020003b88d044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f0011010001889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab0020003988d044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b0020003b88d044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020003"
|
||||
|
||||
const testKeys1And2PrivateHex = "9501d8044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd00110100010003ff4d91393b9a8e3430b14d6209df42f98dc927425b881f1209f319220841273a802a97c7bdb8b3a7740b3ab5866c4d1d308ad0d3a79bd1e883aacf1ac92dfe720285d10d08752a7efe3c609b1d00f17f2805b217be53999a7da7e493bfc3e9618fd17018991b8128aea70a05dbce30e4fbe626aa45775fa255dd9177aabf4df7cf0200c1ded12566e4bc2bb590455e5becfb2e2c9796482270a943343a7835de41080582c2be3caf5981aa838140e97afa40ad652a0b544f83eb1833b0957dce26e47b0200eacd6046741e9ce2ec5beb6fb5e6335457844fb09477f83b050a96be7da043e17f3a9523567ed40e7a521f818813a8b8a72209f1442844843ccc7eb9805442570200bdafe0438d97ac36e773c7162028d65844c4d463e2420aa2228c6e50dc2743c3d6c72d0d782a5173fe7be2169c8a9f4ef8a7cf3e37165e8c61b89c346cdc6c1799d2b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b00200009d01d8044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f00110100010003fd17a7490c22a79c59281fb7b20f5e6553ec0c1637ae382e8adaea295f50241037f8997cf42c1ce26417e015091451b15424b2c59eb8d4161b0975630408e394d3b00f88d4b4e18e2cc85e8251d4753a27c639c83f5ad4a571c4f19d7cd460b9b73c25ade730c99df09637bd173d8e3e981ac64432078263bb6dc30d3e974150dd0200d0ee05be3d4604d2146fb0457f31ba17c057560785aa804e8ca5530a7cd81d3440d0f4ba6851efcfd3954b7e68908fc0ba47f7ac37bf559c6c168b70d3a7c8cd0200da1c677c4bce06a068070f2b3733b0a714e88d62aa3f9a26c6f5216d48d5c2b5624144f3807c0df30be66b3268eeeca4df1fbded58faf49fc95dc3c35f134f8b01fd1396b6c0fc1b6c4f0eb8f5e44b8eace1e6073e20d0b8bc5385f86f1cf3f050f66af789f3ef1fc107b7f4421e19e0349c730c68f0a226981f4e889054fdb4dc149e8e889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab00200009501fe044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001fe030302e9030f3c783e14856063f16938530e148bc57a7aa3f3e4f90df9dceccdc779bc0835e1ad3d006e4a8d7b36d08b8e0de5a0d947254ecfbd22037e6572b426bcfdc517796b224b0036ff90bc574b5509bede85512f2eefb520fb4b02aa523ba739bff424a6fe81c5041f253f8d757e69a503d3563a104d0d49e9e890b9d0c26f96b55b743883b472caa7050c4acfd4a21f875bdf1258d88bd61224d303dc9df77f743137d51e6d5246b88c406780528fd9a3e15bab5452e5b93970d9dcc79f48b38651b9f15bfbcf6da452837e9cc70683d1bdca94507870f743e4ad902005812488dd342f836e72869afd00ce1850eea4cfa53ce10e3608e13d3c149394ee3cbd0e23d018fcbcb6e2ec5a1a22972d1d462ca05355d0d290dd2751e550d5efb38c6c89686344df64852bf4ff86638708f644e8ec6bd4af9b50d8541cb91891a431326ab2e332faa7ae86cfb6e0540aa63160c1e5cdd5a4add518b303fff0a20117c6bc77f7cfbaf36b04c865c6c2b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b00200009d01fe044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001fe030302e9030f3c783e148560f936097339ae381d63116efcf802ff8b1c9360767db5219cc987375702a4123fd8657d3e22700f23f95020d1b261eda5257e9a72f9a918e8ef22dd5b3323ae03bbc1923dd224db988cadc16acc04b120a9f8b7e84da9716c53e0334d7b66586ddb9014df604b41be1e960dcfcbc96f4ed150a1a0dd070b9eb14276b9b6be413a769a75b519a53d3ecc0c220e85cd91ca354d57e7344517e64b43b6e29823cbd87eae26e2b2e78e6dedfbb76e3e9f77bcb844f9a8932eb3db2c3f9e44316e6f5d60e9e2a56e46b72abe6b06dc9a31cc63f10023d1f5e12d2a3ee93b675c96f504af0001220991c88db759e231b3320dcedf814dcf723fd9857e3d72d66a0f2af26950b915abdf56c1596f46a325bf17ad4810d3535fb02a259b247ac3dbd4cc3ecf9c51b6c07cebb009c1506fba0a89321ec8683e3fd009a6e551d50243e2d5092fefb3321083a4bad91320dc624bd6b5dddf93553e3d53924c05bfebec1fb4bd47e89a1a889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020000"
|
||||
|
||||
const dsaElGamalTestKeysHex = "9501e1044dfcb16a110400aa3e5c1a1f43dd28c2ffae8abf5cfce555ee874134d8ba0a0f7b868ce2214beddc74e5e1e21ded354a95d18acdaf69e5e342371a71fbb9093162e0c5f3427de413a7f2c157d83f5cd2f9d791256dc4f6f0e13f13c3302af27f2384075ab3021dff7a050e14854bbde0a1094174855fc02f0bae8e00a340d94a1f22b32e48485700a0cec672ac21258fb95f61de2ce1af74b2c4fa3e6703ff698edc9be22c02ae4d916e4fa223f819d46582c0516235848a77b577ea49018dcd5e9e15cff9dbb4663a1ae6dd7580fa40946d40c05f72814b0f88481207e6c0832c3bded4853ebba0a7e3bd8e8c66df33d5a537cd4acf946d1080e7a3dcea679cb2b11a72a33a2b6a9dc85f466ad2ddf4c3db6283fa645343286971e3dd700703fc0c4e290d45767f370831a90187e74e9972aae5bff488eeff7d620af0362bfb95c1a6c3413ab5d15a2e4139e5d07a54d72583914661ed6a87cce810be28a0aa8879a2dd39e52fb6fe800f4f181ac7e328f740cde3d09a05cecf9483e4cca4253e60d4429ffd679d9996a520012aad119878c941e3cf151459873bdfc2a9563472fe0303027a728f9feb3b864260a1babe83925ce794710cfd642ee4ae0e5b9d74cee49e9c67b6cd0ea5dfbb582132195a121356a1513e1bca73e5b80c58c7ccb4164453412f456c47616d616c2054657374204b65792031886204131102002205024dfcb16a021b03060b090807030206150802090a0b0416020301021e01021780000a091033af447ccd759b09fadd00a0b8fd6f5a790bad7e9f2dbb7632046dc4493588db009c087c6a9ba9f7f49fab221587a74788c00db4889ab00200009d0157044dfcb16a1004008dec3f9291205255ccff8c532318133a6840739dd68b03ba942676f9038612071447bf07d00d559c5c0875724ea16a4c774f80d8338b55fca691a0522e530e604215b467bbc9ccfd483a1da99d7bc2648b4318fdbd27766fc8bfad3fddb37c62b8ae7ccfe9577e9b8d1e77c1d417ed2c2ef02d52f4da11600d85d3229607943700030503ff506c94c87c8cab778e963b76cf63770f0a79bf48fb49d3b4e52234620fc9f7657f9f8d56c96a2b7c7826ae6b57ebb2221a3fe154b03b6637cea7e6d98e3e45d87cf8dc432f723d3d71f89c5192ac8d7290684d2c25ce55846a80c9a7823f6acd9bb29fa6cd71f20bc90eccfca20451d0c976e460e672b000df49466408d527affe0303027a728f9feb3b864260abd761730327bca2aaa4ea0525c175e92bf240682a0e83b226f97ecb2e935b62c9a133858ce31b271fa8eb41f6a1b3cd72a63025ce1a75ee4180dcc284884904181102000905024dfcb16a021b0c000a091033af447ccd759b09dd0b009e3c3e7296092c81bee5a19929462caaf2fff3ae26009e218c437a2340e7ea628149af1ec98ec091a43992b00200009501e1044dfcb1be1104009f61faa61aa43df75d128cbe53de528c4aec49ce9360c992e70c77072ad5623de0a3a6212771b66b39a30dad6781799e92608316900518ec01184a85d872365b7d2ba4bacfb5882ea3c2473d3750dc6178cc1cf82147fb58caa28b28e9f12f6d1efcb0534abed644156c91cca4ab78834268495160b2400bc422beb37d237c2300a0cac94911b6d493bda1e1fbc6feeca7cb7421d34b03fe22cec6ccb39675bb7b94a335c2b7be888fd3906a1125f33301d8aa6ec6ee6878f46f73961c8d57a3e9544d8ef2a2cbfd4d52da665b1266928cfe4cb347a58c412815f3b2d2369dec04b41ac9a71cc9547426d5ab941cccf3b18575637ccfb42df1a802df3cfe0a999f9e7109331170e3a221991bf868543960f8c816c28097e503fe319db10fb98049f3a57d7c80c420da66d56f3644371631fad3f0ff4040a19a4fedc2d07727a1b27576f75a4d28c47d8246f27071e12d7a8de62aad216ddbae6aa02efd6b8a3e2818cda48526549791ab277e447b3a36c57cefe9b592f5eab73959743fcc8e83cbefec03a329b55018b53eec196765ae40ef9e20521a603c551efe0303020950d53a146bf9c66034d00c23130cce95576a2ff78016ca471276e8227fb30b1ffbd92e61804fb0c3eff9e30b1a826ee8f3e4730b4d86273ca977b4164453412f456c47616d616c2054657374204b65792032886204131102002205024dfcb1be021b03060b090807030206150802090a0b0416020301021e01021780000a0910a86bf526325b21b22bd9009e34511620415c974750a20df5cb56b182f3b48e6600a0a9466cb1a1305a84953445f77d461593f1d42bc1b00200009d0157044dfcb1be1004009565a951da1ee87119d600c077198f1c1bceb0f7aa54552489298e41ff788fa8f0d43a69871f0f6f77ebdfb14a4260cf9fbeb65d5844b4272a1904dd95136d06c3da745dc46327dd44a0f16f60135914368c8039a34033862261806bb2c5ce1152e2840254697872c85441ccb7321431d75a747a4bfb1d2c66362b51ce76311700030503fc0ea76601c196768070b7365a200e6ddb09307f262d5f39eec467b5f5784e22abdf1aa49226f59ab37cb49969d8f5230ea65caf56015abda62604544ed526c5c522bf92bed178a078789f6c807b6d34885688024a5bed9e9f8c58d11d4b82487b44c5f470c5606806a0443b79cadb45e0f897a561a53f724e5349b9267c75ca17fe0303020950d53a146bf9c660bc5f4ce8f072465e2d2466434320c1e712272fafc20e342fe7608101580fa1a1a367e60486a7cd1246b7ef5586cf5e10b32762b710a30144f12dd17dd4884904181102000905024dfcb1be021b0c000a0910a86bf526325b21b2904c00a0b2b66b4b39ccffda1d10f3ea8d58f827e30a8b8e009f4255b2d8112a184e40cde43a34e8655ca7809370b0020000"
|
||||
|
||||
const signedMessageHex = "a3019bc0cbccc0c4b8d8b74ee2108fe16ec6d3ca490cbe362d3f8333d3f352531472538b8b13d353b97232f352158c20943157c71c16064626063656269052062e4e01987e9b6fccff4b7df3a34c534b23e679cbec3bc0f8f6e64dfb4b55fe3f8efa9ce110ddb5cd79faf1d753c51aecfa669f7e7aa043436596cccc3359cb7dd6bbe9ecaa69e5989d9e57209571edc0b2fa7f57b9b79a64ee6e99ce1371395fee92fec2796f7b15a77c386ff668ee27f6d38f0baa6c438b561657377bf6acff3c5947befd7bf4c196252f1d6e5c524d0300"
|
||||
|
||||
const signedTextMessageHex = "a3019bc0cbccc8c4b8d8b74ee2108fe16ec6d36a250cbece0c178233d3f352531472538b8b13d35379b97232f352158ca0b4312f57c71c1646462606365626906a062e4e019811591798ff99bf8afee860b0d8a8c2a85c3387e3bcf0bb3b17987f2bbcfab2aa526d930cbfd3d98757184df3995c9f3e7790e36e3e9779f06089d4c64e9e47dd6202cb6e9bc73c5d11bb59fbaf89d22d8dc7cf199ddf17af96e77c5f65f9bbed56f427bd8db7af37f6c9984bf9385efaf5f184f986fb3e6adb0ecfe35bbf92d16a7aa2a344fb0bc52fb7624f0200"
|
||||
|
||||
const signedEncryptedMessageHex = "c18c032a67d68660df41c70103ff5a84c9a72f80e74ef0384c2d6a9ebfe2b09e06a8f298394f6d2abf174e40934ab0ec01fb2d0ddf21211c6fe13eb238563663b017a6b44edca552eb4736c4b7dc6ed907dd9e12a21b51b64b46f902f76fb7aaf805c1db8070574d8d0431a23e324a750f77fb72340a17a42300ee4ca8207301e95a731da229a63ab9c6b44541fbd2c11d016d810b3b3b2b38f15b5b40f0a4910332829c2062f1f7cc61f5b03677d73c54cafa1004ced41f315d46444946faae571d6f426e6dbd45d9780eb466df042005298adabf7ce0ef766dfeb94cd449c7ed0046c880339599c4711af073ce649b1e237c40b50a5536283e03bdbb7afad78bd08707715c67fb43295f905b4c479178809d429a8e167a9a8c6dfd8ab20b4edebdc38d6dec879a3202e1b752690d9bb5b0c07c5a227c79cc200e713a99251a4219d62ad5556900cf69bd384b6c8e726c7be267471d0d23af956da165af4af757246c2ebcc302b39e8ef2fccb4971b234fcda22d759ddb20e27269ee7f7fe67898a9de721bfa02ab0becaa046d00ea16cb1afc4e2eab40d0ac17121c565686e5cbd0cbdfbd9d6db5c70278b9c9db5a83176d04f61fbfbc4471d721340ede2746e5c312ded4f26787985af92b64fae3f253dbdde97f6a5e1996fd4d865599e32ff76325d3e9abe93184c02988ee89a4504356a4ef3b9b7a57cbb9637ca90af34a7676b9ef559325c3cca4e29d69fec1887f5440bb101361d744ad292a8547f22b4f22b419a42aa836169b89190f46d9560824cb2ac6e8771de8223216a5e647e132ab9eebcba89569ab339cb1c3d70fe806b31f4f4c600b4103b8d7583ebff16e43dcda551e6530f975122eb8b29"
|
||||
|
||||
const verifiedSignatureEncryptedMessageHex = "c2b304000108000605026048f6d600210910a34d7e18c20c31bb1621045fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb9a3b0400a32ddac1af259c1b0abab0041327ea04970944401978fb647dd1cf9aba4f164e43f0d8a9389501886474bdd4a6e77f6aea945c07dfbf87743835b44cc2c39a1f9aeecfa83135abc92e18e50396f2e6a06c44e0188b0081effbfb4160d28f118d4ff73dd199a102e47cffd8c7ff2bacd83ae72b5820c021a486766dd587b5da61"
|
||||
|
||||
const unverifiedSignatureEncryptedMessageHex = "c2b304000108000605026048f6d600210910a34d7e18c20c31bb1621045fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb9a3b0400a32ddac1af259c1b0abab0041327ea04970944401978fb647dd1cf9aba4f164e43f0d8a9389501886474bdd4a6e77f6aea945c07dfbf87743835b44cc2c39a1f9aeecfa83135abc92e18e50396f2e6a06c44e0188b0081effbfb4160d28f118d4ff73dd199a102e47cffd8c7ff2bacd83ae72b5820c021a486766dd587b5da61"
|
||||
|
||||
const signedEncryptedMessage2Hex = "85010e03cf6a7abcd43e36731003fb057f5495b79db367e277cdbe4ab90d924ddee0c0381494112ff8c1238fb0184af35d1731573b01bc4c55ecacd2aafbe2003d36310487d1ecc9ac994f3fada7f9f7f5c3a64248ab7782906c82c6ff1303b69a84d9a9529c31ecafbcdb9ba87e05439897d87e8a2a3dec55e14df19bba7f7bd316291c002ae2efd24f83f9e3441203fc081c0c23dc3092a454ca8a082b27f631abf73aca341686982e8fbda7e0e7d863941d68f3de4a755c2964407f4b5e0477b3196b8c93d551dd23c8beef7d0f03fbb1b6066f78907faf4bf1677d8fcec72651124080e0b7feae6b476e72ab207d38d90b958759fdedfc3c6c35717c9dbfc979b3cfbbff0a76d24a5e57056bb88acbd2a901ef64bc6e4db02adc05b6250ff378de81dca18c1910ab257dff1b9771b85bb9bbe0a69f5989e6d1710a35e6dfcceb7d8fb5ccea8db3932b3d9ff3fe0d327597c68b3622aec8e3716c83a6c93f497543b459b58ba504ed6bcaa747d37d2ca746fe49ae0a6ce4a8b694234e941b5159ff8bd34b9023da2814076163b86f40eed7c9472f81b551452d5ab87004a373c0172ec87ea6ce42ccfa7dbdad66b745496c4873d8019e8c28d6b3"
|
||||
|
||||
const signatureEncryptedMessage2Hex = "c24604001102000605024dfd0166000a091033af447ccd759b09bae600a096ec5e63ecf0a403085e10f75cc3bab327663282009f51fad9df457ed8d2b70d8a73c76e0443eac0f377"
|
||||
|
||||
const symmetricallyEncryptedCompressedHex = "c32e040903085a357c1a7b5614ed00cc0d1d92f428162058b3f558a0fb0980d221ebac6c97d5eda4e0fe32f6e706e94dd263012d6ca1ef8c4bbd324098225e603a10c85ebf09cbf7b5aeeb5ce46381a52edc51038b76a8454483be74e6dcd1e50d5689a8ae7eceaeefed98a0023d49b22eb1f65c2aa1ef1783bb5e1995713b0457102ec3c3075fe871267ffa4b686ad5d52000d857"
|
||||
|
||||
const dsaTestKeyHex = "9901a2044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794"
|
||||
|
||||
const dsaTestKeyPrivateHex = "9501bb044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4d00009f592e0619d823953577d4503061706843317e4fee083db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794"
|
||||
|
||||
const p256TestKeyHex = "98520456e5b83813082a8648ce3d030107020304a2072cd6d21321266c758cc5b83fab0510f751cb8d91897cddb7047d8d6f185546e2107111b0a95cb8ef063c33245502af7a65f004d5919d93ee74eb71a66253b424502d3235362054657374204b6579203c696e76616c6964406578616d706c652e636f6d3e8879041313080021050256e5b838021b03050b09080702061508090a0b020416020301021e01021780000a0910d44a2c495918513e54e50100dfa64f97d9b47766fc1943c6314ba3f2b2a103d71ad286dc5b1efb96a345b0c80100dbc8150b54241f559da6ef4baacea6d31902b4f4b1bdc09b34bf0502334b7754b8560456e5b83812082a8648ce3d030107020304bfe3cea9cee13486f8d518aa487fecab451f25467d2bf08e58f63e5fa525d5482133e6a79299c274b068ef0be448152ad65cf11cf764348588ca4f6a0bcf22b6030108078861041813080009050256e5b838021b0c000a0910d44a2c495918513e4a4800ff49d589fa64024ad30be363a032e3a0e0e6f5db56ba4c73db850518bf0121b8f20100fd78e065f4c70ea5be9df319ea67e493b936fc78da834a71828043d3154af56e"
|
||||
|
||||
const p256TestKeyPrivateHex = "94a50456e5b83813082a8648ce3d030107020304a2072cd6d21321266c758cc5b83fab0510f751cb8d91897cddb7047d8d6f185546e2107111b0a95cb8ef063c33245502af7a65f004d5919d93ee74eb71a66253fe070302f0c2bfb0b6c30f87ee1599472b8636477eab23ced13b271886a4b50ed34c9d8436af5af5b8f88921f0efba6ef8c37c459bbb88bc1c6a13bbd25c4ce9b1e97679569ee77645d469bf4b43de637f5561b424502d3235362054657374204b6579203c696e76616c6964406578616d706c652e636f6d3e8879041313080021050256e5b838021b03050b09080702061508090a0b020416020301021e01021780000a0910d44a2c495918513e54e50100dfa64f97d9b47766fc1943c6314ba3f2b2a103d71ad286dc5b1efb96a345b0c80100dbc8150b54241f559da6ef4baacea6d31902b4f4b1bdc09b34bf0502334b77549ca90456e5b83812082a8648ce3d030107020304bfe3cea9cee13486f8d518aa487fecab451f25467d2bf08e58f63e5fa525d5482133e6a79299c274b068ef0be448152ad65cf11cf764348588ca4f6a0bcf22b603010807fe0703027510012471a603cfee2968dce19f732721ddf03e966fd133b4e3c7a685b788705cbc46fb026dc94724b830c9edbaecd2fb2c662f23169516cacd1fe423f0475c364ecc10abcabcfd4bbbda1a36a1bd8861041813080009050256e5b838021b0c000a0910d44a2c495918513e4a4800ff49d589fa64024ad30be363a032e3a0e0e6f5db56ba4c73db850518bf0121b8f20100fd78e065f4c70ea5be9df319ea67e493b936fc78da834a71828043d3154af56e"
|
||||
|
||||
const armoredPrivateKeyBlock = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
Version: GnuPG v1.4.10 (GNU/Linux)
|
||||
|
||||
lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp
|
||||
idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn
|
||||
vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB
|
||||
AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X
|
||||
0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL
|
||||
IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk
|
||||
VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn
|
||||
gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9
|
||||
TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx
|
||||
q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz
|
||||
dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA
|
||||
CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1
|
||||
ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+
|
||||
eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid
|
||||
AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV
|
||||
bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK
|
||||
/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA
|
||||
A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX
|
||||
TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc
|
||||
lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6
|
||||
rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN
|
||||
oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8
|
||||
QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU
|
||||
nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC
|
||||
AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp
|
||||
BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad
|
||||
AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL
|
||||
VrM0m72/jnpKo04=
|
||||
=zNCn
|
||||
-----END PGP PRIVATE KEY BLOCK-----`
|
||||
|
||||
const e2ePublicKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Charset: UTF-8
|
||||
|
||||
xv8AAABSBAAAAAATCCqGSM49AwEHAgME1LRoXSpOxtHXDUdmuvzchyg6005qIBJ4
|
||||
sfaSxX7QgH9RV2ONUhC+WiayCNADq+UMzuR/vunSr4aQffXvuGnR383/AAAAFDxk
|
||||
Z2lsQHlhaG9vLWluYy5jb20+wv8AAACGBBATCAA4/wAAAAWCVGvAG/8AAAACiwn/
|
||||
AAAACZC2VkQCOjdvYf8AAAAFlQgJCgv/AAAAA5YBAv8AAAACngEAAE1BAP0X8veD
|
||||
24IjmI5/C6ZAfVNXxgZZFhTAACFX75jUA3oD6AEAzoSwKf1aqH6oq62qhCN/pekX
|
||||
+WAsVMBhNwzLpqtCRjLO/wAAAFYEAAAAABIIKoZIzj0DAQcCAwT50ain7vXiIRv8
|
||||
B1DO3x3cE/aattZ5sHNixJzRCXi2vQIA5QmOxZ6b5jjUekNbdHG3SZi1a2Ak5mfX
|
||||
fRxC/5VGAwEIB8L/AAAAZQQYEwgAGP8AAAAFglRrwBz/AAAACZC2VkQCOjdvYQAA
|
||||
FJAA9isX3xtGyMLYwp2F3nXm7QEdY5bq5VUcD/RJlj792VwA/1wH0pCzVLl4Q9F9
|
||||
ex7En5r7rHR5xwX82Msc+Rq9dSyO
|
||||
=7MrZ
|
||||
-----END PGP PUBLIC KEY BLOCK-----`
|
||||
|
||||
const dsaKeyWithSHA512 = `9901a2044f04b07f110400db244efecc7316553ee08d179972aab87bb1214de7692593fcf5b6feb1c80fba268722dd464748539b85b81d574cd2d7ad0ca2444de4d849b8756bad7768c486c83a824f9bba4af773d11742bdfb4ac3b89ef8cc9452d4aad31a37e4b630d33927bff68e879284a1672659b8b298222fc68f370f3e24dccacc4a862442b9438b00a0ea444a24088dc23e26df7daf8f43cba3bffc4fe703fe3d6cd7fdca199d54ed8ae501c30e3ec7871ea9cdd4cf63cfe6fc82281d70a5b8bb493f922cd99fba5f088935596af087c8d818d5ec4d0b9afa7f070b3d7c1dd32a84fca08d8280b4890c8da1dde334de8e3cad8450eed2a4a4fcc2db7b8e5528b869a74a7f0189e11ef097ef1253582348de072bb07a9fa8ab838e993cef0ee203ff49298723e2d1f549b00559f886cd417a41692ce58d0ac1307dc71d85a8af21b0cf6eaa14baf2922d3a70389bedf17cc514ba0febbd107675a372fe84b90162a9e88b14d4b1c6be855b96b33fb198c46f058568817780435b6936167ebb3724b680f32bf27382ada2e37a879b3d9de2abe0c3f399350afd1ad438883f4791e2e3b4184453412068617368207472756e636174696f6e207465737488620413110a002205024f04b07f021b03060b090807030206150802090a0b0416020301021e01021780000a0910ef20e0cefca131581318009e2bf3bf047a44d75a9bacd00161ee04d435522397009a03a60d51bd8a568c6c021c8d7cf1be8d990d6417b0020003`
|
||||
|
||||
const unknownHashFunctionHex = `8a00000040040001990006050253863c24000a09103b4fe6acc0b21f32ffff01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101`
|
||||
|
||||
const rsaSignatureBadMPIlength = `8a00000040040001030006050253863c24000a09103b4fe6acc0b21f32ffff0101010101010101010101010101010101010101010101010101010101010101010101010101`
|
||||
|
||||
const missingHashFunctionHex = `8a00000040040001030006050253863c24000a09103b4fe6acc0b21f32ffff0101010101010101010101010101010101010101010101010101010101010101010101`
|
||||
|
||||
const campbellQuine = `a0b001000300fcffa0b001000d00f2ff000300fcffa0b001000d00f2ff8270a01c00000500faff8270a01c00000500faff000500faff001400ebff8270a01c00000500faff000500faff001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400000000ffff000000ffff000b00f4ff428821c400000000ffff000000ffff000b00f4ff0233214c40000100feff000233214c40000100feff0000`
|
||||
|
||||
const keyV4forVerifyingSignedMessageV3 = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Comment: GPGTools - https://gpgtools.org
|
||||
|
||||
mI0EVfxoFQEEAMBIqmbDfYygcvP6Phr1wr1XI41IF7Qixqybs/foBF8qqblD9gIY
|
||||
BKpXjnBOtbkcVOJ0nljd3/sQIfH4E0vQwK5/4YRQSI59eKOqd6Fx+fWQOLG+uu6z
|
||||
tewpeCj9LLHvibx/Sc7VWRnrznia6ftrXxJ/wHMezSab3tnGC0YPVdGNABEBAAG0
|
||||
JEdvY3J5cHRvIFRlc3QgS2V5IDx0aGVtYXhAZ21haWwuY29tPoi5BBMBCgAjBQJV
|
||||
/GgVAhsDBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQeXnQmhdGW9PFVAP+
|
||||
K7TU0qX5ArvIONIxh/WAweyOk884c5cE8f+3NOPOOCRGyVy0FId5A7MmD5GOQh4H
|
||||
JseOZVEVCqlmngEvtHZb3U1VYtVGE5WZ+6rQhGsMcWP5qaT4soYwMBlSYxgYwQcx
|
||||
YhN9qOr292f9j2Y//TTIJmZT4Oa+lMxhWdqTfX+qMgG4jQRV/GgVAQQArhFSiij1
|
||||
b+hT3dnapbEU+23Z1yTu1DfF6zsxQ4XQWEV3eR8v+8mEDDNcz8oyyF56k6UQ3rXi
|
||||
UMTIwRDg4V6SbZmaFbZYCOwp/EmXJ3rfhm7z7yzXj2OFN22luuqbyVhuL7LRdB0M
|
||||
pxgmjXb4tTvfgKd26x34S+QqUJ7W6uprY4sAEQEAAYifBBgBCgAJBQJV/GgVAhsM
|
||||
AAoJEHl50JoXRlvT7y8D/02ckx4OMkKBZo7viyrBw0MLG92i+DC2bs35PooHR6zz
|
||||
786mitjOp5z2QWNLBvxC70S0qVfCIz8jKupO1J6rq6Z8CcbLF3qjm6h1omUBf8Nd
|
||||
EfXKD2/2HV6zMKVknnKzIEzauh+eCKS2CeJUSSSryap/QLVAjRnckaES/OsEWhNB
|
||||
=RZia
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
`
|
||||
|
||||
const signedMessageV3 = `-----BEGIN PGP MESSAGE-----
|
||||
Comment: GPGTools - https://gpgtools.org
|
||||
|
||||
owGbwMvMwMVYWXlhlrhb9GXG03JJDKF/MtxDMjKLFYAoUaEktbhEITe1uDgxPVWP
|
||||
q5NhKjMrWAVcC9evD8z/bF/uWNjqtk/X3y5/38XGRQHm/57rrDRYuGnTw597Xqka
|
||||
uM3137/hH3Os+Jf2dc0fXOITKwJvXJvecPVs0ta+Vg7ZO1MLn8w58Xx+6L58mbka
|
||||
DGHyU9yTueZE8D+QF/Tz28Y78dqtF56R1VPn9Xw4uJqrWYdd7b3vIZ1V6R4Nh05d
|
||||
iT57d/OhWwA=
|
||||
=hG7R
|
||||
-----END PGP MESSAGE-----
|
||||
`
|
||||
|
||||
// https://mailarchive.ietf.org/arch/msg/openpgp/9SheW_LENE0Kxf7haNllovPyAdY/
|
||||
const v5PrivKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
|
||||
lGEFXJH05BYAAAAtCSsGAQQB2kcPAQEHQFhZlVcVVtwf+21xNQPX+ecMJJBL0MPd
|
||||
fj75iux+my8QAAAAAAAiAQCHZ1SnSUmWqxEsoI6facIVZQu6mph3cBFzzTvcm5lA
|
||||
Ng5ctBhlbW1hLmdvbGRtYW5AZXhhbXBsZS5uZXSIlgUTFggASCIhBRk0e8mHJGQC
|
||||
X5nfPsLgAA7ZiEiS4fez6kyUAJFZVptUBQJckfTkAhsDBQsJCAcCAyICAQYVCgkI
|
||||
CwIEFgIDAQIeBwIXgAAA9cAA/jiR3yMsZMeEQ40u6uzEoXa6UXeV/S3wwJAXRJy9
|
||||
M8s0AP9vuL/7AyTfFXwwzSjDnYmzS0qAhbLDQ643N+MXGBJ2BZxmBVyR9OQSAAAA
|
||||
MgorBgEEAZdVAQUBAQdA+nysrzml2UCweAqtpDuncSPlvrcBWKU0yfU0YvYWWAoD
|
||||
AQgHAAAAAAAiAP9OdAPppjU1WwpqjIItkxr+VPQRT8Zm/Riw7U3F6v3OiBFHiHoF
|
||||
GBYIACwiIQUZNHvJhyRkAl+Z3z7C4AAO2YhIkuH3s+pMlACRWVabVAUCXJH05AIb
|
||||
DAAAOSQBAP4BOOIR/sGLNMOfeb5fPs/02QMieoiSjIBnijhob2U5AQC+RtOHCHx7
|
||||
TcIYl5/Uyoi+FOvPLcNw4hOv2nwUzSSVAw==
|
||||
=IiS2
|
||||
-----END PGP PRIVATE KEY BLOCK-----`
|
||||
|
||||
// Generated with the above private key
|
||||
const v5PrivKeyMsg = `-----BEGIN PGP MESSAGE-----
|
||||
Version: OpenPGP.js v4.10.7
|
||||
Comment: https://openpgpjs.org
|
||||
|
||||
xA0DAQoWGTR7yYckZAIByxF1B21zZy50eHRfbIGSdGVzdMJ3BQEWCgAGBQJf
|
||||
bIGSACMiIQUZNHvJhyRkAl+Z3z7C4AAO2YhIkuH3s+pMlACRWVabVDQvAP9G
|
||||
y29VPonFXqi2zKkpZrvyvZxg+n5e8Nt9wNbuxeCd3QD/TtO2s+JvjrE4Siwv
|
||||
UQdl5MlBka1QSNbMq2Bz7XwNPg4=
|
||||
=6lbM
|
||||
-----END PGP MESSAGE-----`
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
// Package s2k implements the various OpenPGP string-to-key transforms as
|
||||
// specified in RFC 4800 section 3.7.1.
|
||||
package s2k // import "golang.org/x/crypto/openpgp/s2k"
|
||||
package s2k // import "github.com/ProtonMail/go-crypto/openpgp/s2k"
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
|
@ -12,49 +12,67 @@ import (
|
|||
"io"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
|
||||
)
|
||||
|
||||
// Config collects configuration parameters for s2k key-stretching
|
||||
// transformatioms. A nil *Config is valid and results in all default
|
||||
// transformations. A nil *Config is valid and results in all default
|
||||
// values. Currently, Config is used only by the Serialize function in
|
||||
// this package.
|
||||
type Config struct {
|
||||
// S2KMode is the mode of s2k function.
|
||||
// It can be 0 (simple), 1(salted), 3(iterated)
|
||||
// 2(reserved) 100-110(private/experimental).
|
||||
S2KMode uint8
|
||||
// Hash is the default hash function to be used. If
|
||||
// nil, SHA1 is used.
|
||||
// nil, SHA256 is used.
|
||||
Hash crypto.Hash
|
||||
// S2KCount is only used for symmetric encryption. It
|
||||
// determines the strength of the passphrase stretching when
|
||||
// the said passphrase is hashed to produce a key. S2KCount
|
||||
// should be between 1024 and 65011712, inclusive. If Config
|
||||
// is nil or S2KCount is 0, the value 65536 used. Not all
|
||||
// should be between 65536 and 65011712, inclusive. If Config
|
||||
// is nil or S2KCount is 0, the value 16777216 used. Not all
|
||||
// values in the above range can be represented. S2KCount will
|
||||
// be rounded up to the next representable value if it cannot
|
||||
// be encoded exactly. When set, it is strongly encrouraged to
|
||||
// use a value that is at least 65536. See RFC 4880 Section
|
||||
// 3.7.1.3.
|
||||
// be encoded exactly. See RFC 4880 Section 3.7.1.3.
|
||||
S2KCount int
|
||||
}
|
||||
|
||||
// Params contains all the parameters of the s2k packet
|
||||
type Params struct {
|
||||
// mode is the mode of s2k function.
|
||||
// It can be 0 (simple), 1(salted), 3(iterated)
|
||||
// 2(reserved) 100-110(private/experimental).
|
||||
mode uint8
|
||||
// hashId is the ID of the hash function used in any of the modes
|
||||
hashId byte
|
||||
// salt is a byte array to use as a salt in hashing process
|
||||
salt []byte
|
||||
// countByte is used to determine how many rounds of hashing are to
|
||||
// be performed in s2k mode 3. See RFC 4880 Section 3.7.1.3.
|
||||
countByte byte
|
||||
}
|
||||
|
||||
func (c *Config) hash() crypto.Hash {
|
||||
if c == nil || uint(c.Hash) == 0 {
|
||||
// SHA1 is the historical default in this package.
|
||||
return crypto.SHA1
|
||||
return crypto.SHA256
|
||||
}
|
||||
|
||||
return c.Hash
|
||||
}
|
||||
|
||||
func (c *Config) encodedCount() uint8 {
|
||||
// EncodedCount get encoded count
|
||||
func (c *Config) EncodedCount() uint8 {
|
||||
if c == nil || c.S2KCount == 0 {
|
||||
return 96 // The common case. Correspoding to 65536
|
||||
return 224 // The common case. Corresponding to 16777216
|
||||
}
|
||||
|
||||
i := c.S2KCount
|
||||
|
||||
switch {
|
||||
// Behave like GPG. Should we make 65536 the lowest value used?
|
||||
case i < 1024:
|
||||
i = 1024
|
||||
case i < 65536:
|
||||
i = 65536
|
||||
case i > 65011712:
|
||||
i = 65011712
|
||||
}
|
||||
|
@ -68,11 +86,11 @@ func (c *Config) encodedCount() uint8 {
|
|||
// if i is not in the above range (encodedCount above takes care to
|
||||
// pass i in the correct range). See RFC 4880 Section 3.7.7.1.
|
||||
func encodeCount(i int) uint8 {
|
||||
if i < 1024 || i > 65011712 {
|
||||
if i < 65536 || i > 65011712 {
|
||||
panic("count arg i outside the required range")
|
||||
}
|
||||
|
||||
for encoded := 0; encoded < 256; encoded++ {
|
||||
for encoded := 96; encoded < 256; encoded++ {
|
||||
count := decodeCount(uint8(encoded))
|
||||
if count >= i {
|
||||
return uint8(encoded)
|
||||
|
@ -151,9 +169,44 @@ func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) {
|
|||
}
|
||||
}
|
||||
|
||||
// Generate generates valid parameters from given configuration.
|
||||
// It will enforce salted + hashed s2k method
|
||||
func Generate(rand io.Reader, c *Config) (*Params, error) {
|
||||
hashId, ok := HashToHashId(c.Hash)
|
||||
if !ok {
|
||||
return nil, errors.UnsupportedError("no such hash")
|
||||
}
|
||||
|
||||
params := &Params{
|
||||
mode: 3, // Enforce iterared + salted method
|
||||
hashId: hashId,
|
||||
salt: make([]byte, 8),
|
||||
countByte: c.EncodedCount(),
|
||||
}
|
||||
|
||||
if _, err := io.ReadFull(rand, params.salt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// Parse reads a binary specification for a string-to-key transformation from r
|
||||
// and returns a function which performs that transform.
|
||||
// and returns a function which performs that transform. If the S2K is a special
|
||||
// GNU extension that indicates that the private key is missing, then the error
|
||||
// returned is errors.ErrDummyPrivateKey.
|
||||
func Parse(r io.Reader) (f func(out, in []byte), err error) {
|
||||
params, err := ParseIntoParams(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return params.Function()
|
||||
}
|
||||
|
||||
// ParseIntoParams reads a binary specification for a string-to-key
|
||||
// transformation from r and returns a struct describing the s2k parameters.
|
||||
func ParseIntoParams(r io.Reader) (params *Params, err error) {
|
||||
var buf [9]byte
|
||||
|
||||
_, err = io.ReadFull(r, buf[:2])
|
||||
|
@ -161,91 +214,135 @@ func Parse(r io.Reader) (f func(out, in []byte), err error) {
|
|||
return
|
||||
}
|
||||
|
||||
hash, ok := HashIdToHash(buf[1])
|
||||
if !ok {
|
||||
return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1])))
|
||||
params = &Params{
|
||||
mode: buf[0],
|
||||
hashId: buf[1],
|
||||
}
|
||||
if !hash.Available() {
|
||||
return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hash)))
|
||||
}
|
||||
h := hash.New()
|
||||
|
||||
switch buf[0] {
|
||||
switch params.mode {
|
||||
case 0:
|
||||
f := func(out, in []byte) {
|
||||
Simple(out, h, in)
|
||||
}
|
||||
return f, nil
|
||||
return params, nil
|
||||
case 1:
|
||||
_, err = io.ReadFull(r, buf[:8])
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
f := func(out, in []byte) {
|
||||
Salted(out, h, in, buf[:8])
|
||||
}
|
||||
return f, nil
|
||||
|
||||
params.salt = buf[:8]
|
||||
return params, nil
|
||||
case 3:
|
||||
_, err = io.ReadFull(r, buf[:9])
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
count := decodeCount(buf[8])
|
||||
|
||||
params.salt = buf[:8]
|
||||
params.countByte = buf[8]
|
||||
return params, nil
|
||||
case 101:
|
||||
// This is a GNU extension. See
|
||||
// https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/DETAILS;h=fe55ae16ab4e26d8356dc574c9e8bc935e71aef1;hb=23191d7851eae2217ecdac6484349849a24fd94a#l1109
|
||||
if _, err = io.ReadFull(r, buf[:4]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if buf[0] == 'G' && buf[1] == 'N' && buf[2] == 'U' && buf[3] == 1 {
|
||||
return params, nil
|
||||
}
|
||||
return nil, errors.UnsupportedError("GNU S2K extension")
|
||||
}
|
||||
|
||||
return nil, errors.UnsupportedError("S2K function")
|
||||
}
|
||||
|
||||
func (params *Params) Dummy() bool {
|
||||
return params != nil && params.mode == 101
|
||||
}
|
||||
|
||||
func (params *Params) Function() (f func(out, in []byte), err error) {
|
||||
if params.Dummy() {
|
||||
return nil, errors.ErrDummyPrivateKey("dummy key found")
|
||||
}
|
||||
hashObj, ok := HashIdToHash(params.hashId)
|
||||
if !ok {
|
||||
return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(params.hashId)))
|
||||
}
|
||||
if !hashObj.Available() {
|
||||
return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashObj)))
|
||||
}
|
||||
|
||||
switch params.mode {
|
||||
case 0:
|
||||
f := func(out, in []byte) {
|
||||
Iterated(out, h, in, buf[:8], count)
|
||||
Simple(out, hashObj.New(), in)
|
||||
}
|
||||
|
||||
return f, nil
|
||||
case 1:
|
||||
f := func(out, in []byte) {
|
||||
Salted(out, hashObj.New(), in, params.salt)
|
||||
}
|
||||
|
||||
return f, nil
|
||||
case 3:
|
||||
f := func(out, in []byte) {
|
||||
Iterated(out, hashObj.New(), in, params.salt, decodeCount(params.countByte))
|
||||
}
|
||||
|
||||
return f, nil
|
||||
}
|
||||
|
||||
return nil, errors.UnsupportedError("S2K function")
|
||||
}
|
||||
|
||||
func (params *Params) Serialize(w io.Writer) (err error) {
|
||||
if _, err = w.Write([]byte{params.mode}); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = w.Write([]byte{params.hashId}); err != nil {
|
||||
return
|
||||
}
|
||||
if params.Dummy() {
|
||||
_, err = w.Write(append([]byte("GNU"), 1))
|
||||
return
|
||||
}
|
||||
if params.mode > 0 {
|
||||
if _, err = w.Write(params.salt); err != nil {
|
||||
return
|
||||
}
|
||||
if params.mode == 3 {
|
||||
_, err = w.Write([]byte{params.countByte})
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Serialize salts and stretches the given passphrase and writes the
|
||||
// resulting key into key. It also serializes an S2K descriptor to
|
||||
// w. The key stretching can be configured with c, which may be
|
||||
// nil. In that case, sensible defaults will be used.
|
||||
func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte, c *Config) error {
|
||||
var buf [11]byte
|
||||
buf[0] = 3 /* iterated and salted */
|
||||
buf[1], _ = HashToHashId(c.hash())
|
||||
salt := buf[2:10]
|
||||
if _, err := io.ReadFull(rand, salt); err != nil {
|
||||
params, err := Generate(rand, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
encodedCount := c.encodedCount()
|
||||
count := decodeCount(encodedCount)
|
||||
buf[10] = encodedCount
|
||||
if _, err := w.Write(buf[:]); err != nil {
|
||||
err = params.Serialize(w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Iterated(key, c.hash().New(), passphrase, salt, count)
|
||||
f, err := params.Function()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f(key, passphrase)
|
||||
return nil
|
||||
}
|
||||
|
||||
// hashToHashIdMapping contains pairs relating OpenPGP's hash identifier with
|
||||
// Go's crypto.Hash type. See RFC 4880, section 9.4.
|
||||
var hashToHashIdMapping = []struct {
|
||||
id byte
|
||||
hash crypto.Hash
|
||||
name string
|
||||
}{
|
||||
{1, crypto.MD5, "MD5"},
|
||||
{2, crypto.SHA1, "SHA1"},
|
||||
{3, crypto.RIPEMD160, "RIPEMD160"},
|
||||
{8, crypto.SHA256, "SHA256"},
|
||||
{9, crypto.SHA384, "SHA384"},
|
||||
{10, crypto.SHA512, "SHA512"},
|
||||
{11, crypto.SHA224, "SHA224"},
|
||||
}
|
||||
|
||||
// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP
|
||||
// hash id.
|
||||
func HashIdToHash(id byte) (h crypto.Hash, ok bool) {
|
||||
for _, m := range hashToHashIdMapping {
|
||||
if m.id == id {
|
||||
return m.hash, true
|
||||
}
|
||||
if hash, ok := algorithm.HashById[id]; ok {
|
||||
return hash.HashFunc(), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
@ -253,20 +350,17 @@ func HashIdToHash(id byte) (h crypto.Hash, ok bool) {
|
|||
// HashIdToString returns the name of the hash function corresponding to the
|
||||
// given OpenPGP hash id.
|
||||
func HashIdToString(id byte) (name string, ok bool) {
|
||||
for _, m := range hashToHashIdMapping {
|
||||
if m.id == id {
|
||||
return m.name, true
|
||||
}
|
||||
if hash, ok := algorithm.HashById[id]; ok {
|
||||
return hash.String(), true
|
||||
}
|
||||
|
||||
return "", false
|
||||
}
|
||||
|
||||
// HashIdToHash returns an OpenPGP hash id which corresponds the given Hash.
|
||||
func HashToHashId(h crypto.Hash) (id byte, ok bool) {
|
||||
for _, m := range hashToHashIdMapping {
|
||||
if m.hash == h {
|
||||
return m.id, true
|
||||
for id, hash := range algorithm.HashById {
|
||||
if hash.HashFunc() == h {
|
||||
return id, true
|
||||
}
|
||||
}
|
||||
return 0, false
|
|
@ -11,10 +11,10 @@ import (
|
|||
"strconv"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/openpgp/armor"
|
||||
"golang.org/x/crypto/openpgp/errors"
|
||||
"golang.org/x/crypto/openpgp/packet"
|
||||
"golang.org/x/crypto/openpgp/s2k"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/armor"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/packet"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/s2k"
|
||||
)
|
||||
|
||||
// DetachSign signs message with the private key from signer (which must
|
||||
|
@ -60,27 +60,35 @@ func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType p
|
|||
}
|
||||
|
||||
func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) {
|
||||
if signer.PrivateKey == nil {
|
||||
signingKey, ok := signer.SigningKeyById(config.Now(), config.SigningKey())
|
||||
if !ok {
|
||||
return errors.InvalidArgumentError("no valid signing keys")
|
||||
}
|
||||
if signingKey.PrivateKey == nil {
|
||||
return errors.InvalidArgumentError("signing key doesn't have a private key")
|
||||
}
|
||||
if signer.PrivateKey.Encrypted {
|
||||
if signingKey.PrivateKey.Encrypted {
|
||||
return errors.InvalidArgumentError("signing key is encrypted")
|
||||
}
|
||||
|
||||
sig := new(packet.Signature)
|
||||
sig.SigType = sigType
|
||||
sig.PubKeyAlgo = signer.PrivateKey.PubKeyAlgo
|
||||
sig.PubKeyAlgo = signingKey.PrivateKey.PubKeyAlgo
|
||||
sig.Hash = config.Hash()
|
||||
sig.CreationTime = config.Now()
|
||||
sig.IssuerKeyId = &signer.PrivateKey.KeyId
|
||||
sigLifetimeSecs := config.SigLifetime()
|
||||
sig.SigLifetimeSecs = &sigLifetimeSecs
|
||||
sig.IssuerKeyId = &signingKey.PrivateKey.KeyId
|
||||
|
||||
h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
io.Copy(wrappedHash, message)
|
||||
if _, err = io.Copy(wrappedHash, message); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = sig.Sign(h, signer.PrivateKey, config)
|
||||
err = sig.Sign(h, signingKey.PrivateKey, config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -115,18 +123,27 @@ func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHi
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
w, err := packet.SerializeSymmetricallyEncrypted(ciphertext, config.Cipher(), key, config)
|
||||
if err != nil {
|
||||
return
|
||||
|
||||
var w io.WriteCloser
|
||||
if config.AEAD() != nil {
|
||||
w, err = packet.SerializeAEADEncrypted(ciphertext, key, config.Cipher(), config.AEAD().Mode(), config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
w, err = packet.SerializeSymmetricallyEncrypted(ciphertext, config.Cipher(), key, config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
literaldata := w
|
||||
literalData := w
|
||||
if algo := config.Compression(); algo != packet.CompressionNone {
|
||||
var compConfig *packet.CompressionConfig
|
||||
if config != nil {
|
||||
compConfig = config.CompressionConfig
|
||||
}
|
||||
literaldata, err = packet.SerializeCompressed(w, algo, compConfig)
|
||||
literalData, err = packet.SerializeCompressed(w, algo, compConfig)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -136,7 +153,7 @@ func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHi
|
|||
if !hints.ModTime.IsZero() {
|
||||
epochSeconds = uint32(hints.ModTime.Unix())
|
||||
}
|
||||
return packet.SerializeLiteral(literaldata, hints.IsBinary, hints.FileName, epochSeconds)
|
||||
return packet.SerializeLiteral(literalData, hints.IsBinary, hints.FileName, epochSeconds)
|
||||
}
|
||||
|
||||
// intersectPreferences mutates and returns a prefix of a that contains only
|
||||
|
@ -164,15 +181,51 @@ func hashToHashId(h crypto.Hash) uint8 {
|
|||
return v
|
||||
}
|
||||
|
||||
// EncryptText encrypts a message to a number of recipients and, optionally,
|
||||
// signs it. Optional information is contained in 'hints', also encrypted, that
|
||||
// aids the recipients in processing the message. The resulting WriteCloser
|
||||
// must be closed after the contents of the file have been written. If config
|
||||
// is nil, sensible defaults will be used. The signing is done in text mode.
|
||||
func EncryptText(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) {
|
||||
return encrypt(ciphertext, ciphertext, to, signed, hints, packet.SigTypeText, config)
|
||||
}
|
||||
|
||||
// Encrypt encrypts a message to a number of recipients and, optionally, signs
|
||||
// it. hints contains optional information, that is also encrypted, that aids
|
||||
// the recipients in processing the message. The resulting WriteCloser must
|
||||
// be closed after the contents of the file have been written.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) {
|
||||
return encrypt(ciphertext, ciphertext, to, signed, hints, packet.SigTypeBinary, config)
|
||||
}
|
||||
|
||||
// EncryptSplit encrypts a message to a number of recipients and, optionally, signs
|
||||
// it. hints contains optional information, that is also encrypted, that aids
|
||||
// the recipients in processing the message. The resulting WriteCloser must
|
||||
// be closed after the contents of the file have been written.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func EncryptSplit(keyWriter io.Writer, dataWriter io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) {
|
||||
return encrypt(keyWriter, dataWriter, to, signed, hints, packet.SigTypeBinary, config)
|
||||
}
|
||||
|
||||
// EncryptTextSplit encrypts a message to a number of recipients and, optionally, signs
|
||||
// it. hints contains optional information, that is also encrypted, that aids
|
||||
// the recipients in processing the message. The resulting WriteCloser must
|
||||
// be closed after the contents of the file have been written.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func EncryptTextSplit(keyWriter io.Writer, dataWriter io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) {
|
||||
return encrypt(keyWriter, dataWriter, to, signed, hints, packet.SigTypeText, config)
|
||||
}
|
||||
|
||||
// writeAndSign writes the data as a payload package and, optionally, signs
|
||||
// it. hints contains optional information, that is also encrypted,
|
||||
// that aids the recipients in processing the message. The resulting
|
||||
// WriteCloser must be closed after the contents of the file have been
|
||||
// written. If config is nil, sensible defaults will be used.
|
||||
func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) {
|
||||
func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entity, hints *FileHints, sigType packet.SignatureType, config *packet.Config) (plaintext io.WriteCloser, err error) {
|
||||
var signer *packet.PrivateKey
|
||||
if signed != nil {
|
||||
signKey, ok := signed.signingKey(config.Now())
|
||||
signKey, ok := signed.SigningKeyById(config.Now(), config.SigningKey())
|
||||
if !ok {
|
||||
return nil, errors.InvalidArgumentError("no valid signing keys")
|
||||
}
|
||||
|
@ -214,7 +267,7 @@ func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entit
|
|||
|
||||
if signer != nil {
|
||||
ops := &packet.OnePassSignature{
|
||||
SigType: packet.SigTypeBinary,
|
||||
SigType: sigType,
|
||||
Hash: hash,
|
||||
PubKeyAlgo: signer.PubKeyAlgo,
|
||||
KeyId: signer.KeyId,
|
||||
|
@ -247,17 +300,29 @@ func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entit
|
|||
}
|
||||
|
||||
if signer != nil {
|
||||
return signatureWriter{payload, literalData, hash, hash.New(), signer, config}, nil
|
||||
h, wrappedHash, err := hashForSignature(hash, sigType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
metadata := &packet.LiteralData{
|
||||
Format: 't',
|
||||
FileName: hints.FileName,
|
||||
Time: epochSeconds,
|
||||
}
|
||||
if hints.IsBinary {
|
||||
metadata.Format = 'b'
|
||||
}
|
||||
return signatureWriter{payload, literalData, hash, wrappedHash, h, signer, sigType, config, metadata}, nil
|
||||
}
|
||||
return literalData, nil
|
||||
}
|
||||
|
||||
// Encrypt encrypts a message to a number of recipients and, optionally, signs
|
||||
// encrypt encrypts a message to a number of recipients and, optionally, signs
|
||||
// it. hints contains optional information, that is also encrypted, that aids
|
||||
// the recipients in processing the message. The resulting WriteCloser must
|
||||
// be closed after the contents of the file have been written.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) {
|
||||
func encrypt(keyWriter io.Writer, dataWriter io.Writer, to []*Entity, signed *Entity, hints *FileHints, sigType packet.SignatureType, config *packet.Config) (plaintext io.WriteCloser, err error) {
|
||||
if len(to) == 0 {
|
||||
return nil, errors.InvalidArgumentError("no encryption recipient provided")
|
||||
}
|
||||
|
@ -276,21 +341,39 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
|
|||
hashToHashId(crypto.SHA1),
|
||||
hashToHashId(crypto.RIPEMD160),
|
||||
}
|
||||
candidateAeadModes := []uint8{
|
||||
uint8(packet.AEADModeEAX),
|
||||
uint8(packet.AEADModeOCB),
|
||||
uint8(packet.AEADModeExperimentalGCM),
|
||||
}
|
||||
candidateCompression := []uint8{
|
||||
uint8(packet.CompressionNone),
|
||||
uint8(packet.CompressionZIP),
|
||||
uint8(packet.CompressionZLIB),
|
||||
}
|
||||
// In the event that a recipient doesn't specify any supported ciphers
|
||||
// or hash functions, these are the ones that we assume that every
|
||||
// implementation supports.
|
||||
defaultCiphers := candidateCiphers[len(candidateCiphers)-1:]
|
||||
defaultHashes := candidateHashes[len(candidateHashes)-1:]
|
||||
defaultCiphers := candidateCiphers[0:1]
|
||||
defaultHashes := candidateHashes[0:1]
|
||||
defaultAeadModes := candidateAeadModes[0:1]
|
||||
defaultCompression := candidateCompression[0:1]
|
||||
|
||||
encryptKeys := make([]Key, len(to))
|
||||
// AEAD is used only if every key supports it.
|
||||
aeadSupported := true
|
||||
|
||||
for i := range to {
|
||||
var ok bool
|
||||
encryptKeys[i], ok = to[i].encryptionKey(config.Now())
|
||||
encryptKeys[i], ok = to[i].EncryptionKey(config.Now())
|
||||
if !ok {
|
||||
return nil, errors.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys")
|
||||
}
|
||||
|
||||
sig := to[i].primaryIdentity().SelfSignature
|
||||
sig := to[i].PrimaryIdentity().SelfSignature
|
||||
if sig.AEAD == false {
|
||||
aeadSupported = false
|
||||
}
|
||||
|
||||
preferredSymmetric := sig.PreferredSymmetric
|
||||
if len(preferredSymmetric) == 0 {
|
||||
|
@ -300,15 +383,26 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
|
|||
if len(preferredHashes) == 0 {
|
||||
preferredHashes = defaultHashes
|
||||
}
|
||||
preferredAeadModes := sig.PreferredAEAD
|
||||
if len(preferredAeadModes) == 0 {
|
||||
preferredAeadModes = defaultAeadModes
|
||||
}
|
||||
preferredCompression := sig.PreferredCompression
|
||||
if len(preferredCompression) == 0 {
|
||||
preferredCompression = defaultCompression
|
||||
}
|
||||
candidateCiphers = intersectPreferences(candidateCiphers, preferredSymmetric)
|
||||
candidateHashes = intersectPreferences(candidateHashes, preferredHashes)
|
||||
candidateAeadModes = intersectPreferences(candidateAeadModes, preferredAeadModes)
|
||||
candidateCompression = intersectPreferences(candidateCompression, preferredCompression)
|
||||
}
|
||||
|
||||
if len(candidateCiphers) == 0 || len(candidateHashes) == 0 {
|
||||
if len(candidateCiphers) == 0 || len(candidateHashes) == 0 || len(candidateAeadModes) == 0 {
|
||||
return nil, errors.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms")
|
||||
}
|
||||
|
||||
cipher := packet.CipherFunction(candidateCiphers[0])
|
||||
mode := packet.AEADMode(candidateAeadModes[0])
|
||||
// If the cipher specified by config is a candidate, we'll use that.
|
||||
configuredCipher := config.Cipher()
|
||||
for _, c := range candidateCiphers {
|
||||
|
@ -325,17 +419,29 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
|
|||
}
|
||||
|
||||
for _, key := range encryptKeys {
|
||||
if err := packet.SerializeEncryptedKey(ciphertext, key.PublicKey, cipher, symKey, config); err != nil {
|
||||
if err := packet.SerializeEncryptedKey(keyWriter, key.PublicKey, cipher, symKey, config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
payload, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey, config)
|
||||
var payload io.WriteCloser
|
||||
if aeadSupported {
|
||||
payload, err = packet.SerializeAEADEncrypted(dataWriter, symKey, cipher, mode, config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
payload, err = packet.SerializeSymmetricallyEncrypted(dataWriter, cipher, symKey, config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
payload, err = handleCompression(payload, candidateCompression, config)
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeAndSign(payload, candidateHashes, signed, hints, config)
|
||||
return writeAndSign(payload, candidateHashes, signed, hints, sigType, config)
|
||||
}
|
||||
|
||||
// Sign signs a message. The resulting WriteCloser must be closed after the
|
||||
|
@ -355,13 +461,17 @@ func Sign(output io.Writer, signed *Entity, hints *FileHints, config *packet.Con
|
|||
hashToHashId(crypto.SHA1),
|
||||
hashToHashId(crypto.RIPEMD160),
|
||||
}
|
||||
defaultHashes := candidateHashes[len(candidateHashes)-1:]
|
||||
preferredHashes := signed.primaryIdentity().SelfSignature.PreferredHash
|
||||
defaultHashes := candidateHashes[0:1]
|
||||
preferredHashes := signed.PrimaryIdentity().SelfSignature.PreferredHash
|
||||
if len(preferredHashes) == 0 {
|
||||
preferredHashes = defaultHashes
|
||||
}
|
||||
candidateHashes = intersectPreferences(candidateHashes, preferredHashes)
|
||||
return writeAndSign(noOpCloser{output}, candidateHashes, signed, hints, config)
|
||||
if len(candidateHashes) == 0 {
|
||||
return nil, errors.InvalidArgumentError("cannot sign because signing key shares no common algorithms with candidate hashes")
|
||||
}
|
||||
|
||||
return writeAndSign(noOpCloser{output}, candidateHashes, signed, hints, packet.SigTypeBinary, config)
|
||||
}
|
||||
|
||||
// signatureWriter hashes the contents of a message while passing it along to
|
||||
|
@ -371,23 +481,35 @@ type signatureWriter struct {
|
|||
encryptedData io.WriteCloser
|
||||
literalData io.WriteCloser
|
||||
hashType crypto.Hash
|
||||
wrappedHash hash.Hash
|
||||
h hash.Hash
|
||||
signer *packet.PrivateKey
|
||||
sigType packet.SignatureType
|
||||
config *packet.Config
|
||||
metadata *packet.LiteralData // V5 signatures protect document metadata
|
||||
}
|
||||
|
||||
func (s signatureWriter) Write(data []byte) (int, error) {
|
||||
s.h.Write(data)
|
||||
return s.literalData.Write(data)
|
||||
s.wrappedHash.Write(data)
|
||||
switch s.sigType {
|
||||
case packet.SigTypeBinary:
|
||||
return s.literalData.Write(data)
|
||||
case packet.SigTypeText:
|
||||
flag := 0
|
||||
return writeCanonical(s.literalData, data, &flag)
|
||||
}
|
||||
return 0, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(s.sigType)))
|
||||
}
|
||||
|
||||
func (s signatureWriter) Close() error {
|
||||
sig := &packet.Signature{
|
||||
SigType: packet.SigTypeBinary,
|
||||
Version: s.signer.Version,
|
||||
SigType: s.sigType,
|
||||
PubKeyAlgo: s.signer.PubKeyAlgo,
|
||||
Hash: s.hashType,
|
||||
CreationTime: s.config.Now(),
|
||||
IssuerKeyId: &s.signer.KeyId,
|
||||
Metadata: s.metadata,
|
||||
}
|
||||
|
||||
if err := sig.Sign(s.h, s.signer, s.config); err != nil {
|
||||
|
@ -416,3 +538,31 @@ func (c noOpCloser) Write(data []byte) (n int, err error) {
|
|||
func (c noOpCloser) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleCompression(compressed io.WriteCloser, candidateCompression []uint8, config *packet.Config) (data io.WriteCloser, err error) {
|
||||
data = compressed
|
||||
confAlgo := config.Compression()
|
||||
if confAlgo == packet.CompressionNone {
|
||||
return
|
||||
}
|
||||
finalAlgo := packet.CompressionNone
|
||||
// if compression specified by config available we will use it
|
||||
for _, c := range candidateCompression {
|
||||
if uint8(confAlgo) == c {
|
||||
finalAlgo = confAlgo
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if finalAlgo != packet.CompressionNone {
|
||||
var compConfig *packet.CompressionConfig
|
||||
if config != nil {
|
||||
compConfig = config.CompressionConfig
|
||||
}
|
||||
data, err = packet.SerializeCompressed(compressed, finalAlgo, compConfig)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return data, nil
|
||||
}
|
42
vendor/github.com/acomagu/bufpipe/README.md
generated
vendored
Normal file
42
vendor/github.com/acomagu/bufpipe/README.md
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
# bufpipe: Buffered Pipe
|
||||
|
||||
[![CircleCI](https://img.shields.io/circleci/build/github/acomagu/bufpipe.svg?style=flat-square)](https://circleci.com/gh/acomagu/bufpipe) [![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat-square)](https://godoc.org/github.com/acomagu/bufpipe)
|
||||
|
||||
The buffered version of io.Pipe. It's safe for concurrent use.
|
||||
|
||||
## How does it differ from io.Pipe?
|
||||
|
||||
Writes never block because the pipe has variable-sized buffer.
|
||||
|
||||
```Go
|
||||
r, w := bufpipe.New(nil)
|
||||
io.WriteString(w, "abc") // No blocking.
|
||||
io.WriteString(w, "def") // No blocking, too.
|
||||
w.Close()
|
||||
io.Copy(os.Stdout, r)
|
||||
// Output: abcdef
|
||||
```
|
||||
|
||||
[Playground](https://play.golang.org/p/PdyBAS3pVob)
|
||||
|
||||
## How does it differ from bytes.Buffer?
|
||||
|
||||
Reads block if the internal buffer is empty until the writer is closed.
|
||||
|
||||
```Go
|
||||
r, w := bufpipe.New(nil)
|
||||
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
io.Copy(os.Stdout, r) // The reads block until the writer is closed.
|
||||
done <- struct{}{}
|
||||
}()
|
||||
|
||||
io.WriteString(w, "abc")
|
||||
io.WriteString(w, "def")
|
||||
w.Close()
|
||||
<-done
|
||||
// Output: abcdef
|
||||
```
|
||||
|
||||
[Playground](https://play.golang.org/p/UppmyLeRgX6)
|
128
vendor/github.com/acomagu/bufpipe/bufpipe.go
generated
vendored
Normal file
128
vendor/github.com/acomagu/bufpipe/bufpipe.go
generated
vendored
Normal file
|
@ -0,0 +1,128 @@
|
|||
package bufpipe
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// ErrClosedPipe is the error used for read or write operations on a closed pipe.
|
||||
var ErrClosedPipe = errors.New("bufpipe: read/write on closed pipe")
|
||||
|
||||
type pipe struct {
|
||||
cond *sync.Cond
|
||||
buf *bytes.Buffer
|
||||
rerr, werr error
|
||||
}
|
||||
|
||||
// A PipeReader is the read half of a pipe.
|
||||
type PipeReader struct {
|
||||
*pipe
|
||||
}
|
||||
|
||||
// A PipeWriter is the write half of a pipe.
|
||||
type PipeWriter struct {
|
||||
*pipe
|
||||
}
|
||||
|
||||
// New creates a synchronous pipe using buf as its initial contents. It can be
|
||||
// used to connect code expecting an io.Reader with code expecting an io.Writer.
|
||||
//
|
||||
// Unlike io.Pipe, writes never block because the internal buffer has variable
|
||||
// size. Reads block only when the buffer is empty.
|
||||
//
|
||||
// It is safe to call Read and Write in parallel with each other or with Close.
|
||||
// Parallel calls to Read and parallel calls to Write are also safe: the
|
||||
// individual calls will be gated sequentially.
|
||||
//
|
||||
// The new pipe takes ownership of buf, and the caller should not use buf after
|
||||
// this call. New is intended to prepare a PipeReader to read existing data. It
|
||||
// can also be used to set the initial size of the internal buffer for writing.
|
||||
// To do that, buf should have the desired capacity but a length of zero.
|
||||
func New(buf []byte) (*PipeReader, *PipeWriter) {
|
||||
p := &pipe{
|
||||
buf: bytes.NewBuffer(buf),
|
||||
cond: sync.NewCond(new(sync.Mutex)),
|
||||
}
|
||||
return &PipeReader{
|
||||
pipe: p,
|
||||
}, &PipeWriter{
|
||||
pipe: p,
|
||||
}
|
||||
}
|
||||
|
||||
// Read implements the standard Read interface: it reads data from the pipe,
|
||||
// reading from the internal buffer, otherwise blocking until a writer arrives
|
||||
// or the write end is closed. If the write end is closed with an error, that
|
||||
// error is returned as err; otherwise err is io.EOF.
|
||||
func (r *PipeReader) Read(data []byte) (int, error) {
|
||||
r.cond.L.Lock()
|
||||
defer r.cond.L.Unlock()
|
||||
|
||||
RETRY:
|
||||
n, err := r.buf.Read(data)
|
||||
// If not closed and no read, wait for writing.
|
||||
if err == io.EOF && r.rerr == nil && n == 0 {
|
||||
r.cond.Wait()
|
||||
goto RETRY
|
||||
}
|
||||
if err == io.EOF {
|
||||
return n, r.rerr
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Close closes the reader; subsequent writes from the write half of the pipe
|
||||
// will return error ErrClosedPipe.
|
||||
func (r *PipeReader) Close() error {
|
||||
return r.CloseWithError(nil)
|
||||
}
|
||||
|
||||
// CloseWithError closes the reader; subsequent writes to the write half of the
|
||||
// pipe will return the error err.
|
||||
func (r *PipeReader) CloseWithError(err error) error {
|
||||
r.cond.L.Lock()
|
||||
defer r.cond.L.Unlock()
|
||||
|
||||
if err == nil {
|
||||
err = ErrClosedPipe
|
||||
}
|
||||
r.werr = err
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write implements the standard Write interface: it writes data to the internal
|
||||
// buffer. If the read end is closed with an error, that err is returned as err;
|
||||
// otherwise err is ErrClosedPipe.
|
||||
func (w *PipeWriter) Write(data []byte) (int, error) {
|
||||
w.cond.L.Lock()
|
||||
defer w.cond.L.Unlock()
|
||||
|
||||
if w.werr != nil {
|
||||
return 0, w.werr
|
||||
}
|
||||
|
||||
n, err := w.buf.Write(data)
|
||||
w.cond.Signal()
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Close closes the writer; subsequent reads from the read half of the pipe will
|
||||
// return io.EOF once the internal buffer get empty.
|
||||
func (w *PipeWriter) Close() error {
|
||||
return w.CloseWithError(nil)
|
||||
}
|
||||
|
||||
// Close closes the writer; subsequent reads from the read half of the pipe will
|
||||
// return err once the internal buffer get empty.
|
||||
func (w *PipeWriter) CloseWithError(err error) error {
|
||||
w.cond.L.Lock()
|
||||
defer w.cond.L.Unlock()
|
||||
|
||||
if err == nil {
|
||||
err = io.EOF
|
||||
}
|
||||
w.rerr = err
|
||||
return nil
|
||||
}
|
2
vendor/github.com/acomagu/bufpipe/doc.go
generated
vendored
Normal file
2
vendor/github.com/acomagu/bufpipe/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
// Package bufpipe provides a IO pipe, has variable-sized buffer.
|
||||
package bufpipe
|
5
vendor/github.com/acomagu/bufpipe/go.mod
generated
vendored
Normal file
5
vendor/github.com/acomagu/bufpipe/go.mod
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
module github.com/acomagu/bufpipe
|
||||
|
||||
go 1.12
|
||||
|
||||
require github.com/matryer/is v1.2.0
|
2
vendor/github.com/acomagu/bufpipe/go.sum
generated
vendored
Normal file
2
vendor/github.com/acomagu/bufpipe/go.sum
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
|
||||
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
|
98
vendor/github.com/adrg/xdg/README.md
generated
vendored
98
vendor/github.com/adrg/xdg/README.md
generated
vendored
|
@ -1,6 +1,6 @@
|
|||
<h1 align="center">
|
||||
<div>
|
||||
<img src="https://raw.githubusercontent.com/adrg/adrg.github.io/master/assets/projects/xdg/logo.png" height="80px" alt="xdg logo"/>
|
||||
<img src="https://raw.githubusercontent.com/adrg/adrg.github.io/master/assets/projects/xdg/logo.svg" alt="xdg logo"/>
|
||||
</div>
|
||||
</h1>
|
||||
|
||||
|
@ -44,7 +44,7 @@ applications should use the XDG defined locations instead of hardcoding paths.
|
|||
|
||||
The package also includes the locations of well known [user directories](https://wiki.archlinux.org/index.php/XDG_user_directories)
|
||||
and an implementation of the [state directory](https://wiki.debian.org/XDGBaseDirectorySpecification#Proposal:_STATE_directory) proposal.
|
||||
Windows, macOS and most flavors of Unix are supported.
|
||||
Most flavors of Unix, Windows, macOS and Plan 9 are supported.
|
||||
|
||||
Full documentation can be found at: https://pkg.go.dev/github.com/adrg/xdg.
|
||||
|
||||
|
@ -58,75 +58,56 @@ present in the environment.
|
|||
|
||||
#### XDG Base Directory
|
||||
|
||||
| | Unix | macOS | Windows |
|
||||
| :-------------- | :---------------------------------- | :------------------------------------------------------------------------------------ | :-------------------------------------- |
|
||||
| XDG_DATA_HOME | `~/.local/share` | `~/Library/Application Support` | `%LOCALAPPDATA%` |
|
||||
| XDG_DATA_DIRS | `/usr/local/share`<br/>`/usr/share` | `/Library/Application Support` | `%APPDATA%\Roaming`<br/>`%PROGRAMDATA%` |
|
||||
| XDG_CONFIG_HOME | `~/.config` | `~/Library/Application Support` | `%LOCALAPPDATA%` |
|
||||
| XDG_CONFIG_DIRS | `/etc/xdg` | `~/Library/Preferences`<br/>`/Library/Application Support`<br/>`/Library/Preferences` | `%PROGRAMDATA%` |
|
||||
| XDG_CACHE_HOME | `~/.cache` | `~/Library/Caches` | `%LOCALAPPDATA%\cache` |
|
||||
| XDG_RUNTIME_DIR | `/run/user/UID` | `~/Library/Application Support` | `%LOCALAPPDATA%` |
|
||||
| | Unix | macOS | Windows | Plan 9 |
|
||||
| :--------------------------------------------- | :---------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------- | :------------------------- |
|
||||
| <kbd><b><samp>XDG_DATA_HOME</samp></b></kbd> | <kbd>~/.local/share</kbd> | <kbd>~/Library/Application Support</kbd> | <kbd>%LOCALAPPDATA%</kbd> | <kbd>$home/lib</kbd> |
|
||||
| <kbd><b><samp>XDG_DATA_DIRS</samp></b></kbd> | <kbd>/usr/local/share</kbd><br/><kbd>/usr/share</kbd> | <kbd>/Library/Application Support</kbd> | <kbd>%APPDATA%\Roaming</kbd><br/><kbd>%PROGRAMDATA%</kbd> | <kbd>/lib</kbd> |
|
||||
| <kbd><b><samp>XDG_CONFIG_HOME</samp></b></kbd> | <kbd>~/.config</kbd> | <kbd>~/Library/Application Support</kbd> | <kbd>%LOCALAPPDATA%</kbd> | <kbd>$home/lib</kbd> |
|
||||
| <kbd><b><samp>XDG_CONFIG_DIRS</samp></b></kbd> | <kbd>/etc/xdg</kbd> | <kbd>~/Library/Preferences</kbd><br/><kbd>/Library/Application Support</kbd><br/><kbd>/Library/Preferences</kbd> | <kbd>%PROGRAMDATA%</kbd> | <kbd>/lib</kbd> |
|
||||
| <kbd><b><samp>XDG_CACHE_HOME</samp></b></kbd> | <kbd>~/.cache</kbd> | <kbd>~/Library/Caches</kbd> | <kbd>%LOCALAPPDATA%\cache</kbd> | <kbd>$home/lib/cache</kbd> |
|
||||
| <kbd><b><samp>XDG_RUNTIME_DIR</samp></b></kbd> | <kbd>/run/user/UID</kbd> | <kbd>~/Library/Application Support</kbd> | <kbd>%LOCALAPPDATA%</kbd> | <kbd>/tmp</kbd> |
|
||||
|
||||
#### XDG user directories
|
||||
|
||||
| | Unix | macOS | Windows |
|
||||
| :------------------ | :------------ | :------------ | :------------------------ |
|
||||
| XDG_DESKTOP_DIR | `~/Desktop` | `~/Desktop` | `%USERPROFILE%/Desktop` |
|
||||
| XDG_DOWNLOAD_DIR | `~/Downloads` | `~/Downloads` | `%USERPROFILE%/Downloads` |
|
||||
| XDG_DOCUMENTS_DIR | `~/Documents` | `~/Documents` | `%USERPROFILE%/Documents` |
|
||||
| XDG_MUSIC_DIR | `~/Music` | `~/Music` | `%USERPROFILE%/Music` |
|
||||
| XDG_PICTURES_DIR | `~/Pictures` | `~/Pictures` | `%USERPROFILE%/Pictures` |
|
||||
| XDG_VIDEOS_DIR | `~/Videos` | `~/Movies` | `%USERPROFILE%/Videos` |
|
||||
| XDG_TEMPLATES_DIR | `~/Templates` | `~/Templates` | `%USERPROFILE%/Templates` |
|
||||
| XDG_PUBLICSHARE_DIR | `~/Public` | `~/Public` | `%PUBLIC%` |
|
||||
| | Unix | macOS | Windows | Plan 9 |
|
||||
| :------------------------------------------------- | :--------------------- | :--------------------- | :--------------------------------- | :------------------------- |
|
||||
| <kbd><b><samp>XDG_DESKTOP_DIR</samp></b></kbd> | <kbd>~/Desktop</kbd> | <kbd>~/Desktop</kbd> | <kbd>%USERPROFILE%\Desktop</kbd> | <kbd>$home/desktop</kbd> |
|
||||
| <kbd><b><samp>XDG_DOWNLOAD_DIR</samp></b></kbd> | <kbd>~/Downloads</kbd> | <kbd>~/Downloads</kbd> | <kbd>%USERPROFILE%\Downloads</kbd> | <kbd>$home/downloads</kbd> |
|
||||
| <kbd><b><samp>XDG_DOCUMENTS_DIR</samp></b></kbd> | <kbd>~/Documents</kbd> | <kbd>~/Documents</kbd> | <kbd>%USERPROFILE%\Documents</kbd> | <kbd>$home/documents</kbd> |
|
||||
| <kbd><b><samp>XDG_MUSIC_DIR</samp></b></kbd> | <kbd>~/Music</kbd> | <kbd>~/Music</kbd> | <kbd>%USERPROFILE%\Music</kbd> | <kbd>$home/music</kbd> |
|
||||
| <kbd><b><samp>XDG_PICTURES_DIR</samp></b></kbd> | <kbd>~/Pictures</kbd> | <kbd>~/Pictures</kbd> | <kbd>%USERPROFILE%\Pictures</kbd> | <kbd>$home/pictures</kbd> |
|
||||
| <kbd><b><samp>XDG_VIDEOS_DIR</samp></b></kbd> | <kbd>~/Videos</kbd> | <kbd>~/Movies</kbd> | <kbd>%USERPROFILE%\Videos</kbd> | <kbd>$home/videos</kbd> |
|
||||
| <kbd><b><samp>XDG_TEMPLATES_DIR</samp></b></kbd> | <kbd>~/Templates</kbd> | <kbd>~/Templates</kbd> | <kbd>%USERPROFILE%\Templates</kbd> | <kbd>$home/templates</kbd> |
|
||||
| <kbd><b><samp>XDG_PUBLICSHARE_DIR</samp></b></kbd> | <kbd>~/Public</kbd> | <kbd>~/Public</kbd> | <kbd>%PUBLIC%</kbd> | <kbd>$home/public</kbd> |
|
||||
|
||||
#### Non-standard directories
|
||||
|
||||
State directory
|
||||
|
||||
```
|
||||
Unix
|
||||
• ~/.local/state
|
||||
macOS
|
||||
• ~/Library/Application Support
|
||||
Windows
|
||||
• %LOCALAPPDATA%
|
||||
```
|
||||
| | Unix | macOS | Windows | Plan 9 |
|
||||
| :-------------------------------------------- | :------------------------ | :--------------------------------------- | :------------------------ | :------------------------- |
|
||||
| <kbd><b><samp>XDG_STATE_HOME</samp></b></kbd> | <kbd>~/.local/state</kbd> | <kbd>~/Library/Application Support</kbd> | <kbd>%LOCALAPPDATA%</kbd> | <kbd>$home/lib/state</kbd> |
|
||||
|
||||
Application directories
|
||||
|
||||
```
|
||||
Unix
|
||||
• $XDG_DATA_HOME/applications
|
||||
• ~/.local/share/applications
|
||||
• /usr/local/share/applications
|
||||
• /usr/share/applications
|
||||
• $XDG_DATA_DIRS/applications
|
||||
macOS
|
||||
• /Applications
|
||||
Windows
|
||||
• %APPDATA%\Roaming\Microsoft\Windows\Start Menu\Programs
|
||||
```
|
||||
| Unix | macOS | Windows | Plan 9 |
|
||||
| :--------------------------------------- | :----------------------- | :----------------------------------------------------------------- | :-------------------- |
|
||||
| <kbd>$XDG_DATA_HOME/applications</kbd> | <kbd>/Applications</kbd> | <kbd>%APPDATA%\Roaming\Microsoft\Windows\Start Menu\Programs</kbd> | <kbd>$home/bin</kbd> |
|
||||
| <kbd>~/.local/share/applications</kbd> | | | <kbd>/bin</kbd> |
|
||||
| <kbd>/usr/local/share/applications</kbd> | | | |
|
||||
| <kbd>/usr/share/applications</kbd> | | | |
|
||||
| <kbd>$XDG_DATA_DIRS/applications</kbd> | | | |
|
||||
|
||||
Font directories
|
||||
|
||||
```
|
||||
Unix
|
||||
• $XDG_DATA_HOME/fonts
|
||||
• ~/.fonts
|
||||
• ~/.local/share/fonts
|
||||
• /usr/local/share/fonts
|
||||
• /usr/share/fonts
|
||||
• $XDG_DATA_DIRS/fonts
|
||||
macOS
|
||||
• ~/Library/Fonts
|
||||
• /Library/Fonts
|
||||
• /System/Library/Fonts
|
||||
• /Network/Library/Fonts
|
||||
Windows
|
||||
• %windir%\Fonts
|
||||
• %LOCALAPPDATA%\Microsoft\Windows\Fonts
|
||||
```
|
||||
| Unix | macOS | Windows | Plan 9 |
|
||||
| :-------------------------------- | :-------------------------------- | :------------------------------------------------ | :------------------------ |
|
||||
| <kbd>$XDG_DATA_HOME/fonts</kbd> | <kbd>~/Library/Fonts</kbd> | <kbd>%windir%\Fonts</kbd> | <kbd>$home/lib/font</kbd> |
|
||||
| <kbd>~/.fonts</kbd> | <kbd>/Library/Fonts</kbd> | <kbd>%LOCALAPPDATA%\Microsoft\Windows\Fonts</kbd> | <kbd>/lib/font</kbd> |
|
||||
| <kbd>~/.local/share/fonts</kbd> | <kbd>/System/Library/Fonts</kbd> | | |
|
||||
| <kbd>/usr/local/share/fonts</kbd> | <kbd>/Network/Library/Fonts</kbd> | | |
|
||||
| <kbd>/usr/share/fonts</kbd> | | | |
|
||||
| <kbd>$XDG_DATA_DIRS/fonts</kbd> | | | |
|
||||
|
||||
## Usage
|
||||
|
||||
|
@ -228,7 +209,8 @@ See [CONTRIBUTING.MD](CONTRIBUTING.md).
|
|||
[wichert](https://github.com/wichert),
|
||||
[bouncepaw](https://github.com/bouncepaw),
|
||||
[gabriel-vasile](https://github.com/gabriel-vasile),
|
||||
[KalleDK](https://github.com/KalleDK).
|
||||
[KalleDK](https://github.com/KalleDK),
|
||||
[djdv](https://github.com/djdv).
|
||||
|
||||
## References
|
||||
|
||||
|
|
11
vendor/github.com/adrg/xdg/codecov.yml
generated
vendored
Normal file
11
vendor/github.com/adrg/xdg/codecov.yml
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
coverage:
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
target: 90%
|
||||
threshold: 1%
|
||||
patch:
|
||||
default:
|
||||
target: 100%
|
||||
ignore:
|
||||
- "paths_plan9.go"
|
2
vendor/github.com/adrg/xdg/go.mod
generated
vendored
2
vendor/github.com/adrg/xdg/go.mod
generated
vendored
|
@ -2,4 +2,4 @@ module github.com/adrg/xdg
|
|||
|
||||
go 1.14
|
||||
|
||||
require github.com/stretchr/testify v1.6.1
|
||||
require github.com/stretchr/testify v1.7.0
|
||||
|
|
5
vendor/github.com/adrg/xdg/go.sum
generated
vendored
5
vendor/github.com/adrg/xdg/go.sum
generated
vendored
|
@ -2,9 +2,10 @@ 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
|
|
42
vendor/github.com/adrg/xdg/paths_plan9.go
generated
vendored
Normal file
42
vendor/github.com/adrg/xdg/paths_plan9.go
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
package xdg
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func initBaseDirs(home string) {
|
||||
homeLibDir := filepath.Join(home, "lib")
|
||||
rootLibDir := "/lib"
|
||||
|
||||
// Initialize base directories.
|
||||
baseDirs.dataHome = xdgPath(envDataHome, homeLibDir)
|
||||
baseDirs.data = xdgPaths(envDataDirs, rootLibDir)
|
||||
baseDirs.configHome = xdgPath(envConfigHome, homeLibDir)
|
||||
baseDirs.config = xdgPaths(envConfigDirs, rootLibDir)
|
||||
baseDirs.cacheHome = xdgPath(envCacheHome, filepath.Join(homeLibDir, "cache"))
|
||||
baseDirs.runtime = xdgPath(envRuntimeDir, "/tmp")
|
||||
|
||||
// Initialize non-standard directories.
|
||||
baseDirs.stateHome = xdgPath(envStateHome, filepath.Join(homeLibDir, "state"))
|
||||
|
||||
baseDirs.applications = []string{
|
||||
filepath.Join(home, "bin"),
|
||||
"/bin",
|
||||
}
|
||||
|
||||
baseDirs.fonts = []string{
|
||||
filepath.Join(homeLibDir, "font"),
|
||||
"/lib/font",
|
||||
}
|
||||
}
|
||||
|
||||
func initUserDirs(home string) {
|
||||
UserDirs.Desktop = xdgPath(envDesktopDir, filepath.Join(home, "desktop"))
|
||||
UserDirs.Download = xdgPath(envDownloadDir, filepath.Join(home, "downloads"))
|
||||
UserDirs.Documents = xdgPath(envDocumentsDir, filepath.Join(home, "documents"))
|
||||
UserDirs.Music = xdgPath(envMusicDir, filepath.Join(home, "music"))
|
||||
UserDirs.Pictures = xdgPath(envPicturesDir, filepath.Join(home, "pictures"))
|
||||
UserDirs.Videos = xdgPath(envVideosDir, filepath.Join(home, "videos"))
|
||||
UserDirs.Templates = xdgPath(envTemplatesDir, filepath.Join(home, "templates"))
|
||||
UserDirs.PublicShare = xdgPath(envPublicShareDir, filepath.Join(home, "public"))
|
||||
}
|
2
vendor/github.com/adrg/xdg/paths_unix.go
generated
vendored
2
vendor/github.com/adrg/xdg/paths_unix.go
generated
vendored
|
@ -1,4 +1,4 @@
|
|||
// +build aix dragonfly freebsd linux nacl netbsd openbsd solaris
|
||||
// +build aix dragonfly freebsd js,wasm nacl linux netbsd openbsd solaris
|
||||
|
||||
package xdg
|
||||
|
||||
|
|
10
vendor/github.com/adrg/xdg/stat.go
generated
vendored
Normal file
10
vendor/github.com/adrg/xdg/stat.go
generated
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
// +build !windows
|
||||
|
||||
package xdg
|
||||
|
||||
import "os"
|
||||
|
||||
func pathExists(path string) bool {
|
||||
_, err := os.Stat(path)
|
||||
return err == nil || os.IsExist(err)
|
||||
}
|
15
vendor/github.com/adrg/xdg/stat_windows.go
generated
vendored
Normal file
15
vendor/github.com/adrg/xdg/stat_windows.go
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
package xdg
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func pathExists(path string) bool {
|
||||
fi, err := os.Lstat(path)
|
||||
if fi != nil && fi.Mode()&os.ModeSymlink != 0 {
|
||||
_, err = filepath.EvalSymlinks(path)
|
||||
}
|
||||
|
||||
return err == nil || os.IsExist(err)
|
||||
}
|
9
vendor/github.com/adrg/xdg/utils.go
generated
vendored
9
vendor/github.com/adrg/xdg/utils.go
generated
vendored
|
@ -33,11 +33,6 @@ func homeDir() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func exists(path string) bool {
|
||||
_, err := os.Stat(path)
|
||||
return err == nil || os.IsExist(err)
|
||||
}
|
||||
|
||||
func expandPath(path, homeDir string) string {
|
||||
if path == "" || homeDir == "" {
|
||||
return path
|
||||
|
@ -58,7 +53,7 @@ func createPath(name string, paths []string) (string, error) {
|
|||
path := filepath.Join(p, name)
|
||||
dir := filepath.Dir(path)
|
||||
|
||||
if exists(dir) {
|
||||
if pathExists(dir) {
|
||||
return path, nil
|
||||
}
|
||||
if err := os.MkdirAll(dir, os.ModeDir|0700); err == nil {
|
||||
|
@ -76,7 +71,7 @@ func searchFile(name string, paths []string) (string, error) {
|
|||
var searchedPaths []string
|
||||
for _, p := range paths {
|
||||
path := filepath.Join(p, name)
|
||||
if exists(path) {
|
||||
if pathExists(path) {
|
||||
return path, nil
|
||||
}
|
||||
|
||||
|
|
16
vendor/github.com/alecthomas/chroma/.golangci.yml
generated
vendored
16
vendor/github.com/alecthomas/chroma/.golangci.yml
generated
vendored
|
@ -25,6 +25,17 @@ linters:
|
|||
- testpackage
|
||||
- godot
|
||||
- nestif
|
||||
- paralleltest
|
||||
- nlreturn
|
||||
- cyclop
|
||||
- exhaustivestruct
|
||||
- gci
|
||||
- gofumpt
|
||||
- errorlint
|
||||
- exhaustive
|
||||
- ifshort
|
||||
- wrapcheck
|
||||
- stylecheck
|
||||
|
||||
linters-settings:
|
||||
govet:
|
||||
|
@ -36,6 +47,11 @@ linters-settings:
|
|||
goconst:
|
||||
min-len: 8
|
||||
min-occurrences: 3
|
||||
forbidigo:
|
||||
forbid:
|
||||
- (Must)?NewLexer
|
||||
exclude_godoc_examples: false
|
||||
|
||||
|
||||
issues:
|
||||
max-per-linter: 0
|
||||
|
|
2
vendor/github.com/alecthomas/chroma/.goreleaser.yml
generated
vendored
2
vendor/github.com/alecthomas/chroma/.goreleaser.yml
generated
vendored
|
@ -6,6 +6,8 @@ release:
|
|||
brews:
|
||||
-
|
||||
install: bin.install "chroma"
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
builds:
|
||||
- goos:
|
||||
- linux
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/.travis.yml
generated
vendored
12
vendor/github.com/alecthomas/chroma/.travis.yml
generated
vendored
|
@ -1,12 +0,0 @@
|
|||
sudo: false
|
||||
language: go
|
||||
go:
|
||||
- "1.13.x"
|
||||
script:
|
||||
- go test -v ./...
|
||||
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s v1.26.0
|
||||
- ./bin/golangci-lint run
|
||||
- git clean -fdx .
|
||||
after_success:
|
||||
curl -sL https://git.io/goreleaser | bash && goreleaser
|
||||
|
6
vendor/github.com/alecthomas/chroma/Makefile
generated
vendored
6
vendor/github.com/alecthomas/chroma/Makefile
generated
vendored
|
@ -1,5 +1,7 @@
|
|||
.PHONY: chromad upload all
|
||||
|
||||
VERSION ?= $(shell git describe --tags --dirty --always)
|
||||
|
||||
all: README.md tokentype_string.go
|
||||
|
||||
README.md: lexers/*/*.go
|
||||
|
@ -9,10 +11,8 @@ tokentype_string.go: types.go
|
|||
go generate
|
||||
|
||||
chromad:
|
||||
(cd ./cmd/chromad && go get github.com/GeertJohan/go.rice/rice@master && go install github.com/GeertJohan/go.rice/rice)
|
||||
rm -f chromad
|
||||
(export CGOENABLED=0 GOOS=linux ; cd ./cmd/chromad && go build -o ../../chromad .)
|
||||
rice append -i ./cmd/chromad --exec=./chromad
|
||||
(export CGOENABLED=0 GOOS=linux ; cd ./cmd/chromad && go build -ldflags="-X 'main.version=$(VERSION)'" -o ../../chromad .)
|
||||
|
||||
upload: chromad
|
||||
scp chromad root@swapoff.org: && \
|
||||
|
|
53
vendor/github.com/alecthomas/chroma/README.md
generated
vendored
53
vendor/github.com/alecthomas/chroma/README.md
generated
vendored
|
@ -1,4 +1,4 @@
|
|||
# Chroma — A general purpose syntax highlighter in pure Go [![Golang Documentation](https://godoc.org/github.com/alecthomas/chroma?status.svg)](https://godoc.org/github.com/alecthomas/chroma) [![Build Status](https://travis-ci.org/alecthomas/chroma.svg)](https://travis-ci.org/alecthomas/chroma) [![Gitter chat](https://badges.gitter.im/alecthomas.svg)](https://gitter.im/alecthomas/Lobby)
|
||||
# Chroma — A general purpose syntax highlighter in pure Go [![Golang Documentation](https://godoc.org/github.com/alecthomas/chroma?status.svg)](https://godoc.org/github.com/alecthomas/chroma) [![CircleCI](https://img.shields.io/circleci/project/github/alecthomas/chroma.svg)](https://circleci.com/gh/alecthomas/chroma) [![Go Report Card](https://goreportcard.com/badge/github.com/alecthomas/chroma)](https://goreportcard.com/report/github.com/alecthomas/chroma) [![Slack chat](https://img.shields.io/static/v1?logo=slack&style=flat&label=slack&color=green&message=gophers)](https://invite.slack.golangbridge.org/)
|
||||
|
||||
> **NOTE:** As Chroma has just been released, its API is still in flux. That said, the high-level interface should not change significantly.
|
||||
|
||||
|
@ -36,29 +36,30 @@ translators for Pygments lexers and styles.
|
|||
Prefix | Language
|
||||
:----: | --------
|
||||
A | ABAP, ABNF, ActionScript, ActionScript 3, Ada, Angular2, ANTLR, ApacheConf, APL, AppleScript, Arduino, Awk
|
||||
B | Ballerina, Base Makefile, Bash, Batchfile, BlitzBasic, BNF, Brainfuck
|
||||
C | C, C#, C++, Cap'n Proto, Cassandra CQL, Ceylon, CFEngine3, cfstatement, ChaiScript, Cheetah, Clojure, CMake, COBOL, CoffeeScript, Common Lisp, Coq, Crystal, CSS, Cython
|
||||
D | D, Dart, Diff, Django/Jinja, Docker, DTD
|
||||
B | Ballerina, Base Makefile, Bash, Batchfile, BibTeX, BlitzBasic, BNF, Brainfuck
|
||||
C | C, C#, C++, Caddyfile, Caddyfile Directives, Cap'n Proto, Cassandra CQL, Ceylon, CFEngine3, cfstatement, ChaiScript, Cheetah, Clojure, CMake, COBOL, CoffeeScript, Common Lisp, Coq, Crystal, CSS, Cython
|
||||
D | D, Dart, Diff, Django/Jinja, Docker, DTD, Dylan
|
||||
E | EBNF, Elixir, Elm, EmacsLisp, Erlang
|
||||
F | Factor, Fish, Forth, Fortran, FSharp
|
||||
G | GAS, GDScript, Genshi, Genshi HTML, Genshi Text, GLSL, Gnuplot, Go, Go HTML Template, Go Text Template, GraphQL, Groovy
|
||||
H | Handlebars, Haskell, Haxe, HCL, Hexdump, HTML, HTTP, Hy
|
||||
I | Idris, INI, Io
|
||||
G | GAS, GDScript, Genshi, Genshi HTML, Genshi Text, Gherkin, GLSL, Gnuplot, Go, Go HTML Template, Go Text Template, GraphQL, Groff, Groovy
|
||||
H | Handlebars, Haskell, Haxe, HCL, Hexdump, HLB, HTML, HTTP, Hy
|
||||
I | Idris, Igor, INI, Io
|
||||
J | J, Java, JavaScript, JSON, Julia, Jungle
|
||||
K | Kotlin
|
||||
L | Lighttpd configuration file, LLVM, Lua
|
||||
M | Mako, markdown, Mason, Mathematica, Matlab, MiniZinc, MLIR, Modula-2, MonkeyC, MorrowindScript, Myghty, MySQL
|
||||
N | NASM, Newspeak, Nginx configuration file, Nim, Nix
|
||||
O | Objective-C, OCaml, Octave, OpenSCAD, Org Mode
|
||||
P | PacmanConf, Perl, PHP, Pig, PkgConfig, PL/pgSQL, plaintext, PostgreSQL SQL dialect, PostScript, POVRay, PowerShell, Prolog, Protocol Buffer, Puppet, Python, Python 3
|
||||
P | PacmanConf, Perl, PHP, PHTML, Pig, PkgConfig, PL/pgSQL, plaintext, Pony, PostgreSQL SQL dialect, PostScript, POVRay, PowerShell, Prolog, PromQL, Protocol Buffer, Puppet, Python 2, Python
|
||||
Q | QBasic
|
||||
R | R, Racket, Ragel, react, reg, reStructuredText, Rexx, Ruby, Rust
|
||||
S | Sass, Scala, Scheme, Scilab, SCSS, Smalltalk, Smarty, SML, Snobol, Solidity, SPARQL, SQL, SquidConf, Swift, SYSTEMD, systemverilog
|
||||
R | R, Racket, Ragel, Raku, react, ReasonML, reg, reStructuredText, Rexx, Ruby, Rust
|
||||
S | SAS, Sass, Scala, Scheme, Scilab, SCSS, Smalltalk, Smarty, Snobol, Solidity, SPARQL, SQL, SquidConf, Standard ML, Stylus, Svelte, Swift, SYSTEMD, systemverilog
|
||||
T | TableGen, TASM, Tcl, Tcsh, Termcap, Terminfo, Terraform, TeX, Thrift, TOML, TradingView, Transact-SQL, Turing, Turtle, Twig, TypeScript, TypoScript, TypoScriptCssData, TypoScriptHtmlData
|
||||
V | VB.net, verilog, VHDL, VimL, vue
|
||||
W | WDTE
|
||||
X | XML, Xorg
|
||||
Y | YAML
|
||||
Y | YAML, YANG
|
||||
Z | Zig
|
||||
|
||||
|
||||
_I will attempt to keep this section up to date, but an authoritative list can be
|
||||
|
@ -183,7 +184,7 @@ following constructor options:
|
|||
- `ClassPrefix(prefix)` - prefix each generated CSS class.
|
||||
- `TabWidth(width)` - Set the rendered tab width, in characters.
|
||||
- `WithLineNumbers()` - Render line numbers (style with `LineNumbers`).
|
||||
- `LinkableLineNumbers()` - Make the line numbers linkable.
|
||||
- `LinkableLineNumbers()` - Make the line numbers linkable and be a link to themselves.
|
||||
- `HighlightLines(ranges)` - Highlight lines in these ranges (style with `LineHighlight`).
|
||||
- `LineNumbersInTable()` - Use a table for formatting line numbers and code, rather than spans.
|
||||
|
||||
|
@ -209,13 +210,13 @@ using the included Python 3 script `pygments2chroma.py`. I use something like
|
|||
the following:
|
||||
|
||||
```sh
|
||||
python3 ~/Projects/chroma/_tools/pygments2chroma.py \
|
||||
python3 _tools/pygments2chroma.py \
|
||||
pygments.lexers.jvm.KotlinLexer \
|
||||
> ~/Projects/chroma/lexers/kotlin.go \
|
||||
&& gofmt -s -w ~/Projects/chroma/lexers/*.go
|
||||
> lexers/k/kotlin.go \
|
||||
&& gofmt -s -w lexers/k/kotlin.go
|
||||
```
|
||||
|
||||
See notes in [pygments-lexers.go](https://github.com/alecthomas/chroma/blob/master/pygments-lexers.txt)
|
||||
See notes in [pygments-lexers.txt](https://github.com/alecthomas/chroma/blob/master/pygments-lexers.txt)
|
||||
for a list of lexers, and notes on some of the issues importing them.
|
||||
|
||||
<a id="markdown-formatters" name="formatters"></a>
|
||||
|
@ -254,12 +255,30 @@ A command-line interface to Chroma is included. It can be installed with:
|
|||
go get -u github.com/alecthomas/chroma/cmd/chroma
|
||||
```
|
||||
|
||||
The CLI can be used as a preprocessor to colorise output of `less(1)`,
|
||||
see documentation for the `LESSOPEN` environment variable.
|
||||
|
||||
The `--fail` flag can be used to suppress output and return with exit status
|
||||
1 to facilitate falling back to some other preprocessor in case chroma
|
||||
does not resolve a specific lexer to use for the given file. For example:
|
||||
|
||||
```shell
|
||||
export LESSOPEN='| p() { chroma --fail "$1" || cat "$1"; }; p "%s"'
|
||||
```
|
||||
|
||||
Replace `cat` with your favourite fallback preprocessor.
|
||||
|
||||
When invoked as `.lessfilter`, the `--fail` flag is automatically turned
|
||||
on under the hood for easy integration with [lesspipe shipping with
|
||||
Debian and derivatives](https://manpages.debian.org/lesspipe#USER_DEFINED_FILTERS);
|
||||
for that setup the `chroma` executable can be just symlinked to `~/.lessfilter`.
|
||||
|
||||
<a id="markdown-whats-missing-compared-to-pygments" name="whats-missing-compared-to-pygments"></a>
|
||||
## What's missing compared to Pygments?
|
||||
|
||||
- Quite a few lexers, for various reasons (pull-requests welcome):
|
||||
- Pygments lexers for complex languages often include custom code to
|
||||
handle certain aspects, such as Perl6's ability to nest code inside
|
||||
handle certain aspects, such as Raku's ability to nest code inside
|
||||
regular expressions. These require time and effort to convert.
|
||||
- I mostly only converted languages I had heard of, to reduce the porting cost.
|
||||
- Some more esoteric features of Pygments are omitted for simplicity.
|
||||
|
|
20
vendor/github.com/alecthomas/chroma/formatters/html/html.go
generated
vendored
20
vendor/github.com/alecthomas/chroma/formatters/html/html.go
generated
vendored
|
@ -131,7 +131,7 @@ var (
|
|||
}
|
||||
defaultPreWrapper = preWrapper{
|
||||
start: func(code bool, styleAttr string) string {
|
||||
return fmt.Sprintf("<pre%s>", styleAttr)
|
||||
return fmt.Sprintf(`<pre tabindex="0"%s>`, styleAttr)
|
||||
},
|
||||
end: func(code bool) string {
|
||||
return "</pre>"
|
||||
|
@ -211,7 +211,7 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
|
|||
fmt.Fprintf(w, "<span%s>", f.styleAttr(css, chroma.LineHighlight))
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "<span%s%s>%*d\n</span>", f.styleAttr(css, chroma.LineNumbersTable), f.lineIDAttribute(line), lineDigits, line)
|
||||
fmt.Fprintf(w, "<span%s%s>%s\n</span>", f.styleAttr(css, chroma.LineNumbersTable), f.lineIDAttribute(line), f.lineTitleWithLinkIfNeeded(lineDigits, line))
|
||||
|
||||
if highlight {
|
||||
fmt.Fprintf(w, "</span>")
|
||||
|
@ -237,7 +237,7 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
|
|||
}
|
||||
|
||||
if f.lineNumbers && !wrapInTable {
|
||||
fmt.Fprintf(w, "<span%s%s>%*d</span>", f.styleAttr(css, chroma.LineNumbers), f.lineIDAttribute(line), lineDigits, line)
|
||||
fmt.Fprintf(w, "<span%s%s>%s</span>", f.styleAttr(css, chroma.LineNumbers), f.lineIDAttribute(line), f.lineTitleWithLinkIfNeeded(lineDigits, line))
|
||||
}
|
||||
|
||||
for _, token := range tokens {
|
||||
|
@ -272,7 +272,19 @@ func (f *Formatter) lineIDAttribute(line int) string {
|
|||
if !f.linkableLineNumbers {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf(" id=\"%s%d\"", f.lineNumbersIDPrefix, line)
|
||||
return fmt.Sprintf(" id=\"%s\"", f.lineID(line))
|
||||
}
|
||||
|
||||
func (f *Formatter) lineTitleWithLinkIfNeeded(lineDigits, line int) string {
|
||||
title := fmt.Sprintf("%*d", lineDigits, line)
|
||||
if !f.linkableLineNumbers {
|
||||
return title
|
||||
}
|
||||
return fmt.Sprintf("<a style=\"outline: none; text-decoration:none; color:inherit\" href=\"#%s\">%s</a>", f.lineID(line), title)
|
||||
}
|
||||
|
||||
func (f *Formatter) lineID(line int) string {
|
||||
return fmt.Sprintf("%s%d", f.lineNumbersIDPrefix, line)
|
||||
}
|
||||
|
||||
func (f *Formatter) shouldHighlight(highlightIndex, line int) (bool, bool) {
|
||||
|
|
4
vendor/github.com/alecthomas/chroma/formatters/svg/svg.go
generated
vendored
4
vendor/github.com/alecthomas/chroma/formatters/svg/svg.go
generated
vendored
|
@ -120,7 +120,7 @@ func maxLineWidth(lines [][]chroma.Token) int {
|
|||
for _, tokens := range lines {
|
||||
length := 0
|
||||
for _, token := range tokens {
|
||||
length += len(strings.Replace(token.String(), ` `, " ", -1))
|
||||
length += len(strings.ReplaceAll(token.String(), ` `, " "))
|
||||
}
|
||||
if length > maxWidth {
|
||||
maxWidth = length
|
||||
|
@ -136,7 +136,7 @@ func (f *Formatter) writeTokenBackgrounds(w io.Writer, lines [][]chroma.Token, s
|
|||
for index, tokens := range lines {
|
||||
lineLength := 0
|
||||
for _, token := range tokens {
|
||||
length := len(strings.Replace(token.String(), ` `, " ", -1))
|
||||
length := len(strings.ReplaceAll(token.String(), ` `, " "))
|
||||
tokenBackground := style.Get(token.Type).Background
|
||||
if tokenBackground.IsSet() && tokenBackground != style.Get(chroma.Background).Background {
|
||||
fmt.Fprintf(w, "<rect id=\"%s\" x=\"%dch\" y=\"%fem\" width=\"%dch\" height=\"1.2em\" fill=\"%s\" />\n", escapeString(token.String()), lineLength, 1.2*float64(index)+0.25, length, style.Get(token.Type).Background.String())
|
||||
|
|
32
vendor/github.com/alecthomas/chroma/formatters/tty_indexed.go
generated
vendored
32
vendor/github.com/alecthomas/chroma/formatters/tty_indexed.go
generated
vendored
|
@ -17,6 +17,20 @@ var c = chroma.MustParseColour
|
|||
|
||||
var ttyTables = map[int]*ttyTable{
|
||||
8: {
|
||||
foreground: map[chroma.Colour]string{
|
||||
c("#000000"): "\033[30m", c("#7f0000"): "\033[31m", c("#007f00"): "\033[32m", c("#7f7fe0"): "\033[33m",
|
||||
c("#00007f"): "\033[34m", c("#7f007f"): "\033[35m", c("#007f7f"): "\033[36m", c("#e5e5e5"): "\033[37m",
|
||||
c("#555555"): "\033[1m\033[30m", c("#ff0000"): "\033[1m\033[31m", c("#00ff00"): "\033[1m\033[32m", c("#ffff00"): "\033[1m\033[33m",
|
||||
c("#0000ff"): "\033[1m\033[34m", c("#ff00ff"): "\033[1m\033[35m", c("#00ffff"): "\033[1m\033[36m", c("#ffffff"): "\033[1m\033[37m",
|
||||
},
|
||||
background: map[chroma.Colour]string{
|
||||
c("#000000"): "\033[40m", c("#7f0000"): "\033[41m", c("#007f00"): "\033[42m", c("#7f7fe0"): "\033[43m",
|
||||
c("#00007f"): "\033[44m", c("#7f007f"): "\033[45m", c("#007f7f"): "\033[46m", c("#e5e5e5"): "\033[47m",
|
||||
c("#555555"): "\033[1m\033[40m", c("#ff0000"): "\033[1m\033[41m", c("#00ff00"): "\033[1m\033[42m", c("#ffff00"): "\033[1m\033[43m",
|
||||
c("#0000ff"): "\033[1m\033[44m", c("#ff00ff"): "\033[1m\033[45m", c("#00ffff"): "\033[1m\033[46m", c("#ffffff"): "\033[1m\033[47m",
|
||||
},
|
||||
},
|
||||
16: {
|
||||
foreground: map[chroma.Colour]string{
|
||||
c("#000000"): "\033[30m", c("#7f0000"): "\033[31m", c("#007f00"): "\033[32m", c("#7f7fe0"): "\033[33m",
|
||||
c("#00007f"): "\033[34m", c("#7f007f"): "\033[35m", c("#007f7f"): "\033[36m", c("#e5e5e5"): "\033[37m",
|
||||
|
@ -227,15 +241,11 @@ type indexedTTYFormatter struct {
|
|||
func (c *indexedTTYFormatter) Format(w io.Writer, style *chroma.Style, it chroma.Iterator) (err error) {
|
||||
theme := styleToEscapeSequence(c.table, style)
|
||||
for token := it(); token != chroma.EOF; token = it() {
|
||||
// TODO: Cache token lookups?
|
||||
clr, ok := theme[token.Type]
|
||||
if !ok {
|
||||
clr, ok = theme[token.Type.SubCategory()]
|
||||
if !ok {
|
||||
clr = theme[token.Type.Category()]
|
||||
// if !ok {
|
||||
// clr = theme[chroma.InheritStyle]
|
||||
// }
|
||||
}
|
||||
}
|
||||
if clr != "" {
|
||||
|
@ -249,10 +259,22 @@ func (c *indexedTTYFormatter) Format(w io.Writer, style *chroma.Style, it chroma
|
|||
return nil
|
||||
}
|
||||
|
||||
// TTY is an 8-colour terminal formatter.
|
||||
//
|
||||
// The Lab colour space is used to map RGB values to the most appropriate index colour.
|
||||
var TTY = Register("terminal", &indexedTTYFormatter{ttyTables[8]})
|
||||
|
||||
// TTY8 is an 8-colour terminal formatter.
|
||||
//
|
||||
// The Lab colour space is used to map RGB values to the most appropriate index colour.
|
||||
var TTY8 = Register("terminal", &indexedTTYFormatter{ttyTables[8]})
|
||||
var TTY8 = Register("terminal8", &indexedTTYFormatter{ttyTables[8]})
|
||||
|
||||
// TTY16 is a 16-colour terminal formatter.
|
||||
//
|
||||
// It uses \033[3xm for normal colours and \033[90Xm for bright colours.
|
||||
//
|
||||
// The Lab colour space is used to map RGB values to the most appropriate index colour.
|
||||
var TTY16 = Register("terminal16", &indexedTTYFormatter{ttyTables[16]})
|
||||
|
||||
// TTY256 is a 256-colour terminal formatter.
|
||||
//
|
||||
|
|
2
vendor/github.com/alecthomas/chroma/go.mod
generated
vendored
2
vendor/github.com/alecthomas/chroma/go.mod
generated
vendored
|
@ -8,7 +8,7 @@ require (
|
|||
github.com/alecthomas/kong v0.2.4
|
||||
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 // indirect
|
||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964
|
||||
github.com/dlclark/regexp2 v1.2.0
|
||||
github.com/dlclark/regexp2 v1.4.0
|
||||
github.com/mattn/go-colorable v0.1.6
|
||||
github.com/mattn/go-isatty v0.0.12
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
|
|
6
vendor/github.com/alecthomas/chroma/go.sum
generated
vendored
6
vendor/github.com/alecthomas/chroma/go.sum
generated
vendored
|
@ -11,13 +11,12 @@ github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk=
|
||||
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
|
||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
|
@ -26,7 +25,6 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
|||
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
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.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
|
|
2
vendor/github.com/alecthomas/chroma/iterator.go
generated
vendored
2
vendor/github.com/alecthomas/chroma/iterator.go
generated
vendored
|
@ -4,7 +4,7 @@ import "strings"
|
|||
|
||||
// An Iterator across tokens.
|
||||
//
|
||||
// nil will be returned at the end of the Token stream.
|
||||
// EOF will be returned at the end of the Token stream.
|
||||
//
|
||||
// If an error occurs within an Iterator, it may propagate this in a panic. Formatters should recover.
|
||||
type Iterator func() Token
|
||||
|
|
9
vendor/github.com/alecthomas/chroma/lexer.go
generated
vendored
9
vendor/github.com/alecthomas/chroma/lexer.go
generated
vendored
|
@ -2,6 +2,7 @@ package chroma
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -98,9 +99,11 @@ type Lexer interface {
|
|||
// Lexers is a slice of lexers sortable by name.
|
||||
type Lexers []Lexer
|
||||
|
||||
func (l Lexers) Len() int { return len(l) }
|
||||
func (l Lexers) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
|
||||
func (l Lexers) Less(i, j int) bool { return l[i].Config().Name < l[j].Config().Name }
|
||||
func (l Lexers) Len() int { return len(l) }
|
||||
func (l Lexers) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
|
||||
func (l Lexers) Less(i, j int) bool {
|
||||
return strings.ToLower(l[i].Config().Name) < strings.ToLower(l[j].Config().Name)
|
||||
}
|
||||
|
||||
// PrioritisedLexers is a slice of lexers sortable by priority.
|
||||
type PrioritisedLexers []Lexer
|
||||
|
|
3
vendor/github.com/alecthomas/chroma/lexers/README.md
generated
vendored
3
vendor/github.com/alecthomas/chroma/lexers/README.md
generated
vendored
|
@ -3,6 +3,9 @@
|
|||
The tests in this directory feed a known input `testdata/<name>.actual` into the parser for `<name>` and check
|
||||
that its output matches `<name>.exported`.
|
||||
|
||||
It is also possible to perform several tests on a same parser `<name>`, by placing know inputs `*.actual` into a
|
||||
directory `testdata/<name>/`.
|
||||
|
||||
## Running the tests
|
||||
|
||||
Run the tests as normal:
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/a/abap.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/a/abap.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// ABAP lexer.
|
||||
var Abap = internal.Register(MustNewLexer(
|
||||
var Abap = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "ABAP",
|
||||
Aliases: []string{"abap"},
|
||||
|
@ -14,7 +14,11 @@ var Abap = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"text/x-abap"},
|
||||
CaseInsensitive: true,
|
||||
},
|
||||
Rules{
|
||||
abapRules,
|
||||
))
|
||||
|
||||
func abapRules() Rules {
|
||||
return Rules{
|
||||
"common": {
|
||||
{`\s+`, Text, nil},
|
||||
{`^\*.*$`, CommentSingle, nil},
|
||||
|
@ -52,5 +56,5 @@ var Abap = internal.Register(MustNewLexer(
|
|||
{`[/;:()\[\],.]`, Punctuation, nil},
|
||||
{`(!)(\w+)`, ByGroups(Operator, Name), nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/a/abnf.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/a/abnf.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Abnf lexer.
|
||||
var Abnf = internal.Register(MustNewLexer(
|
||||
var Abnf = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "ABNF",
|
||||
Aliases: []string{"abnf"},
|
||||
Filenames: []string{"*.abnf"},
|
||||
MimeTypes: []string{"text/x-abnf"},
|
||||
},
|
||||
Rules{
|
||||
abnfRules,
|
||||
))
|
||||
|
||||
func abnfRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`;.*$`, CommentSingle, nil},
|
||||
{`(%[si])?"[^"]*"`, Literal, nil},
|
||||
|
@ -34,5 +38,5 @@ var Abnf = internal.Register(MustNewLexer(
|
|||
{`\s+`, Text, nil},
|
||||
{`.`, Text, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/a/actionscript.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/a/actionscript.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Actionscript lexer.
|
||||
var Actionscript = internal.Register(MustNewLexer(
|
||||
var Actionscript = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "ActionScript",
|
||||
Aliases: []string{"as", "actionscript"},
|
||||
|
@ -15,7 +15,11 @@ var Actionscript = internal.Register(MustNewLexer(
|
|||
NotMultiline: true,
|
||||
DotAll: true,
|
||||
},
|
||||
Rules{
|
||||
actionscriptRules,
|
||||
))
|
||||
|
||||
func actionscriptRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\s+`, Text, nil},
|
||||
{`//.*?\n`, CommentSingle, nil},
|
||||
|
@ -35,5 +39,5 @@ var Actionscript = internal.Register(MustNewLexer(
|
|||
{`"(\\\\|\\"|[^"])*"`, LiteralStringDouble, nil},
|
||||
{`'(\\\\|\\'|[^'])*'`, LiteralStringSingle, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/a/actionscript3.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/a/actionscript3.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Actionscript 3 lexer.
|
||||
var Actionscript3 = internal.Register(MustNewLexer(
|
||||
var Actionscript3 = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "ActionScript 3",
|
||||
Aliases: []string{"as3", "actionscript3"},
|
||||
|
@ -14,7 +14,11 @@ var Actionscript3 = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"application/x-actionscript3", "text/x-actionscript3", "text/actionscript3"},
|
||||
DotAll: true,
|
||||
},
|
||||
Rules{
|
||||
actionscript3Rules,
|
||||
))
|
||||
|
||||
func actionscript3Rules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\s+`, Text, nil},
|
||||
{`(function\s+)([$a-zA-Z_]\w*)(\s*)(\()`, ByGroups(KeywordDeclaration, NameFunction, Text, Operator), Push("funcparams")},
|
||||
|
@ -52,5 +56,5 @@ var Actionscript3 = internal.Register(MustNewLexer(
|
|||
{`,`, Operator, Pop(1)},
|
||||
Default(Pop(1)),
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/a/ada.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/a/ada.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Ada lexer.
|
||||
var Ada = internal.Register(MustNewLexer(
|
||||
var Ada = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Ada",
|
||||
Aliases: []string{"ada", "ada95", "ada2005"},
|
||||
|
@ -14,7 +14,11 @@ var Ada = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"text/x-ada"},
|
||||
CaseInsensitive: true,
|
||||
},
|
||||
Rules{
|
||||
adaRules,
|
||||
))
|
||||
|
||||
func adaRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`[^\S\n]+`, Text, nil},
|
||||
{`--.*?\n`, CommentSingle, nil},
|
||||
|
@ -110,5 +114,5 @@ var Ada = internal.Register(MustNewLexer(
|
|||
{`\)`, Punctuation, Pop(1)},
|
||||
Include("root"),
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
48
vendor/github.com/alecthomas/chroma/lexers/a/al.go
generated
vendored
Normal file
48
vendor/github.com/alecthomas/chroma/lexers/a/al.go
generated
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
package a
|
||||
|
||||
import (
|
||||
. "github.com/alecthomas/chroma" // nolint
|
||||
"github.com/alecthomas/chroma/lexers/internal"
|
||||
)
|
||||
|
||||
// Al lexer.
|
||||
var Al = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "AL",
|
||||
Aliases: []string{"al"},
|
||||
Filenames: []string{"*.al", "*.dal"},
|
||||
MimeTypes: []string{"text/x-al"},
|
||||
DotAll: true,
|
||||
CaseInsensitive: true,
|
||||
},
|
||||
alRules,
|
||||
))
|
||||
|
||||
// https://github.com/microsoft/AL/blob/master/grammar/alsyntax.tmlanguage
|
||||
func alRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\s+`, TextWhitespace, nil},
|
||||
{`(?s)\/\*.*?\\*\*\/`, CommentMultiline, nil},
|
||||
{`(?s)//.*?\n`, CommentSingle, nil},
|
||||
{`\"([^\"])*\"`, Text, nil},
|
||||
{`'([^'])*'`, LiteralString, nil},
|
||||
{`\b(?i:(ARRAY|ASSERTERROR|BEGIN|BREAK|CASE|DO|DOWNTO|ELSE|END|EVENT|EXIT|FOR|FOREACH|FUNCTION|IF|IMPLEMENTS|IN|INDATASET|INTERFACE|INTERNAL|LOCAL|OF|PROCEDURE|PROGRAM|PROTECTED|REPEAT|RUNONCLIENT|SECURITYFILTERING|SUPPRESSDISPOSE|TEMPORARY|THEN|TO|TRIGGER|UNTIL|VAR|WHILE|WITH|WITHEVENTS))\b`, Keyword, nil},
|
||||
{`\b(?i:(AND|DIV|MOD|NOT|OR|XOR))\b`, OperatorWord, nil},
|
||||
{`\b(?i:(AVERAGE|CONST|COUNT|EXIST|FIELD|FILTER|LOOKUP|MAX|MIN|ORDER|SORTING|SUM|TABLEDATA|UPPERLIMIT|WHERE|ASCENDING|DESCENDING))\b`, Keyword, nil},
|
||||
// Added new objects types of BC 2021 wave 1 (REPORTEXTENSION|Entitlement|PermissionSet|PermissionSetExtension)
|
||||
{`\b(?i:(CODEUNIT|PAGE|PAGEEXTENSION|PAGECUSTOMIZATION|DOTNET|ENUM|ENUMEXTENSION|VALUE|QUERY|REPORT|TABLE|TABLEEXTENSION|XMLPORT|PROFILE|CONTROLADDIN|REPORTEXTENSION|Entitlement|PermissionSet|PermissionSetExtension))\b`, Keyword, nil},
|
||||
{`\b(?i:(Action|Array|Automation|BigInteger|BigText|Blob|Boolean|Byte|Char|ClientType|Code|Codeunit|CompletionTriggerErrorLevel|ConnectionType|Database|DataClassification|DataScope|Date|DateFormula|DateTime|Decimal|DefaultLayout|Dialog|Dictionary|DotNet|DotNetAssembly|DotNetTypeDeclaration|Duration|Enum|ErrorInfo|ErrorType|ExecutionContext|ExecutionMode|FieldClass|FieldRef|FieldType|File|FilterPageBuilder|Guid|InStream|Integer|Joker|KeyRef|List|ModuleDependencyInfo|ModuleInfo|None|Notification|NotificationScope|ObjectType|Option|OutStream|Page|PageResult|Query|Record|RecordId|RecordRef|Report|ReportFormat|SecurityFilter|SecurityFiltering|Table|TableConnectionType|TableFilter|TestAction|TestField|TestFilterField|TestPage|TestPermissions|TestRequestPage|Text|TextBuilder|TextConst|TextEncoding|Time|TransactionModel|TransactionType|Variant|Verbosity|Version|XmlPort|HttpContent|HttpHeaders|HttpClient|HttpRequestMessage|HttpResponseMessage|JsonToken|JsonValue|JsonArray|JsonObject|View|Views|XmlAttribute|XmlAttributeCollection|XmlComment|XmlCData|XmlDeclaration|XmlDocument|XmlDocumentType|XmlElement|XmlNamespaceManager|XmlNameTable|XmlNode|XmlNodeList|XmlProcessingInstruction|XmlReadOptions|XmlText|XmlWriteOptions|WebServiceActionContext|WebServiceActionResultCode|SessionSettings))\b`, Keyword, nil},
|
||||
{`\b([<>]=|<>|<|>)\b?`, Operator, nil},
|
||||
{`\b(\-|\+|\/|\*)\b`, Operator, nil},
|
||||
{`\s*(\:=|\+=|-=|\/=|\*=)\s*?`, Operator, nil},
|
||||
{`\b(?i:(ADDFIRST|ADDLAST|ADDAFTER|ADDBEFORE|ACTION|ACTIONS|AREA|ASSEMBLY|CHARTPART|CUEGROUP|CUSTOMIZES|COLUMN|DATAITEM|DATASET|ELEMENTS|EXTENDS|FIELD|FIELDGROUP|FIELDATTRIBUTE|FIELDELEMENT|FIELDGROUPS|FIELDS|FILTER|FIXED|GRID|GROUP|MOVEAFTER|MOVEBEFORE|KEY|KEYS|LABEL|LABELS|LAYOUT|MODIFY|MOVEFIRST|MOVELAST|MOVEBEFORE|MOVEAFTER|PART|REPEATER|USERCONTROL|REQUESTPAGE|SCHEMA|SEPARATOR|SYSTEMPART|TABLEELEMENT|TEXTATTRIBUTE|TEXTELEMENT|TYPE))\b`, Keyword, nil},
|
||||
{`\s*[(\.\.)&\|]\s*`, Operator, nil},
|
||||
{`\b((0(x|X)[0-9a-fA-F]*)|(([0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]+)?)(L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\b`, LiteralNumber, nil},
|
||||
{`[;:,]`, Punctuation, nil},
|
||||
{`#[ \t]*(if|else|elif|endif|define|undef|region|endregion|pragma)\b.*?\n`, CommentPreproc, nil},
|
||||
{`\w+`, Text, nil},
|
||||
{`.`, Text, nil},
|
||||
},
|
||||
}
|
||||
}
|
12
vendor/github.com/alecthomas/chroma/lexers/a/angular2.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/a/angular2.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Angular2 lexer.
|
||||
var Angular2 = internal.Register(MustNewLexer(
|
||||
var Angular2 = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Angular2",
|
||||
Aliases: []string{"ng2"},
|
||||
Filenames: []string{},
|
||||
MimeTypes: []string{},
|
||||
},
|
||||
Rules{
|
||||
angular2Rules,
|
||||
))
|
||||
|
||||
func angular2Rules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`[^{([*#]+`, Other, nil},
|
||||
{`(\{\{)(\s*)`, ByGroups(CommentPreproc, Text), Push("ngExpression")},
|
||||
|
@ -38,5 +42,5 @@ var Angular2 = internal.Register(MustNewLexer(
|
|||
{`'.*?'`, LiteralString, Pop(1)},
|
||||
{`[^\s>]+`, LiteralString, Pop(1)},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/a/antlr.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/a/antlr.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// ANTLR lexer.
|
||||
var ANTLR = internal.Register(MustNewLexer(
|
||||
var ANTLR = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "ANTLR",
|
||||
Aliases: []string{"antlr"},
|
||||
Filenames: []string{},
|
||||
MimeTypes: []string{},
|
||||
},
|
||||
Rules{
|
||||
antlrRules,
|
||||
))
|
||||
|
||||
func antlrRules() Rules {
|
||||
return Rules{
|
||||
"whitespace": {
|
||||
{`\s+`, TextWhitespace, nil},
|
||||
},
|
||||
|
@ -97,5 +101,5 @@ var ANTLR = internal.Register(MustNewLexer(
|
|||
{`(\$[a-zA-Z]+)(\.?)(text|value)?`, ByGroups(NameVariable, Punctuation, NameProperty), nil},
|
||||
{`(\\\\|\\\]|\\\[|[^\[\]])+`, Other, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/a/apache.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/a/apache.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Apacheconf lexer.
|
||||
var Apacheconf = internal.Register(MustNewLexer(
|
||||
var Apacheconf = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "ApacheConf",
|
||||
Aliases: []string{"apacheconf", "aconf", "apache"},
|
||||
|
@ -14,7 +14,11 @@ var Apacheconf = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"text/x-apacheconf"},
|
||||
CaseInsensitive: true,
|
||||
},
|
||||
Rules{
|
||||
apacheconfRules,
|
||||
))
|
||||
|
||||
func apacheconfRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\s+`, Text, nil},
|
||||
{`(#.*?)$`, Comment, nil},
|
||||
|
@ -34,5 +38,5 @@ var Apacheconf = internal.Register(MustNewLexer(
|
|||
{`"([^"\\]*(?:\\.[^"\\]*)*)"`, LiteralStringDouble, nil},
|
||||
{`[^\s"\\]+`, Text, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/a/apl.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/a/apl.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Apl lexer.
|
||||
var Apl = internal.Register(MustNewLexer(
|
||||
var Apl = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "APL",
|
||||
Aliases: []string{"apl"},
|
||||
Filenames: []string{"*.apl"},
|
||||
MimeTypes: []string{},
|
||||
},
|
||||
Rules{
|
||||
aplRules,
|
||||
))
|
||||
|
||||
func aplRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\s+`, Text, nil},
|
||||
{`[⍝#].*$`, CommentSingle, nil},
|
||||
|
@ -32,5 +36,5 @@ var Apl = internal.Register(MustNewLexer(
|
|||
{`[⍺⍵⍶⍹∇:]`, NameBuiltinPseudo, nil},
|
||||
{`[{}]`, KeywordType, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/a/applescript.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/a/applescript.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Applescript lexer.
|
||||
var Applescript = internal.Register(MustNewLexer(
|
||||
var Applescript = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "AppleScript",
|
||||
Aliases: []string{"applescript"},
|
||||
|
@ -14,7 +14,11 @@ var Applescript = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{},
|
||||
DotAll: true,
|
||||
},
|
||||
Rules{
|
||||
applescriptRules,
|
||||
))
|
||||
|
||||
func applescriptRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\s+`, Text, nil},
|
||||
{`¬\n`, LiteralStringEscape, nil},
|
||||
|
@ -51,5 +55,5 @@ var Applescript = internal.Register(MustNewLexer(
|
|||
{`[^*(]+`, CommentMultiline, nil},
|
||||
{`[*(]`, CommentMultiline, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/a/arduino.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/a/arduino.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Arduino lexer.
|
||||
var Arduino = internal.Register(MustNewLexer(
|
||||
var Arduino = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Arduino",
|
||||
Aliases: []string{"arduino"},
|
||||
|
@ -14,7 +14,11 @@ var Arduino = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"text/x-arduino"},
|
||||
EnsureNL: true,
|
||||
},
|
||||
Rules{
|
||||
arduinoRules,
|
||||
))
|
||||
|
||||
func arduinoRules() Rules {
|
||||
return Rules{
|
||||
"statements": {
|
||||
{Words(``, `\b`, `catch`, `const_cast`, `delete`, `dynamic_cast`, `explicit`, `export`, `friend`, `mutable`, `namespace`, `new`, `operator`, `private`, `protected`, `public`, `reinterpret_cast`, `restrict`, `static_cast`, `template`, `this`, `throw`, `throws`, `try`, `typeid`, `typename`, `using`, `virtual`, `constexpr`, `nullptr`, `decltype`, `thread_local`, `alignas`, `alignof`, `static_assert`, `noexcept`, `override`, `final`), Keyword, nil},
|
||||
{`char(16_t|32_t)\b`, KeywordType, nil},
|
||||
|
@ -106,5 +110,5 @@ var Arduino = internal.Register(MustNewLexer(
|
|||
{`^\s*#endif.*?(?<!\\)\n`, CommentPreproc, Pop(1)},
|
||||
{`.*?\n`, Comment, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/a/awk.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/a/awk.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Awk lexer.
|
||||
var Awk = internal.Register(MustNewLexer(
|
||||
var Awk = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Awk",
|
||||
Aliases: []string{"awk", "gawk", "mawk", "nawk"},
|
||||
Filenames: []string{"*.awk"},
|
||||
MimeTypes: []string{"application/x-awk"},
|
||||
},
|
||||
Rules{
|
||||
awkRules,
|
||||
))
|
||||
|
||||
func awkRules() Rules {
|
||||
return Rules{
|
||||
"commentsandwhitespace": {
|
||||
{`\s+`, Text, nil},
|
||||
{`#.*$`, CommentSingle, nil},
|
||||
|
@ -44,5 +48,5 @@ var Awk = internal.Register(MustNewLexer(
|
|||
{`"(\\\\|\\"|[^"])*"`, LiteralStringDouble, nil},
|
||||
{`'(\\\\|\\'|[^'])*'`, LiteralStringSingle, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/b/ballerina.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/b/ballerina.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Ballerina lexer.
|
||||
var Ballerina = internal.Register(MustNewLexer(
|
||||
var Ballerina = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Ballerina",
|
||||
Aliases: []string{"ballerina"},
|
||||
|
@ -14,7 +14,11 @@ var Ballerina = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"text/x-ballerina"},
|
||||
DotAll: true,
|
||||
},
|
||||
Rules{
|
||||
ballerinaRules,
|
||||
))
|
||||
|
||||
func ballerinaRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`[^\S\n]+`, Text, nil},
|
||||
{`//.*?\n`, CommentSingle, nil},
|
||||
|
@ -42,5 +46,5 @@ var Ballerina = internal.Register(MustNewLexer(
|
|||
"import": {
|
||||
{`[\w.]+`, NameNamespace, Pop(1)},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
23
vendor/github.com/alecthomas/chroma/lexers/b/bash.go
generated
vendored
23
vendor/github.com/alecthomas/chroma/lexers/b/bash.go
generated
vendored
|
@ -7,17 +7,27 @@ import (
|
|||
"github.com/alecthomas/chroma/lexers/internal"
|
||||
)
|
||||
|
||||
// TODO(moorereason): can this be factored away?
|
||||
var bashAnalyserRe = regexp.MustCompile(`(?m)^#!.*/bin/(?:env |)(?:bash|zsh|sh|ksh)`)
|
||||
|
||||
// Bash lexer.
|
||||
var Bash = internal.Register(MustNewLexer(
|
||||
var Bash = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Bash",
|
||||
Aliases: []string{"bash", "sh", "ksh", "zsh", "shell"},
|
||||
Filenames: []string{"*.sh", "*.ksh", "*.bash", "*.ebuild", "*.eclass", "*.exheres-0", "*.exlib", "*.zsh", "*.zshrc", ".bashrc", "bashrc", ".bash_*", "bash_*", "zshrc", ".zshrc", "PKGBUILD"},
|
||||
Filenames: []string{"*.sh", "*.ksh", "*.bash", "*.ebuild", "*.eclass", ".env", "*.env", "*.exheres-0", "*.exlib", "*.zsh", "*.zshrc", ".bashrc", "bashrc", ".bash_*", "bash_*", "zshrc", ".zshrc", "PKGBUILD"},
|
||||
MimeTypes: []string{"application/x-sh", "application/x-shellscript"},
|
||||
},
|
||||
Rules{
|
||||
bashRules,
|
||||
).SetAnalyser(func(text string) float32 {
|
||||
if bashAnalyserRe.FindString(text) != "" {
|
||||
return 1.0
|
||||
}
|
||||
return 0.0
|
||||
}))
|
||||
|
||||
func bashRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
Include("basic"),
|
||||
{"`", LiteralStringBacktick, Push("backticks")},
|
||||
|
@ -86,10 +96,5 @@ var Bash = internal.Register(MustNewLexer(
|
|||
{"`", LiteralStringBacktick, Pop(1)},
|
||||
Include("root"),
|
||||
},
|
||||
},
|
||||
).SetAnalyser(func(text string) float32 {
|
||||
if bashAnalyserRe.FindString(text) != "" {
|
||||
return 1.0
|
||||
}
|
||||
return 0.0
|
||||
}))
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/b/batch.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/b/batch.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Batchfile lexer.
|
||||
var Batchfile = internal.Register(MustNewLexer(
|
||||
var Batchfile = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Batchfile",
|
||||
Aliases: []string{"bat", "batch", "dosbatch", "winbatch"},
|
||||
|
@ -14,7 +14,11 @@ var Batchfile = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"application/x-dos-batch"},
|
||||
CaseInsensitive: true,
|
||||
},
|
||||
Rules{
|
||||
batchfileRules,
|
||||
))
|
||||
|
||||
func batchfileRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\)((?=\()|(?=\^?[\t\v\f\r ,;=\xa0]|[&<>|\n\x1a]))(?:(?:[^\n\x1a^]|\^[\n\x1a]?[\w\W])*)`, CommentSingle, nil},
|
||||
{`(?=((?:(?<=^[^:])|^[^:]?)[\t\v\f\r ,;=\xa0]*)(:))`, Text, Push("follow")},
|
||||
|
@ -190,5 +194,5 @@ var Batchfile = internal.Register(MustNewLexer(
|
|||
{`else(?=\^?[\t\v\f\r ,;=\xa0]|[&<>|\n\x1a])`, Keyword, Pop(1)},
|
||||
Default(Pop(1)),
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/b/bibtex.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/b/bibtex.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Bibtex lexer.
|
||||
var Bibtex = internal.Register(MustNewLexer(
|
||||
var Bibtex = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "BibTeX",
|
||||
Aliases: []string{"bib", "bibtex"},
|
||||
|
@ -15,7 +15,11 @@ var Bibtex = internal.Register(MustNewLexer(
|
|||
NotMultiline: true,
|
||||
CaseInsensitive: true,
|
||||
},
|
||||
Rules{
|
||||
bibtexRules,
|
||||
))
|
||||
|
||||
func bibtexRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
Include("whitespace"),
|
||||
{`@comment`, Comment, nil},
|
||||
|
@ -72,5 +76,5 @@ var Bibtex = internal.Register(MustNewLexer(
|
|||
"whitespace": {
|
||||
{`\s+`, Text, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/b/blitz.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/b/blitz.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Blitzbasic lexer.
|
||||
var Blitzbasic = internal.Register(MustNewLexer(
|
||||
var Blitzbasic = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "BlitzBasic",
|
||||
Aliases: []string{"blitzbasic", "b3d", "bplus"},
|
||||
|
@ -14,7 +14,11 @@ var Blitzbasic = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"text/x-bb"},
|
||||
CaseInsensitive: true,
|
||||
},
|
||||
Rules{
|
||||
blitzbasicRules,
|
||||
))
|
||||
|
||||
func blitzbasicRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`[ \t]+`, Text, nil},
|
||||
{`;.*?\n`, CommentSingle, nil},
|
||||
|
@ -44,5 +48,5 @@ var Blitzbasic = internal.Register(MustNewLexer(
|
|||
{`"C?`, LiteralStringDouble, Pop(1)},
|
||||
{`[^"]+`, LiteralStringDouble, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/b/bnf.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/b/bnf.go
generated
vendored
|
@ -6,19 +6,23 @@ import (
|
|||
)
|
||||
|
||||
// Bnf lexer.
|
||||
var Bnf = internal.Register(MustNewLexer(
|
||||
var Bnf = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "BNF",
|
||||
Aliases: []string{"bnf"},
|
||||
Filenames: []string{"*.bnf"},
|
||||
MimeTypes: []string{"text/x-bnf"},
|
||||
},
|
||||
Rules{
|
||||
bnfRules,
|
||||
))
|
||||
|
||||
func bnfRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`(<)([ -;=?-~]+)(>)`, ByGroups(Punctuation, NameClass, Punctuation), nil},
|
||||
{`::=`, Operator, nil},
|
||||
{`[^<>:]+`, Text, nil},
|
||||
{`.`, Text, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/b/brainfuck.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/b/brainfuck.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Brainfuck lexer.
|
||||
var Brainfuck = internal.Register(MustNewLexer(
|
||||
var Brainfuck = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Brainfuck",
|
||||
Aliases: []string{"brainfuck", "bf"},
|
||||
Filenames: []string{"*.bf", "*.b"},
|
||||
MimeTypes: []string{"application/x-brainfuck"},
|
||||
},
|
||||
Rules{
|
||||
brainfuckRules,
|
||||
))
|
||||
|
||||
func brainfuckRules() Rules {
|
||||
return Rules{
|
||||
"common": {
|
||||
{`[.,]+`, NameTag, nil},
|
||||
{`[+-]+`, NameBuiltin, nil},
|
||||
|
@ -30,5 +34,5 @@ var Brainfuck = internal.Register(MustNewLexer(
|
|||
{`\]`, Keyword, Pop(1)},
|
||||
Include("common"),
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
19
vendor/github.com/alecthomas/chroma/lexers/c/c.go
generated
vendored
19
vendor/github.com/alecthomas/chroma/lexers/c/c.go
generated
vendored
|
@ -6,14 +6,19 @@ import (
|
|||
)
|
||||
|
||||
// C lexer.
|
||||
var C = internal.Register(MustNewLexer(
|
||||
var C = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "C",
|
||||
Aliases: []string{"c"},
|
||||
Filenames: []string{"*.c", "*.h", "*.idc"},
|
||||
MimeTypes: []string{"text/x-chdr", "text/x-csrc"},
|
||||
Filenames: []string{"*.c", "*.h", "*.idc", "*.x[bp]m"},
|
||||
MimeTypes: []string{"text/x-chdr", "text/x-csrc", "image/x-xbitmap", "image/x-xpixmap"},
|
||||
EnsureNL: true,
|
||||
},
|
||||
Rules{
|
||||
cRules,
|
||||
))
|
||||
|
||||
func cRules() Rules {
|
||||
return Rules{
|
||||
"whitespace": {
|
||||
{`^#if\s+0`, CommentPreproc, Push("if0")},
|
||||
{`^#`, CommentPreproc, Push("macro")},
|
||||
|
@ -38,7 +43,7 @@ var C = internal.Register(MustNewLexer(
|
|||
{`[~!%^&*+=|?:<>/-]`, Operator, nil},
|
||||
{`[()\[\],.]`, Punctuation, nil},
|
||||
{Words(``, `\b`, `asm`, `auto`, `break`, `case`, `const`, `continue`, `default`, `do`, `else`, `enum`, `extern`, `for`, `goto`, `if`, `register`, `restricted`, `return`, `sizeof`, `static`, `struct`, `switch`, `typedef`, `union`, `volatile`, `while`), Keyword, nil},
|
||||
{`(bool|int|long|float|short|double|char|unsigned|signed|void)\b`, KeywordType, nil},
|
||||
{`(bool|int|long|float|short|double|char((8|16|32)_t)?|unsigned|signed|void|u?int(_fast|_least|)(8|16|32|64)_t)\b`, KeywordType, nil},
|
||||
{Words(``, `\b`, `inline`, `_inline`, `__inline`, `naked`, `restrict`, `thread`, `typename`), KeywordReserved, nil},
|
||||
{`(__m(128i|128d|128|64))\b`, KeywordReserved, nil},
|
||||
{Words(`__`, `\b`, `asm`, `int8`, `based`, `except`, `int16`, `stdcall`, `cdecl`, `fastcall`, `int32`, `declspec`, `finally`, `int64`, `try`, `leave`, `wchar_t`, `w64`, `unaligned`, `raise`, `noop`, `identifier`, `forceinline`, `assume`), KeywordReserved, nil},
|
||||
|
@ -87,5 +92,5 @@ var C = internal.Register(MustNewLexer(
|
|||
{`^\s*#endif.*?(?<!\\)\n`, CommentPreproc, Pop(1)},
|
||||
{`.*?\n`, Comment, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
278
vendor/github.com/alecthomas/chroma/lexers/c/caddyfile.go
generated
vendored
278
vendor/github.com/alecthomas/chroma/lexers/c/caddyfile.go
generated
vendored
|
@ -6,143 +6,149 @@ import (
|
|||
)
|
||||
|
||||
// caddyfileCommon are the rules common to both of the lexer variants
|
||||
var caddyfileCommon = Rules{
|
||||
"site_block_common": {
|
||||
// Import keyword
|
||||
{`(import)(\s+)([^\s]+)`, ByGroups(Keyword, Text, NameVariableMagic), nil},
|
||||
// Matcher definition
|
||||
{`@[^\s]+(?=\s)`, NameDecorator, Push("matcher")},
|
||||
// Matcher token stub for docs
|
||||
{`\[\<matcher\>\]`, NameDecorator, Push("matcher")},
|
||||
// These cannot have matchers but may have things that look like
|
||||
// matchers in their arguments, so we just parse as a subdirective.
|
||||
{`try_files`, Keyword, Push("subdirective")},
|
||||
// These are special, they can nest more directives
|
||||
{`handle_errors|handle|route|handle_path|not`, Keyword, Push("nested_directive")},
|
||||
// Any other directive
|
||||
{`[^\s#]+`, Keyword, Push("directive")},
|
||||
Include("base"),
|
||||
},
|
||||
"matcher": {
|
||||
{`\{`, Punctuation, Push("block")},
|
||||
// Not can be one-liner
|
||||
{`not`, Keyword, Push("deep_not_matcher")},
|
||||
// Any other same-line matcher
|
||||
{`[^\s#]+`, Keyword, Push("arguments")},
|
||||
// Terminators
|
||||
{`\n`, Text, Pop(1)},
|
||||
{`\}`, Punctuation, Pop(1)},
|
||||
Include("base"),
|
||||
},
|
||||
"block": {
|
||||
{`\}`, Punctuation, Pop(2)},
|
||||
// Not can be one-liner
|
||||
{`not`, Keyword, Push("not_matcher")},
|
||||
// Any other subdirective
|
||||
{`[^\s#]+`, Keyword, Push("subdirective")},
|
||||
Include("base"),
|
||||
},
|
||||
"nested_block": {
|
||||
{`\}`, Punctuation, Pop(2)},
|
||||
// Matcher definition
|
||||
{`@[^\s]+(?=\s)`, NameDecorator, Push("matcher")},
|
||||
// Something that starts with literally < is probably a docs stub
|
||||
{`\<[^#]+\>`, Keyword, Push("nested_directive")},
|
||||
// Any other directive
|
||||
{`[^\s#]+`, Keyword, Push("nested_directive")},
|
||||
Include("base"),
|
||||
},
|
||||
"not_matcher": {
|
||||
{`\}`, Punctuation, Pop(2)},
|
||||
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||
{`[^\s#]+`, Keyword, Push("arguments")},
|
||||
{`\s+`, Text, nil},
|
||||
},
|
||||
"deep_not_matcher": {
|
||||
{`\}`, Punctuation, Pop(2)},
|
||||
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||
{`[^\s#]+`, Keyword, Push("deep_subdirective")},
|
||||
{`\s+`, Text, nil},
|
||||
},
|
||||
"directive": {
|
||||
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||
Include("matcher_token"),
|
||||
Include("comments_pop_1"),
|
||||
{`\n`, Text, Pop(1)},
|
||||
Include("base"),
|
||||
},
|
||||
"nested_directive": {
|
||||
{`\{(?=\s)`, Punctuation, Push("nested_block")},
|
||||
Include("matcher_token"),
|
||||
Include("comments_pop_1"),
|
||||
{`\n`, Text, Pop(1)},
|
||||
Include("base"),
|
||||
},
|
||||
"subdirective": {
|
||||
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||
Include("comments_pop_1"),
|
||||
{`\n`, Text, Pop(1)},
|
||||
Include("base"),
|
||||
},
|
||||
"arguments": {
|
||||
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||
Include("comments_pop_2"),
|
||||
{`\\\n`, Text, nil}, // Skip escaped newlines
|
||||
{`\n`, Text, Pop(2)},
|
||||
Include("base"),
|
||||
},
|
||||
"deep_subdirective": {
|
||||
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||
Include("comments_pop_3"),
|
||||
{`\n`, Text, Pop(3)},
|
||||
Include("base"),
|
||||
},
|
||||
"matcher_token": {
|
||||
{`@[^\s]+`, NameDecorator, Push("arguments")}, // Named matcher
|
||||
{`/[^\s]+`, NameDecorator, Push("arguments")}, // Path matcher
|
||||
{`\*`, NameDecorator, Push("arguments")}, // Wildcard path matcher
|
||||
{`\[\<matcher\>\]`, NameDecorator, Push("arguments")}, // Matcher token stub for docs
|
||||
},
|
||||
"comments": {
|
||||
{`^#.*\n`, CommentSingle, nil}, // Comment at start of line
|
||||
{`\s+#.*\n`, CommentSingle, nil}, // Comment preceded by whitespace
|
||||
},
|
||||
"comments_pop_1": {
|
||||
{`^#.*\n`, CommentSingle, Pop(1)}, // Comment at start of line
|
||||
{`\s+#.*\n`, CommentSingle, Pop(1)}, // Comment preceded by whitespace
|
||||
},
|
||||
"comments_pop_2": {
|
||||
{`^#.*\n`, CommentSingle, Pop(2)}, // Comment at start of line
|
||||
{`\s+#.*\n`, CommentSingle, Pop(2)}, // Comment preceded by whitespace
|
||||
},
|
||||
"comments_pop_3": {
|
||||
{`^#.*\n`, CommentSingle, Pop(3)}, // Comment at start of line
|
||||
{`\s+#.*\n`, CommentSingle, Pop(3)}, // Comment preceded by whitespace
|
||||
},
|
||||
"base": {
|
||||
Include("comments"),
|
||||
{`(on|off|first|last|before|after|internal|strip_prefix|strip_suffix|replace)\b`, NameConstant, nil},
|
||||
{`(https?://)?([a-z0-9.-]+)(:)([0-9]+)`, ByGroups(Name, Name, Punctuation, LiteralNumberInteger), nil},
|
||||
{`[a-z-]+/[a-z-+]+`, LiteralString, nil},
|
||||
{`[0-9]+[km]?\b`, LiteralNumberInteger, nil},
|
||||
{`\{[\w+.\$-]+\}`, LiteralStringEscape, nil}, // Placeholder
|
||||
{`\[(?=[^#{}$]+\])`, Punctuation, nil},
|
||||
{`\]|\|`, Punctuation, nil},
|
||||
{`[^\s#{}$\]]+`, LiteralString, nil},
|
||||
{`/[^\s#]*`, Name, nil},
|
||||
{`\s+`, Text, nil},
|
||||
},
|
||||
func caddyfileCommonRules() Rules {
|
||||
return Rules{
|
||||
"site_block_common": {
|
||||
// Import keyword
|
||||
{`(import)(\s+)([^\s]+)`, ByGroups(Keyword, Text, NameVariableMagic), nil},
|
||||
// Matcher definition
|
||||
{`@[^\s]+(?=\s)`, NameDecorator, Push("matcher")},
|
||||
// Matcher token stub for docs
|
||||
{`\[\<matcher\>\]`, NameDecorator, Push("matcher")},
|
||||
// These cannot have matchers but may have things that look like
|
||||
// matchers in their arguments, so we just parse as a subdirective.
|
||||
{`try_files`, Keyword, Push("subdirective")},
|
||||
// These are special, they can nest more directives
|
||||
{`handle_errors|handle|route|handle_path|not`, Keyword, Push("nested_directive")},
|
||||
// Any other directive
|
||||
{`[^\s#]+`, Keyword, Push("directive")},
|
||||
Include("base"),
|
||||
},
|
||||
"matcher": {
|
||||
{`\{`, Punctuation, Push("block")},
|
||||
// Not can be one-liner
|
||||
{`not`, Keyword, Push("deep_not_matcher")},
|
||||
// Any other same-line matcher
|
||||
{`[^\s#]+`, Keyword, Push("arguments")},
|
||||
// Terminators
|
||||
{`\n`, Text, Pop(1)},
|
||||
{`\}`, Punctuation, Pop(1)},
|
||||
Include("base"),
|
||||
},
|
||||
"block": {
|
||||
{`\}`, Punctuation, Pop(2)},
|
||||
// Not can be one-liner
|
||||
{`not`, Keyword, Push("not_matcher")},
|
||||
// Any other subdirective
|
||||
{`[^\s#]+`, Keyword, Push("subdirective")},
|
||||
Include("base"),
|
||||
},
|
||||
"nested_block": {
|
||||
{`\}`, Punctuation, Pop(2)},
|
||||
// Matcher definition
|
||||
{`@[^\s]+(?=\s)`, NameDecorator, Push("matcher")},
|
||||
// Something that starts with literally < is probably a docs stub
|
||||
{`\<[^#]+\>`, Keyword, Push("nested_directive")},
|
||||
// Any other directive
|
||||
{`[^\s#]+`, Keyword, Push("nested_directive")},
|
||||
Include("base"),
|
||||
},
|
||||
"not_matcher": {
|
||||
{`\}`, Punctuation, Pop(2)},
|
||||
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||
{`[^\s#]+`, Keyword, Push("arguments")},
|
||||
{`\s+`, Text, nil},
|
||||
},
|
||||
"deep_not_matcher": {
|
||||
{`\}`, Punctuation, Pop(2)},
|
||||
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||
{`[^\s#]+`, Keyword, Push("deep_subdirective")},
|
||||
{`\s+`, Text, nil},
|
||||
},
|
||||
"directive": {
|
||||
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||
Include("matcher_token"),
|
||||
Include("comments_pop_1"),
|
||||
{`\n`, Text, Pop(1)},
|
||||
Include("base"),
|
||||
},
|
||||
"nested_directive": {
|
||||
{`\{(?=\s)`, Punctuation, Push("nested_block")},
|
||||
Include("matcher_token"),
|
||||
Include("comments_pop_1"),
|
||||
{`\n`, Text, Pop(1)},
|
||||
Include("base"),
|
||||
},
|
||||
"subdirective": {
|
||||
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||
Include("comments_pop_1"),
|
||||
{`\n`, Text, Pop(1)},
|
||||
Include("base"),
|
||||
},
|
||||
"arguments": {
|
||||
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||
Include("comments_pop_2"),
|
||||
{`\\\n`, Text, nil}, // Skip escaped newlines
|
||||
{`\n`, Text, Pop(2)},
|
||||
Include("base"),
|
||||
},
|
||||
"deep_subdirective": {
|
||||
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||
Include("comments_pop_3"),
|
||||
{`\n`, Text, Pop(3)},
|
||||
Include("base"),
|
||||
},
|
||||
"matcher_token": {
|
||||
{`@[^\s]+`, NameDecorator, Push("arguments")}, // Named matcher
|
||||
{`/[^\s]+`, NameDecorator, Push("arguments")}, // Path matcher
|
||||
{`\*`, NameDecorator, Push("arguments")}, // Wildcard path matcher
|
||||
{`\[\<matcher\>\]`, NameDecorator, Push("arguments")}, // Matcher token stub for docs
|
||||
},
|
||||
"comments": {
|
||||
{`^#.*\n`, CommentSingle, nil}, // Comment at start of line
|
||||
{`\s+#.*\n`, CommentSingle, nil}, // Comment preceded by whitespace
|
||||
},
|
||||
"comments_pop_1": {
|
||||
{`^#.*\n`, CommentSingle, Pop(1)}, // Comment at start of line
|
||||
{`\s+#.*\n`, CommentSingle, Pop(1)}, // Comment preceded by whitespace
|
||||
},
|
||||
"comments_pop_2": {
|
||||
{`^#.*\n`, CommentSingle, Pop(2)}, // Comment at start of line
|
||||
{`\s+#.*\n`, CommentSingle, Pop(2)}, // Comment preceded by whitespace
|
||||
},
|
||||
"comments_pop_3": {
|
||||
{`^#.*\n`, CommentSingle, Pop(3)}, // Comment at start of line
|
||||
{`\s+#.*\n`, CommentSingle, Pop(3)}, // Comment preceded by whitespace
|
||||
},
|
||||
"base": {
|
||||
Include("comments"),
|
||||
{`(on|off|first|last|before|after|internal|strip_prefix|strip_suffix|replace)\b`, NameConstant, nil},
|
||||
{`(https?://)?([a-z0-9.-]+)(:)([0-9]+)`, ByGroups(Name, Name, Punctuation, LiteralNumberInteger), nil},
|
||||
{`[a-z-]+/[a-z-+]+`, LiteralString, nil},
|
||||
{`[0-9]+[km]?\b`, LiteralNumberInteger, nil},
|
||||
{`\{[\w+.\$-]+\}`, LiteralStringEscape, nil}, // Placeholder
|
||||
{`\[(?=[^#{}$]+\])`, Punctuation, nil},
|
||||
{`\]|\|`, Punctuation, nil},
|
||||
{`[^\s#{}$\]]+`, LiteralString, nil},
|
||||
{`/[^\s#]*`, Name, nil},
|
||||
{`\s+`, Text, nil},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Caddyfile lexer.
|
||||
var Caddyfile = internal.Register(MustNewLexer(
|
||||
var Caddyfile = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Caddyfile",
|
||||
Aliases: []string{"caddyfile", "caddy"},
|
||||
Filenames: []string{"Caddyfile*"},
|
||||
MimeTypes: []string{},
|
||||
},
|
||||
Rules{
|
||||
caddyfileRules,
|
||||
))
|
||||
|
||||
func caddyfileRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
Include("comments"),
|
||||
// Global options block
|
||||
|
@ -186,21 +192,25 @@ var Caddyfile = internal.Register(MustNewLexer(
|
|||
{`\}`, Punctuation, Pop(2)},
|
||||
Include("site_block_common"),
|
||||
},
|
||||
}.Merge(caddyfileCommon),
|
||||
))
|
||||
}.Merge(caddyfileCommonRules())
|
||||
}
|
||||
|
||||
// Caddyfile directive-only lexer.
|
||||
var CaddyfileDirectives = internal.Register(MustNewLexer(
|
||||
var CaddyfileDirectives = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Caddyfile Directives",
|
||||
Aliases: []string{"caddyfile-directives", "caddyfile-d", "caddy-d"},
|
||||
Filenames: []string{},
|
||||
MimeTypes: []string{},
|
||||
},
|
||||
Rules{
|
||||
caddyfileDirectivesRules,
|
||||
))
|
||||
|
||||
func caddyfileDirectivesRules() Rules {
|
||||
return Rules{
|
||||
// Same as "site_block" in Caddyfile
|
||||
"root": {
|
||||
Include("site_block_common"),
|
||||
},
|
||||
}.Merge(caddyfileCommon),
|
||||
))
|
||||
}.Merge(caddyfileCommonRules())
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/c/capnproto.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/c/capnproto.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Cap'N'Proto Proto lexer.
|
||||
var CapNProto = internal.Register(MustNewLexer(
|
||||
var CapNProto = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Cap'n Proto",
|
||||
Aliases: []string{"capnp"},
|
||||
Filenames: []string{"*.capnp"},
|
||||
MimeTypes: []string{},
|
||||
},
|
||||
Rules{
|
||||
capNProtoRules,
|
||||
))
|
||||
|
||||
func capNProtoRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`#.*?$`, CommentSingle, nil},
|
||||
{`@[0-9a-zA-Z]*`, NameDecorator, nil},
|
||||
|
@ -57,5 +61,5 @@ var CapNProto = internal.Register(MustNewLexer(
|
|||
{`[])]`, NameAttribute, Pop(1)},
|
||||
Default(Pop(1)),
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/c/ceylon.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/c/ceylon.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Ceylon lexer.
|
||||
var Ceylon = internal.Register(MustNewLexer(
|
||||
var Ceylon = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Ceylon",
|
||||
Aliases: []string{"ceylon"},
|
||||
|
@ -14,7 +14,11 @@ var Ceylon = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"text/x-ceylon"},
|
||||
DotAll: true,
|
||||
},
|
||||
Rules{
|
||||
ceylonRules,
|
||||
))
|
||||
|
||||
func ceylonRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`^(\s*(?:[a-zA-Z_][\w.\[\]]*\s+)+?)([a-zA-Z_]\w*)(\s*)(\()`, ByGroups(UsingSelf("root"), NameFunction, Text, Operator), nil},
|
||||
{`[^\S\n]+`, Text, nil},
|
||||
|
@ -59,5 +63,5 @@ var Ceylon = internal.Register(MustNewLexer(
|
|||
{`\*/`, CommentMultiline, Pop(1)},
|
||||
{`[*/]`, CommentMultiline, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/c/cfengine3.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/c/cfengine3.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Cfengine3 lexer.
|
||||
var Cfengine3 = internal.Register(MustNewLexer(
|
||||
var Cfengine3 = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "CFEngine3",
|
||||
Aliases: []string{"cfengine3", "cf3"},
|
||||
Filenames: []string{"*.cf"},
|
||||
MimeTypes: []string{},
|
||||
},
|
||||
Rules{
|
||||
cfengine3Rules,
|
||||
))
|
||||
|
||||
func cfengine3Rules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`#.*?\n`, Comment, nil},
|
||||
{`(body)(\s+)(\S+)(\s+)(control)`, ByGroups(Keyword, Text, Keyword, Text, Keyword), nil},
|
||||
|
@ -52,5 +56,5 @@ var Cfengine3 = internal.Register(MustNewLexer(
|
|||
{`\w+`, NameVariable, nil},
|
||||
{`\s+`, Text, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/c/chaiscript.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/c/chaiscript.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Chaiscript lexer.
|
||||
var Chaiscript = internal.Register(MustNewLexer(
|
||||
var Chaiscript = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "ChaiScript",
|
||||
Aliases: []string{"chai", "chaiscript"},
|
||||
|
@ -14,7 +14,11 @@ var Chaiscript = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"text/x-chaiscript", "application/x-chaiscript"},
|
||||
DotAll: true,
|
||||
},
|
||||
Rules{
|
||||
chaiscriptRules,
|
||||
))
|
||||
|
||||
func chaiscriptRules() Rules {
|
||||
return Rules{
|
||||
"commentsandwhitespace": {
|
||||
{`\s+`, Text, nil},
|
||||
{`//.*?\n`, CommentSingle, nil},
|
||||
|
@ -59,5 +63,5 @@ var Chaiscript = internal.Register(MustNewLexer(
|
|||
{`[^\\"$]+`, LiteralStringDouble, nil},
|
||||
{`"`, LiteralStringDouble, Pop(1)},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/c/cheetah.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/c/cheetah.go
generated
vendored
|
@ -7,14 +7,18 @@ import (
|
|||
)
|
||||
|
||||
// Cheetah lexer.
|
||||
var Cheetah = internal.Register(MustNewLexer(
|
||||
var Cheetah = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Cheetah",
|
||||
Aliases: []string{"cheetah", "spitfire"},
|
||||
Filenames: []string{"*.tmpl", "*.spt"},
|
||||
MimeTypes: []string{"application/x-cheetah", "application/x-spitfire"},
|
||||
},
|
||||
Rules{
|
||||
cheetahRules,
|
||||
))
|
||||
|
||||
func cheetahRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`(##[^\n]*)$`, ByGroups(Comment), nil},
|
||||
{`#[*](.|\n)*?[*]#`, Comment, nil},
|
||||
|
@ -33,5 +37,5 @@ var Cheetah = internal.Register(MustNewLexer(
|
|||
`, Other, nil},
|
||||
{`\s+`, Text, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
28
vendor/github.com/alecthomas/chroma/lexers/c/cl.go
generated
vendored
28
vendor/github.com/alecthomas/chroma/lexers/c/cl.go
generated
vendored
|
@ -230,7 +230,7 @@ var (
|
|||
)
|
||||
|
||||
// Common Lisp lexer.
|
||||
var CommonLisp = internal.Register(TypeRemappingLexer(MustNewLexer(
|
||||
var CommonLisp = internal.Register(TypeRemappingLexer(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Common Lisp",
|
||||
Aliases: []string{"common-lisp", "cl", "lisp"},
|
||||
|
@ -238,7 +238,19 @@ var CommonLisp = internal.Register(TypeRemappingLexer(MustNewLexer(
|
|||
MimeTypes: []string{"text/x-common-lisp"},
|
||||
CaseInsensitive: true,
|
||||
},
|
||||
Rules{
|
||||
commonLispRules,
|
||||
), TypeMapping{
|
||||
{NameVariable, NameFunction, clBuiltinFunctions},
|
||||
{NameVariable, Keyword, clSpecialForms},
|
||||
{NameVariable, NameBuiltin, clMacros},
|
||||
{NameVariable, Keyword, clLambdaListKeywords},
|
||||
{NameVariable, Keyword, clDeclarations},
|
||||
{NameVariable, KeywordType, clBuiltinTypes},
|
||||
{NameVariable, NameClass, clBuiltinClasses},
|
||||
}))
|
||||
|
||||
func commonLispRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
Default(Push("body")),
|
||||
},
|
||||
|
@ -294,13 +306,5 @@ var CommonLisp = internal.Register(TypeRemappingLexer(MustNewLexer(
|
|||
{`\(`, Punctuation, Push("body")},
|
||||
{`\)`, Punctuation, Pop(1)},
|
||||
},
|
||||
},
|
||||
), TypeMapping{
|
||||
{NameVariable, NameFunction, clBuiltinFunctions},
|
||||
{NameVariable, Keyword, clSpecialForms},
|
||||
{NameVariable, NameBuiltin, clMacros},
|
||||
{NameVariable, Keyword, clLambdaListKeywords},
|
||||
{NameVariable, Keyword, clDeclarations},
|
||||
{NameVariable, KeywordType, clBuiltinTypes},
|
||||
{NameVariable, NameClass, clBuiltinClasses},
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/c/clojure.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/c/clojure.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Clojure lexer.
|
||||
var Clojure = internal.Register(MustNewLexer(
|
||||
var Clojure = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Clojure",
|
||||
Aliases: []string{"clojure", "clj"},
|
||||
Filenames: []string{"*.clj"},
|
||||
MimeTypes: []string{"text/x-clojure", "application/x-clojure"},
|
||||
},
|
||||
Rules{
|
||||
clojureRules,
|
||||
))
|
||||
|
||||
func clojureRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`;.*$`, CommentSingle, nil},
|
||||
{`[,\s]+`, Text, nil},
|
||||
|
@ -34,5 +38,5 @@ var Clojure = internal.Register(MustNewLexer(
|
|||
{`(\{|\})`, Punctuation, nil},
|
||||
{`(\(|\))`, Punctuation, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/c/cmake.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/c/cmake.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Cmake lexer.
|
||||
var Cmake = internal.Register(MustNewLexer(
|
||||
var Cmake = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "CMake",
|
||||
Aliases: []string{"cmake"},
|
||||
Filenames: []string{"*.cmake", "CMakeLists.txt"},
|
||||
MimeTypes: []string{"text/x-cmake"},
|
||||
},
|
||||
Rules{
|
||||
cmakeRules,
|
||||
))
|
||||
|
||||
func cmakeRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\b(\w+)([ \t]*)(\()`, ByGroups(NameBuiltin, Text, Punctuation), Push("args")},
|
||||
Include("keywords"),
|
||||
|
@ -40,5 +44,5 @@ var Cmake = internal.Register(MustNewLexer(
|
|||
{`[ \t]+`, Text, nil},
|
||||
{`#.*\n`, Comment, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/c/cobol.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/c/cobol.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Cobol lexer.
|
||||
var Cobol = internal.Register(MustNewLexer(
|
||||
var Cobol = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "COBOL",
|
||||
Aliases: []string{"cobol"},
|
||||
|
@ -14,7 +14,11 @@ var Cobol = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"text/x-cobol"},
|
||||
CaseInsensitive: true,
|
||||
},
|
||||
Rules{
|
||||
cobolRules,
|
||||
))
|
||||
|
||||
func cobolRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
Include("comment"),
|
||||
Include("strings"),
|
||||
|
@ -47,5 +51,5 @@ var Cobol = internal.Register(MustNewLexer(
|
|||
{`[+-]?\d*\.\d+(E[-+]?\d+)?`, LiteralNumberFloat, nil},
|
||||
{`[+-]?\d+\.\d*(E[-+]?\d+)?`, LiteralNumberFloat, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/c/coffee.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/c/coffee.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Coffeescript lexer.
|
||||
var Coffeescript = internal.Register(MustNewLexer(
|
||||
var Coffeescript = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "CoffeeScript",
|
||||
Aliases: []string{"coffee-script", "coffeescript", "coffee"},
|
||||
|
@ -15,7 +15,11 @@ var Coffeescript = internal.Register(MustNewLexer(
|
|||
NotMultiline: true,
|
||||
DotAll: true,
|
||||
},
|
||||
Rules{
|
||||
coffeescriptRules,
|
||||
))
|
||||
|
||||
func coffeescriptRules() Rules {
|
||||
return Rules{
|
||||
"commentsandwhitespace": {
|
||||
{`\s+`, Text, nil},
|
||||
{`###[^#].*?###`, CommentMultiline, nil},
|
||||
|
@ -87,5 +91,5 @@ var Coffeescript = internal.Register(MustNewLexer(
|
|||
{`#|\\.|\'|"`, LiteralString, nil},
|
||||
Include("strings"),
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/c/coldfusion.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/c/coldfusion.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Cfstatement lexer.
|
||||
var Cfstatement = internal.Register(MustNewLexer(
|
||||
var Cfstatement = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "cfstatement",
|
||||
Aliases: []string{"cfs"},
|
||||
|
@ -15,7 +15,11 @@ var Cfstatement = internal.Register(MustNewLexer(
|
|||
NotMultiline: true,
|
||||
CaseInsensitive: true,
|
||||
},
|
||||
Rules{
|
||||
cfstatementRules,
|
||||
))
|
||||
|
||||
func cfstatementRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`//.*?\n`, CommentSingle, nil},
|
||||
{`/\*(?:.|\n)*?\*/`, CommentMultiline, nil},
|
||||
|
@ -44,5 +48,5 @@ var Cfstatement = internal.Register(MustNewLexer(
|
|||
{`#`, LiteralStringDouble, nil},
|
||||
{`"`, LiteralStringDouble, Pop(1)},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/c/coq.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/c/coq.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Coq lexer.
|
||||
var Coq = internal.Register(MustNewLexer(
|
||||
var Coq = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Coq",
|
||||
Aliases: []string{"coq"},
|
||||
Filenames: []string{"*.v"},
|
||||
MimeTypes: []string{"text/x-coq"},
|
||||
},
|
||||
Rules{
|
||||
coqRules,
|
||||
))
|
||||
|
||||
func coqRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\s+`, Text, nil},
|
||||
{`false|true|\(\)|\[\]`, NameBuiltinPseudo, nil},
|
||||
|
@ -59,5 +63,5 @@ var Coq = internal.Register(MustNewLexer(
|
|||
{`[a-z][a-z0-9_\']*`, Name, Pop(1)},
|
||||
Default(Pop(1)),
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/c/cpp.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/c/cpp.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// CPP lexer.
|
||||
var CPP = internal.Register(MustNewLexer(
|
||||
var CPP = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "C++",
|
||||
Aliases: []string{"cpp", "c++"},
|
||||
|
@ -14,7 +14,11 @@ var CPP = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"text/x-c++hdr", "text/x-c++src"},
|
||||
EnsureNL: true,
|
||||
},
|
||||
Rules{
|
||||
cppRules,
|
||||
))
|
||||
|
||||
func cppRules() Rules {
|
||||
return Rules{
|
||||
"statements": {
|
||||
{Words(``, `\b`, `catch`, `const_cast`, `delete`, `dynamic_cast`, `explicit`, `export`, `friend`, `mutable`, `namespace`, `new`, `operator`, `private`, `protected`, `public`, `reinterpret_cast`, `restrict`, `static_cast`, `template`, `this`, `throw`, `throws`, `try`, `typeid`, `typename`, `using`, `virtual`, `constexpr`, `nullptr`, `decltype`, `thread_local`, `alignas`, `alignof`, `static_assert`, `noexcept`, `override`, `final`, `concept`, `requires`, `consteval`, `co_await`, `co_return`, `co_yield`), Keyword, nil},
|
||||
{`(enum)\b(\s+)(class)\b(\s*)`, ByGroups(Keyword, Text, Keyword, Text), Push("classname")},
|
||||
|
@ -102,5 +106,5 @@ var CPP = internal.Register(MustNewLexer(
|
|||
{`^\s*#endif.*?(?<!\\)\n`, CommentPreproc, Pop(1)},
|
||||
{`.*?\n`, Comment, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
15
vendor/github.com/alecthomas/chroma/lexers/c/cql.go
generated
vendored
15
vendor/github.com/alecthomas/chroma/lexers/c/cql.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// CassandraCQL lexer.
|
||||
var CassandraCQL = internal.Register(MustNewLexer(
|
||||
var CassandraCQL = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Cassandra CQL",
|
||||
Aliases: []string{"cassandra", "cql"},
|
||||
|
@ -15,7 +15,11 @@ var CassandraCQL = internal.Register(MustNewLexer(
|
|||
NotMultiline: true,
|
||||
CaseInsensitive: true,
|
||||
},
|
||||
Rules{
|
||||
cassandraCQLRules,
|
||||
))
|
||||
|
||||
func cassandraCQLRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\s+`, TextWhitespace, nil},
|
||||
{`(--|\/\/).*\n?`, CommentSingle, nil},
|
||||
|
@ -23,7 +27,8 @@ var CassandraCQL = internal.Register(MustNewLexer(
|
|||
{`(ascii|bigint|blob|boolean|counter|date|decimal|double|float|frozen|inet|int|list|map|set|smallint|text|time|timestamp|timeuuid|tinyint|tuple|uuid|varchar|varint)\b`, NameBuiltin, nil},
|
||||
{Words(``, `\b`, `ADD`, `AGGREGATE`, `ALL`, `ALLOW`, `ALTER`, `AND`, `ANY`, `APPLY`, `AS`, `ASC`, `AUTHORIZE`, `BATCH`, `BEGIN`, `BY`, `CLUSTERING`, `COLUMNFAMILY`, `COMPACT`, `CONSISTENCY`, `COUNT`, `CREATE`, `CUSTOM`, `DELETE`, `DESC`, `DISTINCT`, `DROP`, `EACH_QUORUM`, `ENTRIES`, `EXISTS`, `FILTERING`, `FROM`, `FULL`, `GRANT`, `IF`, `IN`, `INDEX`, `INFINITY`, `INSERT`, `INTO`, `KEY`, `KEYS`, `KEYSPACE`, `KEYSPACES`, `LEVEL`, `LIMIT`, `LOCAL_ONE`, `LOCAL_QUORUM`, `MATERIALIZED`, `MODIFY`, `NAN`, `NORECURSIVE`, `NOSUPERUSER`, `NOT`, `OF`, `ON`, `ONE`, `ORDER`, `PARTITION`, `PASSWORD`, `PER`, `PERMISSION`, `PERMISSIONS`, `PRIMARY`, `QUORUM`, `RENAME`, `REVOKE`, `SCHEMA`, `SELECT`, `STATIC`, `STORAGE`, `SUPERUSER`, `TABLE`, `THREE`, `TO`, `TOKEN`, `TRUNCATE`, `TTL`, `TWO`, `TYPE`, `UNLOGGED`, `UPDATE`, `USE`, `USER`, `USERS`, `USING`, `VALUES`, `VIEW`, `WHERE`, `WITH`, `WRITETIME`, `REPLICATION`, `OR`, `REPLACE`, `FUNCTION`, `CALLED`, `INPUT`, `RETURNS`, `LANGUAGE`, `ROLE`, `ROLES`, `TRIGGER`, `DURABLE_WRITES`, `LOGIN`, `OPTIONS`, `LOGGED`, `SFUNC`, `STYPE`, `FINALFUNC`, `INITCOND`, `IS`, `CONTAINS`, `JSON`, `PAGING`, `OFF`), Keyword, nil},
|
||||
{"[+*/<>=~!@#%^&|`?-]+", Operator, nil},
|
||||
{`(?s)(java|javascript)(\s+)(AS)(\s+)('|\$\$)(.*?)(\5)`,
|
||||
{
|
||||
`(?s)(java|javascript)(\s+)(AS)(\s+)('|\$\$)(.*?)(\5)`,
|
||||
UsingByGroup(
|
||||
internal.Get,
|
||||
1, 6,
|
||||
|
@ -65,5 +70,5 @@ var CassandraCQL = internal.Register(MustNewLexer(
|
|||
{`[^\$]+`, LiteralStringHeredoc, nil},
|
||||
{`\$\$`, LiteralStringHeredoc, Pop(1)},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/c/crystal.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/c/crystal.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Crystal lexer.
|
||||
var Crystal = internal.Register(MustNewLexer(
|
||||
var Crystal = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Crystal",
|
||||
Aliases: []string{"cr", "crystal"},
|
||||
|
@ -14,7 +14,11 @@ var Crystal = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"text/x-crystal"},
|
||||
DotAll: true,
|
||||
},
|
||||
Rules{
|
||||
crystalRules,
|
||||
))
|
||||
|
||||
func crystalRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`#.*?$`, CommentSingle, nil},
|
||||
{Words(``, `\b`, `abstract`, `asm`, `as`, `begin`, `break`, `case`, `do`, `else`, `elsif`, `end`, `ensure`, `extend`, `ifdef`, `if`, `include`, `instance_sizeof`, `next`, `of`, `pointerof`, `private`, `protected`, `rescue`, `return`, `require`, `sizeof`, `super`, `then`, `typeof`, `unless`, `until`, `when`, `while`, `with`, `yield`), Keyword, nil},
|
||||
|
@ -258,5 +262,5 @@ var Crystal = internal.Register(MustNewLexer(
|
|||
{`[\\#<>]`, LiteralStringRegex, nil},
|
||||
{`[^\\#<>]+`, LiteralStringRegex, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
14
vendor/github.com/alecthomas/chroma/lexers/c/csharp.go
generated
vendored
14
vendor/github.com/alecthomas/chroma/lexers/c/csharp.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// CSharp lexer.
|
||||
var CSharp = internal.Register(MustNewLexer(
|
||||
var CSharp = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "C#",
|
||||
Aliases: []string{"csharp", "c#"},
|
||||
|
@ -15,7 +15,11 @@ var CSharp = internal.Register(MustNewLexer(
|
|||
DotAll: true,
|
||||
EnsureNL: true,
|
||||
},
|
||||
Rules{
|
||||
cSharpRules,
|
||||
))
|
||||
|
||||
func cSharpRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`^\s*\[.*?\]`, NameAttribute, nil},
|
||||
{`[^\S\n]+`, Text, nil},
|
||||
|
@ -29,7 +33,7 @@ var CSharp = internal.Register(MustNewLexer(
|
|||
{`\$@?"(""|[^"])*"`, LiteralString, nil},
|
||||
{`"(\\\\|\\"|[^"\n])*["\n]`, LiteralString, nil},
|
||||
{`'\\.'|'[^\\]'`, LiteralStringChar, nil},
|
||||
{`[0-9](\.[0-9]*)?([eE][+-][0-9]+)?[flFLdD]?|0[xX][0-9a-fA-F]+[Ll]?`, LiteralNumber, nil},
|
||||
{`0[xX][0-9a-fA-F]+[Ll]?|[0-9_](\.[0-9]*)?([eE][+-]?[0-9]+)?[flFLdD]?`, LiteralNumber, nil},
|
||||
{`#[ \t]*(if|endif|else|elif|define|undef|line|error|warning|region|endregion|pragma)\b.*?\n`, CommentPreproc, nil},
|
||||
{`\b(extern)(\s+)(alias)\b`, ByGroups(Keyword, Text, Keyword), nil},
|
||||
{`(abstract|as|async|await|base|break|by|case|catch|checked|const|continue|default|delegate|do|else|enum|event|explicit|extern|false|finally|fixed|for|foreach|goto|if|implicit|in|interface|internal|is|let|lock|new|null|on|operator|out|override|params|private|protected|public|readonly|ref|return|sealed|sizeof|stackalloc|static|switch|this|throw|true|try|typeof|unchecked|unsafe|virtual|void|while|get|set|new|partial|yield|add|remove|value|alias|ascending|descending|from|group|into|orderby|select|thenby|where|join|equals)\b`, Keyword, nil},
|
||||
|
@ -47,5 +51,5 @@ var CSharp = internal.Register(MustNewLexer(
|
|||
{`(?=\()`, Text, Pop(1)},
|
||||
{`(@?[_a-zA-Z]\w*|\.)+`, NameNamespace, Pop(1)},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
25
vendor/github.com/alecthomas/chroma/lexers/c/css.go
generated
vendored
25
vendor/github.com/alecthomas/chroma/lexers/c/css.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// CSS lexer.
|
||||
var CSS = internal.Register(MustNewLexer(
|
||||
var CSS = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "CSS",
|
||||
Aliases: []string{"css"},
|
||||
Filenames: []string{"*.css"},
|
||||
MimeTypes: []string{"text/css"},
|
||||
},
|
||||
Rules{
|
||||
cssRules,
|
||||
))
|
||||
|
||||
func cssRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
Include("basics"),
|
||||
},
|
||||
|
@ -39,6 +43,18 @@ var CSS = internal.Register(MustNewLexer(
|
|||
Include("basics"),
|
||||
{`\}`, Punctuation, Pop(2)},
|
||||
},
|
||||
"atparenthesis": {
|
||||
Include("common-values"),
|
||||
{`/\*(?:.|\n)*?\*/`, Comment, nil},
|
||||
Include("numeric-values"),
|
||||
{`[*+/-]`, Operator, nil},
|
||||
{`[,]`, Punctuation, nil},
|
||||
{`"(\\\\|\\"|[^"])*"`, LiteralStringDouble, nil},
|
||||
{`'(\\\\|\\'|[^'])*'`, LiteralStringSingle, nil},
|
||||
{`[a-zA-Z_-]\w*`, Name, nil},
|
||||
{`\(`, Punctuation, Push("atparenthesis")},
|
||||
{`\)`, Punctuation, Pop(1)},
|
||||
},
|
||||
"content": {
|
||||
{`\s+`, Text, nil},
|
||||
{`\}`, Punctuation, Pop(1)},
|
||||
|
@ -73,6 +89,7 @@ var CSS = internal.Register(MustNewLexer(
|
|||
{`"(\\\\|\\"|[^"])*"`, LiteralStringDouble, nil},
|
||||
{`'(\\\\|\\'|[^'])*'`, LiteralStringSingle, nil},
|
||||
{`[a-zA-Z_-]\w*`, Name, nil},
|
||||
{`\(`, Punctuation, Push("atparenthesis")},
|
||||
{`\)`, Punctuation, Pop(1)},
|
||||
},
|
||||
"common-values": {
|
||||
|
@ -100,5 +117,5 @@ var CSS = internal.Register(MustNewLexer(
|
|||
{`%`, KeywordType, nil},
|
||||
Default(Pop(1)),
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/c/cython.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/c/cython.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Cython lexer.
|
||||
var Cython = internal.Register(MustNewLexer(
|
||||
var Cython = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Cython",
|
||||
Aliases: []string{"cython", "pyx", "pyrex"},
|
||||
Filenames: []string{"*.pyx", "*.pxd", "*.pxi"},
|
||||
MimeTypes: []string{"text/x-cython", "application/x-cython"},
|
||||
},
|
||||
Rules{
|
||||
cythonRules,
|
||||
))
|
||||
|
||||
func cythonRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\n`, Text, nil},
|
||||
{`^(\s*)("""(?:.|\n)*?""")`, ByGroups(Text, LiteralStringDoc), nil},
|
||||
|
@ -131,5 +135,5 @@ var Cython = internal.Register(MustNewLexer(
|
|||
Include("strings"),
|
||||
Include("nl"),
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
126
vendor/github.com/alecthomas/chroma/lexers/circular/php.go
generated
vendored
126
vendor/github.com/alecthomas/chroma/lexers/circular/php.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// PHP lexer for pure PHP code (not embedded in HTML).
|
||||
var PHP = internal.Register(MustNewLexer(
|
||||
var PHP = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "PHP",
|
||||
Aliases: []string{"php", "php3", "php4", "php5"},
|
||||
|
@ -16,65 +16,71 @@ var PHP = internal.Register(MustNewLexer(
|
|||
CaseInsensitive: true,
|
||||
EnsureNL: true,
|
||||
},
|
||||
phpCommonRules.Rename("php", "root"),
|
||||
phpRules,
|
||||
))
|
||||
|
||||
var phpCommonRules = Rules{
|
||||
"php": {
|
||||
{`\?>`, CommentPreproc, Pop(1)},
|
||||
{`(<<<)([\'"]?)((?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*)(\2\n.*?\n\s*)(\3)(;?)(\n)`, ByGroups(LiteralString, LiteralString, LiteralStringDelimiter, LiteralString, LiteralStringDelimiter, Punctuation, Text), nil},
|
||||
{`\s+`, Text, nil},
|
||||
{`#.*?\n`, CommentSingle, nil},
|
||||
{`//.*?\n`, CommentSingle, nil},
|
||||
{`/\*\*/`, CommentMultiline, nil},
|
||||
{`/\*\*.*?\*/`, LiteralStringDoc, nil},
|
||||
{`/\*.*?\*/`, CommentMultiline, nil},
|
||||
{`(->|::)(\s*)((?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*)`, ByGroups(Operator, Text, NameAttribute), nil},
|
||||
{`[~!%^&*+=|:.<>/@-]+`, Operator, nil},
|
||||
{`\?`, Operator, nil},
|
||||
{`[\[\]{}();,]+`, Punctuation, nil},
|
||||
{`(class)(\s+)`, ByGroups(Keyword, Text), Push("classname")},
|
||||
{`(function)(\s*)(?=\()`, ByGroups(Keyword, Text), nil},
|
||||
{`(function)(\s+)(&?)(\s*)`, ByGroups(Keyword, Text, Operator, Text), Push("functionname")},
|
||||
{`(const)(\s+)((?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*)`, ByGroups(Keyword, Text, NameConstant), nil},
|
||||
{`(and|E_PARSE|old_function|E_ERROR|or|as|E_WARNING|parent|eval|PHP_OS|break|exit|case|extends|PHP_VERSION|cfunction|FALSE|print|for|require|continue|foreach|require_once|declare|return|default|static|do|switch|die|stdClass|echo|else|TRUE|elseif|var|empty|if|xor|enddeclare|include|virtual|endfor|include_once|while|endforeach|global|endif|list|endswitch|new|endwhile|not|array|E_ALL|NULL|final|php_user_filter|interface|implements|public|private|protected|abstract|clone|try|catch|throw|this|use|namespace|trait|yield|finally)\b`, Keyword, nil},
|
||||
{`(true|false|null)\b`, KeywordConstant, nil},
|
||||
Include("magicconstants"),
|
||||
{`\$\{\$+(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*\}`, NameVariable, nil},
|
||||
{`\$+(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*`, NameVariable, nil},
|
||||
{`(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*`, NameOther, nil},
|
||||
{`(\d+\.\d*|\d*\.\d+)(e[+-]?[0-9]+)?`, LiteralNumberFloat, nil},
|
||||
{`\d+e[+-]?[0-9]+`, LiteralNumberFloat, nil},
|
||||
{`0[0-7]+`, LiteralNumberOct, nil},
|
||||
{`0x[a-f0-9]+`, LiteralNumberHex, nil},
|
||||
{`\d+`, LiteralNumberInteger, nil},
|
||||
{`0b[01]+`, LiteralNumberBin, nil},
|
||||
{`'([^'\\]*(?:\\.[^'\\]*)*)'`, LiteralStringSingle, nil},
|
||||
{"`([^`\\\\]*(?:\\\\.[^`\\\\]*)*)`", LiteralStringBacktick, nil},
|
||||
{`"`, LiteralStringDouble, Push("string")},
|
||||
},
|
||||
"magicfuncs": {
|
||||
{Words(``, `\b`, `__construct`, `__destruct`, `__call`, `__callStatic`, `__get`, `__set`, `__isset`, `__unset`, `__sleep`, `__wakeup`, `__toString`, `__invoke`, `__set_state`, `__clone`, `__debugInfo`), NameFunctionMagic, nil},
|
||||
},
|
||||
"magicconstants": {
|
||||
{Words(``, `\b`, `__LINE__`, `__FILE__`, `__DIR__`, `__FUNCTION__`, `__CLASS__`, `__TRAIT__`, `__METHOD__`, `__NAMESPACE__`), NameConstant, nil},
|
||||
},
|
||||
"classname": {
|
||||
{`(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*`, NameClass, Pop(1)},
|
||||
},
|
||||
"functionname": {
|
||||
Include("magicfuncs"),
|
||||
{`(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*`, NameFunction, Pop(1)},
|
||||
Default(Pop(1)),
|
||||
},
|
||||
"string": {
|
||||
{`"`, LiteralStringDouble, Pop(1)},
|
||||
{`[^{$"\\]+`, LiteralStringDouble, nil},
|
||||
{`\\([nrt"$\\]|[0-7]{1,3}|x[0-9a-f]{1,2})`, LiteralStringEscape, nil},
|
||||
{`\$(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*(\[\S+?\]|->(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*)?`, LiteralStringInterpol, nil},
|
||||
{`(\{\$\{)(.*?)(\}\})`, ByGroups(LiteralStringInterpol, UsingSelf("root"), LiteralStringInterpol), nil},
|
||||
{`(\{)(\$.*?)(\})`, ByGroups(LiteralStringInterpol, UsingSelf("root"), LiteralStringInterpol), nil},
|
||||
{`(\$\{)(\S+)(\})`, ByGroups(LiteralStringInterpol, NameVariable, LiteralStringInterpol), nil},
|
||||
{`[${\\]`, LiteralStringDouble, nil},
|
||||
},
|
||||
func phpRules() Rules {
|
||||
return phpCommonRules().Rename("php", "root")
|
||||
}
|
||||
|
||||
func phpCommonRules() Rules {
|
||||
return Rules{
|
||||
"php": {
|
||||
{`\?>`, CommentPreproc, Pop(1)},
|
||||
{`(<<<)([\'"]?)((?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*)(\2\n.*?\n\s*)(\3)(;?)(\n)`, ByGroups(LiteralString, LiteralString, LiteralStringDelimiter, LiteralString, LiteralStringDelimiter, Punctuation, Text), nil},
|
||||
{`\s+`, Text, nil},
|
||||
{`#.*?\n`, CommentSingle, nil},
|
||||
{`//.*?\n`, CommentSingle, nil},
|
||||
{`/\*\*/`, CommentMultiline, nil},
|
||||
{`/\*\*.*?\*/`, LiteralStringDoc, nil},
|
||||
{`/\*.*?\*/`, CommentMultiline, nil},
|
||||
{`(->|::)(\s*)((?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*)`, ByGroups(Operator, Text, NameAttribute), nil},
|
||||
{`[~!%^&*+=|:.<>/@-]+`, Operator, nil},
|
||||
{`\?`, Operator, nil},
|
||||
{`[\[\]{}();,]+`, Punctuation, nil},
|
||||
{`(class)(\s+)`, ByGroups(Keyword, Text), Push("classname")},
|
||||
{`(function)(\s*)(?=\()`, ByGroups(Keyword, Text), nil},
|
||||
{`(function)(\s+)(&?)(\s*)`, ByGroups(Keyword, Text, Operator, Text), Push("functionname")},
|
||||
{`(const)(\s+)((?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*)`, ByGroups(Keyword, Text, NameConstant), nil},
|
||||
{`(and|E_PARSE|old_function|E_ERROR|or|as|E_WARNING|parent|eval|PHP_OS|break|exit|case|extends|PHP_VERSION|cfunction|FALSE|print|for|require|continue|foreach|require_once|declare|return|default|static|do|switch|die|stdClass|echo|else|TRUE|elseif|var|empty|if|xor|enddeclare|include|virtual|endfor|include_once|while|endforeach|global|endif|list|endswitch|new|endwhile|not|array|E_ALL|NULL|final|php_user_filter|interface|implements|public|private|protected|abstract|clone|try|catch|throw|this|use|namespace|trait|yield|finally)\b`, Keyword, nil},
|
||||
{`(true|false|null)\b`, KeywordConstant, nil},
|
||||
Include("magicconstants"),
|
||||
{`\$\{\$+(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*\}`, NameVariable, nil},
|
||||
{`\$+(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*`, NameVariable, nil},
|
||||
{`(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*`, NameOther, nil},
|
||||
{`(\d+\.\d*|\d*\.\d+)(e[+-]?[0-9]+)?`, LiteralNumberFloat, nil},
|
||||
{`\d+e[+-]?[0-9]+`, LiteralNumberFloat, nil},
|
||||
{`0[0-7]+`, LiteralNumberOct, nil},
|
||||
{`0x[a-f0-9_]+`, LiteralNumberHex, nil},
|
||||
{`[\d_]+`, LiteralNumberInteger, nil},
|
||||
{`0b[01]+`, LiteralNumberBin, nil},
|
||||
{`'([^'\\]*(?:\\.[^'\\]*)*)'`, LiteralStringSingle, nil},
|
||||
{"`([^`\\\\]*(?:\\\\.[^`\\\\]*)*)`", LiteralStringBacktick, nil},
|
||||
{`"`, LiteralStringDouble, Push("string")},
|
||||
},
|
||||
"magicfuncs": {
|
||||
{Words(``, `\b`, `__construct`, `__destruct`, `__call`, `__callStatic`, `__get`, `__set`, `__isset`, `__unset`, `__sleep`, `__wakeup`, `__toString`, `__invoke`, `__set_state`, `__clone`, `__debugInfo`), NameFunctionMagic, nil},
|
||||
},
|
||||
"magicconstants": {
|
||||
{Words(``, `\b`, `__LINE__`, `__FILE__`, `__DIR__`, `__FUNCTION__`, `__CLASS__`, `__TRAIT__`, `__METHOD__`, `__NAMESPACE__`), NameConstant, nil},
|
||||
},
|
||||
"classname": {
|
||||
{`(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*`, NameClass, Pop(1)},
|
||||
},
|
||||
"functionname": {
|
||||
Include("magicfuncs"),
|
||||
{`(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*`, NameFunction, Pop(1)},
|
||||
Default(Pop(1)),
|
||||
},
|
||||
"string": {
|
||||
{`"`, LiteralStringDouble, Pop(1)},
|
||||
{`[^{$"\\]+`, LiteralStringDouble, nil},
|
||||
{`\\([nrt"$\\]|[0-7]{1,3}|x[0-9a-f]{1,2})`, LiteralStringEscape, nil},
|
||||
{`\$(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*(\[\S+?\]|->(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*)?`, LiteralStringInterpol, nil},
|
||||
{`(\{\$\{)(.*?)(\}\})`, ByGroups(LiteralStringInterpol, UsingSelf("root"), LiteralStringInterpol), nil},
|
||||
{`(\{)(\$.*?)(\})`, ByGroups(LiteralStringInterpol, UsingSelf("root"), LiteralStringInterpol), nil},
|
||||
{`(\$\{)(\S+)(\})`, ByGroups(LiteralStringInterpol, NameVariable, LiteralStringInterpol), nil},
|
||||
{`[${\\]`, LiteralStringDouble, nil},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
25
vendor/github.com/alecthomas/chroma/lexers/circular/phtml.go
generated
vendored
25
vendor/github.com/alecthomas/chroma/lexers/circular/phtml.go
generated
vendored
|
@ -9,26 +9,31 @@ import (
|
|||
)
|
||||
|
||||
// PHTML lexer is PHP in HTML.
|
||||
var PHTML = internal.Register(DelegatingLexer(h.HTML, MustNewLexer(
|
||||
var PHTML = internal.Register(DelegatingLexer(h.HTML, MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "PHTML",
|
||||
Aliases: []string{"phtml"},
|
||||
Filenames: []string{"*.phtml"},
|
||||
MimeTypes: []string{"application/x-php", "application/x-httpd-php", "application/x-httpd-php3", "application/x-httpd-php4", "application/x-httpd-php5"},
|
||||
Filenames: []string{"*.phtml", "*.php", "*.php[345]", "*.inc"},
|
||||
MimeTypes: []string{"application/x-php", "application/x-httpd-php", "application/x-httpd-php3", "application/x-httpd-php4", "application/x-httpd-php5", "text/x-php"},
|
||||
DotAll: true,
|
||||
CaseInsensitive: true,
|
||||
EnsureNL: true,
|
||||
Priority: 2,
|
||||
},
|
||||
Rules{
|
||||
"root": {
|
||||
{`<\?(php)?`, CommentPreproc, Push("php")},
|
||||
{`[^<]+`, Other, nil},
|
||||
{`<`, Other, nil},
|
||||
},
|
||||
}.Merge(phpCommonRules),
|
||||
phtmlRules,
|
||||
).SetAnalyser(func(text string) float32 {
|
||||
if strings.Contains(text, "<?php") {
|
||||
return 0.5
|
||||
}
|
||||
return 0.0
|
||||
})))
|
||||
|
||||
func phtmlRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`<\?(php)?`, CommentPreproc, Push("php")},
|
||||
{`[^<]+`, Other, nil},
|
||||
{`<`, Other, nil},
|
||||
},
|
||||
}.Merge(phpCommonRules())
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/d/d.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/d/d.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// D lexer. https://dlang.org/spec/lex.html
|
||||
var D = internal.Register(MustNewLexer(
|
||||
var D = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "D",
|
||||
Aliases: []string{"d"},
|
||||
|
@ -14,7 +14,11 @@ var D = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"text/x-d"},
|
||||
EnsureNL: true,
|
||||
},
|
||||
Rules{
|
||||
dRules,
|
||||
))
|
||||
|
||||
func dRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`[^\S\n]+`, Text, nil},
|
||||
|
||||
|
@ -65,5 +69,5 @@ var D = internal.Register(MustNewLexer(
|
|||
"import": {
|
||||
{`[\w.]+\*?`, NameNamespace, Pop(1)},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/d/dart.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/d/dart.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Dart lexer.
|
||||
var Dart = internal.Register(MustNewLexer(
|
||||
var Dart = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Dart",
|
||||
Aliases: []string{"dart"},
|
||||
|
@ -14,7 +14,11 @@ var Dart = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"text/x-dart"},
|
||||
DotAll: true,
|
||||
},
|
||||
Rules{
|
||||
dartRules,
|
||||
))
|
||||
|
||||
func dartRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
Include("string_literal"),
|
||||
{`#!(.*?)$`, CommentPreproc, nil},
|
||||
|
@ -87,5 +91,5 @@ var Dart = internal.Register(MustNewLexer(
|
|||
Include("string_common"),
|
||||
{`(\$|\')+`, LiteralStringSingle, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/d/diff.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/d/diff.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Diff lexer.
|
||||
var Diff = internal.Register(MustNewLexer(
|
||||
var Diff = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Diff",
|
||||
Aliases: []string{"diff", "udiff"},
|
||||
|
@ -14,7 +14,11 @@ var Diff = internal.Register(MustNewLexer(
|
|||
Filenames: []string{"*.diff", "*.patch"},
|
||||
MimeTypes: []string{"text/x-diff", "text/x-patch"},
|
||||
},
|
||||
Rules{
|
||||
diffRules,
|
||||
))
|
||||
|
||||
func diffRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{` .*\n`, Text, nil},
|
||||
{`\+.*\n`, GenericInserted, nil},
|
||||
|
@ -25,5 +29,5 @@ var Diff = internal.Register(MustNewLexer(
|
|||
{`=.*\n`, GenericHeading, nil},
|
||||
{`.*\n`, Text, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/d/django.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/d/django.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Django/Jinja lexer.
|
||||
var DjangoJinja = internal.Register(MustNewLexer(
|
||||
var DjangoJinja = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Django/Jinja",
|
||||
Aliases: []string{"django", "jinja"},
|
||||
|
@ -14,7 +14,11 @@ var DjangoJinja = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"application/x-django-templating", "application/x-jinja"},
|
||||
DotAll: true,
|
||||
},
|
||||
Rules{
|
||||
djangoJinjaRules,
|
||||
))
|
||||
|
||||
func djangoJinjaRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`[^{]+`, Other, nil},
|
||||
{`\{\{`, CommentPreproc, Push("var")},
|
||||
|
@ -49,5 +53,5 @@ var DjangoJinja = internal.Register(MustNewLexer(
|
|||
Include("varnames"),
|
||||
{`.`, Punctuation, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/d/docker.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/d/docker.go
generated
vendored
|
@ -8,7 +8,7 @@ import (
|
|||
)
|
||||
|
||||
// Docker lexer.
|
||||
var Docker = internal.Register(MustNewLexer(
|
||||
var Docker = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Docker",
|
||||
Aliases: []string{"docker", "dockerfile"},
|
||||
|
@ -16,7 +16,11 @@ var Docker = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"text/x-dockerfile-config"},
|
||||
CaseInsensitive: true,
|
||||
},
|
||||
Rules{
|
||||
dockerRules,
|
||||
))
|
||||
|
||||
func dockerRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`#.*`, Comment, nil},
|
||||
{`(ONBUILD)((?:\s*\\?\s*))`, ByGroups(Keyword, Using(b.Bash)), nil},
|
||||
|
@ -27,5 +31,5 @@ var Docker = internal.Register(MustNewLexer(
|
|||
{`((?:RUN|CMD|ENTRYPOINT|ENV|ARG|LABEL|ADD|COPY))`, Keyword, nil},
|
||||
{`(.*\\\n)*.+`, Using(b.Bash), nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/d/dtd.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/d/dtd.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Dtd lexer.
|
||||
var Dtd = internal.Register(MustNewLexer(
|
||||
var Dtd = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "DTD",
|
||||
Aliases: []string{"dtd"},
|
||||
|
@ -14,7 +14,11 @@ var Dtd = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"application/xml-dtd"},
|
||||
DotAll: true,
|
||||
},
|
||||
Rules{
|
||||
dtdRules,
|
||||
))
|
||||
|
||||
func dtdRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
Include("common"),
|
||||
{`(<!ELEMENT)(\s+)(\S+)`, ByGroups(Keyword, Text, NameTag), Push("element")},
|
||||
|
@ -65,5 +69,5 @@ var Dtd = internal.Register(MustNewLexer(
|
|||
{`[^>\s|()?+*,]+`, NameAttribute, nil},
|
||||
{`>`, Keyword, Pop(1)},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
76
vendor/github.com/alecthomas/chroma/lexers/d/dylan.go
generated
vendored
Normal file
76
vendor/github.com/alecthomas/chroma/lexers/d/dylan.go
generated
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
package d
|
||||
|
||||
import (
|
||||
. "github.com/alecthomas/chroma" // nolint
|
||||
"github.com/alecthomas/chroma/lexers/internal"
|
||||
)
|
||||
|
||||
// Dylan lexer.
|
||||
var Dylan = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Dylan",
|
||||
Aliases: []string{"dylan"},
|
||||
Filenames: []string{"*.dylan", "*.dyl", "*.intr"},
|
||||
MimeTypes: []string{"text/x-dylan"},
|
||||
CaseInsensitive: true,
|
||||
},
|
||||
func() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\s+`, Whitespace, nil},
|
||||
{`//.*?\n`, CommentSingle, nil},
|
||||
{`([a-z0-9-]+:)([ \t]*)(.*(?:\n[ \t].+)*)`, ByGroups(NameAttribute, Whitespace, LiteralString), nil},
|
||||
Default(Push("code")),
|
||||
},
|
||||
"code": {
|
||||
{`\s+`, Whitespace, nil},
|
||||
{`//.*?\n`, CommentSingle, nil},
|
||||
{`/\*`, CommentMultiline, Push("comment")},
|
||||
{`"`, LiteralString, Push("string")},
|
||||
{`'(\\.|\\[0-7]{1,3}|\\x[a-f0-9]{1,2}|[^\\\'\n])'`, LiteralStringChar, nil},
|
||||
{`#b[01]+`, LiteralNumberBin, nil},
|
||||
{`#o[0-7]+`, LiteralNumberOct, nil},
|
||||
{`[-+]?(\d*\.\d+([ed][-+]?\d+)?|\d+(\.\d*)?e[-+]?\d+)`, LiteralNumberFloat, nil},
|
||||
{`[-+]?\d+`, LiteralNumberInteger, nil},
|
||||
{`#x[0-9a-f]+`, LiteralNumberHex, nil},
|
||||
|
||||
{`(\?\\?)([\w!&*<>|^$%@+~?/=-]+)(:)(token|name|variable|expression|body|case-body|\*)`,
|
||||
ByGroups(Operator, NameVariable, Operator, NameBuiltin), nil},
|
||||
{`(\?)(:)(token|name|variable|expression|body|case-body|\*)`,
|
||||
ByGroups(Operator, Operator, NameVariable), nil},
|
||||
{`(\?\\?)([\w!&*<>|^$%@+~?/=-]+)`, ByGroups(Operator, NameVariable), nil},
|
||||
|
||||
{`(=>|::|#\(|#\[|##|\?\?|\?=|\?|[(){}\[\],.;])`, Punctuation, nil},
|
||||
{`:=`, Operator, nil},
|
||||
{`#[tf]`, Literal, nil},
|
||||
{`#"`, LiteralStringSymbol, Push("symbol")},
|
||||
{`#[a-z0-9-]+`, Keyword, nil},
|
||||
{`#(all-keys|include|key|next|rest)`, Keyword, nil},
|
||||
{`[\w!&*<>|^$%@+~?/=-]+:`, KeywordConstant, nil},
|
||||
{`<[\w!&*<>|^$%@+~?/=-]+>`, NameClass, nil},
|
||||
{`\*[\w!&*<>|^$%@+~?/=-]+\*`, NameVariableGlobal, nil},
|
||||
{`\$[\w!&*<>|^$%@+~?/=-]+`, NameConstant, nil},
|
||||
{`(let|method|function)([ \t]+)([\w!&*<>|^$%@+~?/=-]+)`, ByGroups(NameBuiltin, Whitespace, NameVariable), nil},
|
||||
{`(error|signal|return|break)`, NameException, nil},
|
||||
{`(\\?)([\w!&*<>|^$%@+~?/=-]+)`, ByGroups(Operator, Name), nil},
|
||||
},
|
||||
"comment": {
|
||||
{`[^*/]`, CommentMultiline, nil},
|
||||
{`/\*`, CommentMultiline, Push()},
|
||||
{`\*/`, CommentMultiline, Pop(1)},
|
||||
{`[*/]`, CommentMultiline, nil},
|
||||
},
|
||||
"symbol": {
|
||||
{`"`, LiteralStringSymbol, Pop(1)},
|
||||
{`[^\\"]+`, LiteralStringSymbol, nil},
|
||||
},
|
||||
"string": {
|
||||
{`"`, LiteralString, Pop(1)},
|
||||
{`\\([\\abfnrtv"\']|x[a-f0-9]{2,4}|[0-7]{1,3})`, LiteralStringEscape, nil},
|
||||
{`[^\\"\n]+`, LiteralString, nil},
|
||||
{`\\\n`, LiteralString, nil},
|
||||
{`\\`, LiteralString, nil},
|
||||
},
|
||||
}
|
||||
},
|
||||
))
|
12
vendor/github.com/alecthomas/chroma/lexers/e/ebnf.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/e/ebnf.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Ebnf lexer.
|
||||
var Ebnf = internal.Register(MustNewLexer(
|
||||
var Ebnf = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "EBNF",
|
||||
Aliases: []string{"ebnf"},
|
||||
Filenames: []string{"*.ebnf"},
|
||||
MimeTypes: []string{"text/x-ebnf"},
|
||||
},
|
||||
Rules{
|
||||
ebnfRules,
|
||||
))
|
||||
|
||||
func ebnfRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
Include("whitespace"),
|
||||
Include("comment_start"),
|
||||
|
@ -47,5 +51,5 @@ var Ebnf = internal.Register(MustNewLexer(
|
|||
"identifier": {
|
||||
{`([a-zA-Z][\w \-]*)`, Keyword, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/e/elixir.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/e/elixir.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Elixir lexer.
|
||||
var Elixir = internal.Register(MustNewLexer(
|
||||
var Elixir = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Elixir",
|
||||
Aliases: []string{"elixir", "ex", "exs"},
|
||||
Filenames: []string{"*.ex", "*.exs"},
|
||||
MimeTypes: []string{"text/x-elixir"},
|
||||
},
|
||||
Rules{
|
||||
elixirRules,
|
||||
))
|
||||
|
||||
func elixirRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\s+`, Text, nil},
|
||||
{`#.*$`, CommentSingle, nil},
|
||||
|
@ -273,5 +277,5 @@ var Elixir = internal.Register(MustNewLexer(
|
|||
{`\\.`, LiteralStringOther, nil},
|
||||
{`'[a-zA-Z]*`, LiteralStringOther, Pop(1)},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/e/elm.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/e/elm.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Elm lexer.
|
||||
var Elm = internal.Register(MustNewLexer(
|
||||
var Elm = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Elm",
|
||||
Aliases: []string{"elm"},
|
||||
Filenames: []string{"*.elm"},
|
||||
MimeTypes: []string{"text/x-elm"},
|
||||
},
|
||||
Rules{
|
||||
elmRules,
|
||||
))
|
||||
|
||||
func elmRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\{-`, CommentMultiline, Push("comment")},
|
||||
{`--.*`, CommentSingle, nil},
|
||||
|
@ -55,5 +59,5 @@ var Elm = internal.Register(MustNewLexer(
|
|||
{`\|\]`, NameEntity, Pop(1)},
|
||||
{`.*\n`, NameEntity, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
24
vendor/github.com/alecthomas/chroma/lexers/e/emacs.go
generated
vendored
24
vendor/github.com/alecthomas/chroma/lexers/e/emacs.go
generated
vendored
|
@ -522,14 +522,24 @@ var (
|
|||
)
|
||||
|
||||
// EmacsLisp lexer.
|
||||
var EmacsLisp = internal.Register(TypeRemappingLexer(MustNewLexer(
|
||||
var EmacsLisp = internal.Register(TypeRemappingLexer(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "EmacsLisp",
|
||||
Aliases: []string{"emacs", "elisp", "emacs-lisp"},
|
||||
Filenames: []string{"*.el"},
|
||||
MimeTypes: []string{"text/x-elisp", "application/x-elisp"},
|
||||
},
|
||||
Rules{
|
||||
emacsLispRules,
|
||||
), TypeMapping{
|
||||
{NameVariable, NameFunction, emacsBuiltinFunction},
|
||||
{NameVariable, NameBuiltin, emacsSpecialForms},
|
||||
{NameVariable, NameException, emacsErrorKeywords},
|
||||
{NameVariable, NameBuiltin, append(emacsBuiltinFunctionHighlighted, emacsMacros...)},
|
||||
{NameVariable, KeywordPseudo, emacsLambdaListKeywords},
|
||||
}))
|
||||
|
||||
func emacsLispRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
Default(Push("body")),
|
||||
},
|
||||
|
@ -572,11 +582,5 @@ var EmacsLisp = internal.Register(TypeRemappingLexer(MustNewLexer(
|
|||
{`\\\n`, LiteralString, nil},
|
||||
{`"`, LiteralString, Pop(1)},
|
||||
},
|
||||
},
|
||||
), TypeMapping{
|
||||
{NameVariable, NameFunction, emacsBuiltinFunction},
|
||||
{NameVariable, NameBuiltin, emacsSpecialForms},
|
||||
{NameVariable, NameException, emacsErrorKeywords},
|
||||
{NameVariable, NameBuiltin, append(emacsBuiltinFunctionHighlighted, emacsMacros...)},
|
||||
{NameVariable, KeywordPseudo, emacsLambdaListKeywords},
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/e/erlang.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/e/erlang.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Erlang lexer.
|
||||
var Erlang = internal.Register(MustNewLexer(
|
||||
var Erlang = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Erlang",
|
||||
Aliases: []string{"erlang"},
|
||||
Filenames: []string{"*.erl", "*.hrl", "*.es", "*.escript"},
|
||||
MimeTypes: []string{"text/x-erlang"},
|
||||
},
|
||||
Rules{
|
||||
erlangRules,
|
||||
))
|
||||
|
||||
func erlangRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\s+`, Text, nil},
|
||||
{`%.*\n`, Comment, nil},
|
||||
|
@ -62,5 +66,5 @@ var Erlang = internal.Register(MustNewLexer(
|
|||
{`,`, Punctuation, Pop(1)},
|
||||
{`(?=\})`, Punctuation, Pop(1)},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/f/factor.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/f/factor.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Factor lexer.
|
||||
var Factor = internal.Register(MustNewLexer(
|
||||
var Factor = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Factor",
|
||||
Aliases: []string{"factor"},
|
||||
Filenames: []string{"*.factor"},
|
||||
MimeTypes: []string{"text/x-factor"},
|
||||
},
|
||||
Rules{
|
||||
factorRules,
|
||||
))
|
||||
|
||||
func factorRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`#!.*$`, CommentPreproc, nil},
|
||||
Default(Push("base")),
|
||||
|
@ -111,5 +115,5 @@ var Factor = internal.Register(MustNewLexer(
|
|||
{`;\s`, Keyword, Pop(1)},
|
||||
{`\S+`, NameFunction, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
55
vendor/github.com/alecthomas/chroma/lexers/f/fish.go
generated
vendored
55
vendor/github.com/alecthomas/chroma/lexers/f/fish.go
generated
vendored
|
@ -6,18 +6,43 @@ import (
|
|||
)
|
||||
|
||||
// Fish lexer.
|
||||
var Fish = internal.Register(MustNewLexer(
|
||||
var Fish = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Fish",
|
||||
Aliases: []string{"fish", "fishshell"},
|
||||
Filenames: []string{"*.fish", "*.load"},
|
||||
MimeTypes: []string{"application/x-fish"},
|
||||
},
|
||||
Rules{
|
||||
fishRules,
|
||||
))
|
||||
|
||||
func fishRules() Rules {
|
||||
keywords := []string{
|
||||
`begin`, `end`, `if`, `else`, `while`, `break`, `for`, `return`, `function`, `block`,
|
||||
`case`, `continue`, `switch`, `not`, `and`, `or`, `set`, `echo`, `exit`, `pwd`, `true`,
|
||||
`false`, `cd`, `cdh`, `count`, `test`,
|
||||
}
|
||||
keywordsPattern := Words(`\b`, `\b`, keywords...)
|
||||
|
||||
builtins := []string{
|
||||
`alias`, `bg`, `bind`, `breakpoint`, `builtin`, `argparse`, `abbr`, `string`, `command`,
|
||||
`commandline`, `complete`, `contains`, `dirh`, `dirs`, `disown`, `emit`, `eval`, `exec`,
|
||||
`fg`, `fish`, `fish_add_path`, `fish_breakpoint_prompt`, `fish_command_not_found`,
|
||||
`fish_config`, `fish_git_prompt`, `fish_greeting`, `fish_hg_prompt`, `fish_indent`,
|
||||
`fish_is_root_user`, `fish_key_reader`, `fish_mode_prompt`, `fish_opt`, `fish_pager`,
|
||||
`fish_prompt`, `fish_right_prompt`, `fish_status_to_signal`, `fish_svn_prompt`,
|
||||
`fish_title`, `fish_update_completions`, `fish_vcs_prompt`, `fishd`, `funced`,
|
||||
`funcsave`, `functions`, `help`, `history`, `isatty`, `jobs`, `math`, `mimedb`, `nextd`,
|
||||
`open`, `prompt_pwd`, `realpath`, `popd`, `prevd`, `psub`, `pushd`, `random`, `read`,
|
||||
`set_color`, `source`, `status`, `suspend`, `trap`, `type`, `ulimit`, `umask`, `vared`,
|
||||
`fc`, `getopts`, `hash`, `kill`, `printf`, `time`, `wait`,
|
||||
}
|
||||
|
||||
return Rules{
|
||||
"root": {
|
||||
Include("basic"),
|
||||
Include("data"),
|
||||
Include("interp"),
|
||||
Include("data"),
|
||||
},
|
||||
"interp": {
|
||||
{`\$\(\(`, Keyword, Push("math")},
|
||||
|
@ -25,13 +50,20 @@ var Fish = internal.Register(MustNewLexer(
|
|||
{`\$#?(\w+|.)`, NameVariable, nil},
|
||||
},
|
||||
"basic": {
|
||||
{`\b(begin|end|if|else|while|break|for|in|return|function|block|case|continue|switch|not|and|or|set|echo|exit|pwd|true|false|cd|count|test)(\s*)\b`, ByGroups(Keyword, Text), nil},
|
||||
{`\b(alias|bg|bind|breakpoint|builtin|command|commandline|complete|contains|dirh|dirs|emit|eval|exec|fg|fish|fish_config|fish_indent|fish_pager|fish_prompt|fish_right_prompt|fish_update_completions|fishd|funced|funcsave|functions|help|history|isatty|jobs|math|mimedb|nextd|open|popd|prevd|psub|pushd|random|read|set_color|source|status|trap|type|ulimit|umask|vared|fc|getopts|hash|kill|printf|time|wait)\s*\b(?!\.)`, NameBuiltin, nil},
|
||||
{Words(`(?<=(?:^|\A|;|&&|\|\||\||`+keywordsPattern+`)\s*)`, `(?=;?\b)`, keywords...), Keyword, nil},
|
||||
{`(?<=for\s+\S+\s+)in\b`, Keyword, nil},
|
||||
{Words(`\b`, `\s*\b(?!\.)`, builtins...), NameBuiltin, nil},
|
||||
{`#!.*\n`, CommentHashbang, nil},
|
||||
{`#.*\n`, Comment, nil},
|
||||
{`\\[\w\W]`, LiteralStringEscape, nil},
|
||||
{`(\b\w+)(\s*)(=)`, ByGroups(NameVariable, Text, Operator), nil},
|
||||
{`[\[\]()=]`, Operator, nil},
|
||||
{`[\[\]()={}]`, Operator, nil},
|
||||
{`(?<=\[[^\]]+)\.\.|-(?=[^\[]+\])`, Operator, nil},
|
||||
{`<<-?\s*(\'?)\\?(\w+)[\w\W]+?\2`, LiteralString, nil},
|
||||
{`(?<=set\s+(?:--?[^\d\W][\w-]*\s+)?)\w+`, NameVariable, nil},
|
||||
{`(?<=for\s+)\w[\w-]*(?=\s+in)`, NameVariable, nil},
|
||||
{`(?<=function\s+)\w(?:[^\n])*?(?= *[-\n])`, NameFunction, nil},
|
||||
{`(?<=(?:^|\b(?:and|or|sudo)\b|;|\|\||&&|\||\(|(?:\b\w+\s*=\S+\s)) *)\w[\w-]*`, NameFunction, nil},
|
||||
},
|
||||
"data": {
|
||||
{`(?s)\$?"(\\\\|\\[0-7]+|\\.|[^"\\$])*"`, LiteralStringDouble, nil},
|
||||
|
@ -39,10 +71,11 @@ var Fish = internal.Register(MustNewLexer(
|
|||
{`(?s)\$'(\\\\|\\[0-7]+|\\.|[^'\\])*'`, LiteralStringSingle, nil},
|
||||
{`(?s)'.*?'`, LiteralStringSingle, nil},
|
||||
{`;`, Punctuation, nil},
|
||||
{`&|\||\^|<|>`, Operator, nil},
|
||||
{`&&|\|\||&|\||\^|<|>`, Operator, nil},
|
||||
{`\s+`, Text, nil},
|
||||
{`\d+(?= |\Z)`, LiteralNumber, nil},
|
||||
{"[^=\\s\\[\\]{}()$\"\\'`\\\\<&|;]+", Text, nil},
|
||||
{`\b\d+\b`, LiteralNumber, nil},
|
||||
{`--?[^\d][\w-]*`, NameAttribute, nil},
|
||||
{".+?", Text, nil},
|
||||
},
|
||||
"string": {
|
||||
{`"`, LiteralStringDouble, Pop(1)},
|
||||
|
@ -61,5 +94,5 @@ var Fish = internal.Register(MustNewLexer(
|
|||
{`\d+`, LiteralNumber, nil},
|
||||
Include("root"),
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/f/forth.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/f/forth.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Forth lexer.
|
||||
var Forth = internal.Register(MustNewLexer(
|
||||
var Forth = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Forth",
|
||||
Aliases: []string{"forth"},
|
||||
|
@ -14,7 +14,11 @@ var Forth = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"application/x-forth"},
|
||||
CaseInsensitive: true,
|
||||
},
|
||||
Rules{
|
||||
forthRules,
|
||||
))
|
||||
|
||||
func forthRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\s+`, Text, nil},
|
||||
{`\\.*?\n`, CommentSingle, nil},
|
||||
|
@ -36,5 +40,5 @@ var Forth = internal.Register(MustNewLexer(
|
|||
"stringdef": {
|
||||
{`[^"]+`, LiteralString, Pop(1)},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/f/fortran.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/f/fortran.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Fortran lexer.
|
||||
var Fortran = internal.Register(MustNewLexer(
|
||||
var Fortran = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Fortran",
|
||||
Aliases: []string{"fortran"},
|
||||
|
@ -14,7 +14,11 @@ var Fortran = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"text/x-fortran"},
|
||||
CaseInsensitive: true,
|
||||
},
|
||||
Rules{
|
||||
fortranRules,
|
||||
))
|
||||
|
||||
func fortranRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`^#.*\n`, CommentPreproc, nil},
|
||||
{`!.*\n`, Comment, nil},
|
||||
|
@ -43,5 +47,5 @@ var Fortran = internal.Register(MustNewLexer(
|
|||
{`[+-]?\d*\.\d+([ed][-+]?\d+)?(_[a-z]\w+)?`, LiteralNumberFloat, nil},
|
||||
{`[+-]?\d+\.\d*([ed][-+]?\d+)?(_[a-z]\w+)?`, LiteralNumberFloat, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
39
vendor/github.com/alecthomas/chroma/lexers/f/fortran_fixed.go
generated
vendored
Normal file
39
vendor/github.com/alecthomas/chroma/lexers/f/fortran_fixed.go
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
package f
|
||||
|
||||
import (
|
||||
. "github.com/alecthomas/chroma" // nolint
|
||||
"github.com/alecthomas/chroma/lexers/internal"
|
||||
)
|
||||
|
||||
// FortranFixed lexer.
|
||||
var FortranFixed = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "FortranFixed",
|
||||
Aliases: []string{"fortranfixed"},
|
||||
Filenames: []string{"*.f", "*.F"},
|
||||
MimeTypes: []string{"text/x-fortran"},
|
||||
NotMultiline: true,
|
||||
CaseInsensitive: true,
|
||||
},
|
||||
func() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`[C*].*\n`, Comment, nil},
|
||||
{`#.*\n`, CommentPreproc, nil},
|
||||
{`[\t ]*!.*\n`, Comment, nil},
|
||||
{`(.{5})`, NameLabel, Push("cont-char")},
|
||||
{`.*\n`, Using(Fortran), nil},
|
||||
},
|
||||
"cont-char": {
|
||||
{` `, Text, Push("code")},
|
||||
{`0`, Comment, Push("code")},
|
||||
{`.`, GenericStrong, Push("code")},
|
||||
},
|
||||
"code": {
|
||||
{`(.{66})(.*)(\n)`, ByGroups(Using(Fortran), Comment, Text), Push("root")},
|
||||
{`.*\n`, Using(Fortran), Push("root")},
|
||||
Default(Push("root")),
|
||||
},
|
||||
}
|
||||
},
|
||||
))
|
12
vendor/github.com/alecthomas/chroma/lexers/f/fsharp.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/f/fsharp.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Fsharp lexer.
|
||||
var Fsharp = internal.Register(MustNewLexer(
|
||||
var Fsharp = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "FSharp",
|
||||
Aliases: []string{"fsharp"},
|
||||
Filenames: []string{"*.fs", "*.fsi"},
|
||||
MimeTypes: []string{"text/x-fsharp"},
|
||||
},
|
||||
Rules{
|
||||
fsharpRules,
|
||||
))
|
||||
|
||||
func fsharpRules() Rules {
|
||||
return Rules{
|
||||
"escape-sequence": {
|
||||
{`\\[\\"\'ntbrafv]`, LiteralStringEscape, nil},
|
||||
{`\\[0-9]{3}`, LiteralStringEscape, nil},
|
||||
|
@ -90,5 +94,5 @@ var Fsharp = internal.Register(MustNewLexer(
|
|||
{`"""B?`, LiteralString, Pop(1)},
|
||||
{`"`, LiteralString, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/g/gas.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/g/gas.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Gas lexer.
|
||||
var Gas = internal.Register(MustNewLexer(
|
||||
var Gas = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "GAS",
|
||||
Aliases: []string{"gas", "asm"},
|
||||
Filenames: []string{"*.s", "*.S"},
|
||||
MimeTypes: []string{"text/x-gas"},
|
||||
},
|
||||
Rules{
|
||||
gasRules,
|
||||
))
|
||||
|
||||
func gasRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
Include("whitespace"),
|
||||
{`(?:[a-zA-Z$_][\w$.@-]*|\.[\w$.@-]+):`, NameLabel, nil},
|
||||
|
@ -51,5 +55,5 @@ var Gas = internal.Register(MustNewLexer(
|
|||
"punctuation": {
|
||||
{`[-*,.()\[\]!:]+`, Punctuation, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/g/gdscript.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/g/gdscript.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// GDScript lexer.
|
||||
var GDScript = internal.Register(MustNewLexer(
|
||||
var GDScript = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "GDScript",
|
||||
Aliases: []string{"gdscript", "gd"},
|
||||
Filenames: []string{"*.gd"},
|
||||
MimeTypes: []string{"text/x-gdscript", "application/x-gdscript"},
|
||||
},
|
||||
Rules{
|
||||
gdscriptRules,
|
||||
))
|
||||
|
||||
func gdscriptRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\n`, Text, nil},
|
||||
{`^(\s*)([rRuUbB]{,2})("""(?:.|\n)*?""")`, ByGroups(Text, LiteralStringAffix, LiteralStringDoc), nil},
|
||||
|
@ -120,5 +124,5 @@ var GDScript = internal.Register(MustNewLexer(
|
|||
Include("strings-single"),
|
||||
{`\n`, LiteralStringSingle, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
116
vendor/github.com/alecthomas/chroma/lexers/g/genshi.go
generated
vendored
116
vendor/github.com/alecthomas/chroma/lexers/g/genshi.go
generated
vendored
|
@ -7,14 +7,18 @@ import (
|
|||
)
|
||||
|
||||
// Genshi Text lexer.
|
||||
var GenshiText = internal.Register(MustNewLexer(
|
||||
var GenshiText = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Genshi Text",
|
||||
Aliases: []string{"genshitext"},
|
||||
Filenames: []string{},
|
||||
MimeTypes: []string{"application/x-genshi-text", "text/x-genshi"},
|
||||
},
|
||||
Rules{
|
||||
genshiTextRules,
|
||||
))
|
||||
|
||||
func genshiTextRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`[^#$\s]+`, Other, nil},
|
||||
{`^(\s*)(##.*)$`, ByGroups(Text, Comment), nil},
|
||||
|
@ -33,11 +37,11 @@ var GenshiText = internal.Register(MustNewLexer(
|
|||
{`(?<!\$)(\$\{)(.+?)(\})`, ByGroups(CommentPreproc, Using(Python), CommentPreproc), nil},
|
||||
{`(?<!\$)(\$)([a-zA-Z_][\w.]*)`, NameVariable, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// Html+Genshi lexer.
|
||||
var GenshiHTMLTemplate = internal.Register(MustNewLexer(
|
||||
var GenshiHTMLTemplate = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Genshi HTML",
|
||||
Aliases: []string{"html+genshi", "html+kid"},
|
||||
|
@ -50,7 +54,7 @@ var GenshiHTMLTemplate = internal.Register(MustNewLexer(
|
|||
))
|
||||
|
||||
// Genshi lexer.
|
||||
var Genshi = internal.Register(MustNewLexer(
|
||||
var Genshi = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Genshi",
|
||||
Aliases: []string{"genshi", "kid", "xml+genshi", "xml+kid"},
|
||||
|
@ -62,53 +66,55 @@ var Genshi = internal.Register(MustNewLexer(
|
|||
genshiMarkupRules,
|
||||
))
|
||||
|
||||
var genshiMarkupRules = Rules{
|
||||
"root": {
|
||||
{`[^<$]+`, Other, nil},
|
||||
{`(<\?python)(.*?)(\?>)`, ByGroups(CommentPreproc, Using(Python), CommentPreproc), nil},
|
||||
{`<\s*(script|style)\s*.*?>.*?<\s*/\1\s*>`, Other, nil},
|
||||
{`<\s*py:[a-zA-Z0-9]+`, NameTag, Push("pytag")},
|
||||
{`<\s*[a-zA-Z0-9:.]+`, NameTag, Push("tag")},
|
||||
Include("variable"),
|
||||
{`[<$]`, Other, nil},
|
||||
},
|
||||
"pytag": {
|
||||
{`\s+`, Text, nil},
|
||||
{`[\w:-]+\s*=`, NameAttribute, Push("pyattr")},
|
||||
{`/?\s*>`, NameTag, Pop(1)},
|
||||
},
|
||||
"pyattr": {
|
||||
{`(")(.*?)(")`, ByGroups(LiteralString, Using(Python), LiteralString), Pop(1)},
|
||||
{`(')(.*?)(')`, ByGroups(LiteralString, Using(Python), LiteralString), Pop(1)},
|
||||
{`[^\s>]+`, LiteralString, Pop(1)},
|
||||
},
|
||||
"tag": {
|
||||
{`\s+`, Text, nil},
|
||||
{`py:[\w-]+\s*=`, NameAttribute, Push("pyattr")},
|
||||
{`[\w:-]+\s*=`, NameAttribute, Push("attr")},
|
||||
{`/?\s*>`, NameTag, Pop(1)},
|
||||
},
|
||||
"attr": {
|
||||
{`"`, LiteralString, Push("attr-dstring")},
|
||||
{`'`, LiteralString, Push("attr-sstring")},
|
||||
{`[^\s>]*`, LiteralString, Pop(1)},
|
||||
},
|
||||
"attr-dstring": {
|
||||
{`"`, LiteralString, Pop(1)},
|
||||
Include("strings"),
|
||||
{`'`, LiteralString, nil},
|
||||
},
|
||||
"attr-sstring": {
|
||||
{`'`, LiteralString, Pop(1)},
|
||||
Include("strings"),
|
||||
{`'`, LiteralString, nil},
|
||||
},
|
||||
"strings": {
|
||||
{`[^"'$]+`, LiteralString, nil},
|
||||
Include("variable"),
|
||||
},
|
||||
"variable": {
|
||||
{`(?<!\$)(\$\{)(.+?)(\})`, ByGroups(CommentPreproc, Using(Python), CommentPreproc), nil},
|
||||
{`(?<!\$)(\$)([a-zA-Z_][\w\.]*)`, NameVariable, nil},
|
||||
},
|
||||
func genshiMarkupRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`[^<$]+`, Other, nil},
|
||||
{`(<\?python)(.*?)(\?>)`, ByGroups(CommentPreproc, Using(Python), CommentPreproc), nil},
|
||||
{`<\s*(script|style)\s*.*?>.*?<\s*/\1\s*>`, Other, nil},
|
||||
{`<\s*py:[a-zA-Z0-9]+`, NameTag, Push("pytag")},
|
||||
{`<\s*[a-zA-Z0-9:.]+`, NameTag, Push("tag")},
|
||||
Include("variable"),
|
||||
{`[<$]`, Other, nil},
|
||||
},
|
||||
"pytag": {
|
||||
{`\s+`, Text, nil},
|
||||
{`[\w:-]+\s*=`, NameAttribute, Push("pyattr")},
|
||||
{`/?\s*>`, NameTag, Pop(1)},
|
||||
},
|
||||
"pyattr": {
|
||||
{`(")(.*?)(")`, ByGroups(LiteralString, Using(Python), LiteralString), Pop(1)},
|
||||
{`(')(.*?)(')`, ByGroups(LiteralString, Using(Python), LiteralString), Pop(1)},
|
||||
{`[^\s>]+`, LiteralString, Pop(1)},
|
||||
},
|
||||
"tag": {
|
||||
{`\s+`, Text, nil},
|
||||
{`py:[\w-]+\s*=`, NameAttribute, Push("pyattr")},
|
||||
{`[\w:-]+\s*=`, NameAttribute, Push("attr")},
|
||||
{`/?\s*>`, NameTag, Pop(1)},
|
||||
},
|
||||
"attr": {
|
||||
{`"`, LiteralString, Push("attr-dstring")},
|
||||
{`'`, LiteralString, Push("attr-sstring")},
|
||||
{`[^\s>]*`, LiteralString, Pop(1)},
|
||||
},
|
||||
"attr-dstring": {
|
||||
{`"`, LiteralString, Pop(1)},
|
||||
Include("strings"),
|
||||
{`'`, LiteralString, nil},
|
||||
},
|
||||
"attr-sstring": {
|
||||
{`'`, LiteralString, Pop(1)},
|
||||
Include("strings"),
|
||||
{`'`, LiteralString, nil},
|
||||
},
|
||||
"strings": {
|
||||
{`[^"'$]+`, LiteralString, nil},
|
||||
Include("variable"),
|
||||
},
|
||||
"variable": {
|
||||
{`(?<!\$)(\$\{)(.+?)(\})`, ByGroups(CommentPreproc, Using(Python), CommentPreproc), nil},
|
||||
{`(?<!\$)(\$)([a-zA-Z_][\w\.]*)`, NameVariable, nil},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
28
vendor/github.com/alecthomas/chroma/lexers/g/gherkin.go
generated
vendored
28
vendor/github.com/alecthomas/chroma/lexers/g/gherkin.go
generated
vendored
|
@ -5,23 +5,27 @@ import (
|
|||
"github.com/alecthomas/chroma/lexers/internal"
|
||||
)
|
||||
|
||||
var stepKeywords = `^(\s*)(하지만|조건|먼저|만일|만약|단|그리고|그러면|那麼|那么|而且|當|当|前提|假設|假设|假如|假定|但是|但し|並且|并且|同時|同时|もし|ならば|ただし|しかし|かつ|و |متى |لكن |عندما |ثم |بفرض |اذاً |כאשר |וגם |בהינתן |אזי |אז |אבל |Якщо |Унда |То |Припустимо, що |Припустимо |Онда |Но |Нехай |Лекин |Когато |Када |Кад |К тому же |И |Задато |Задати |Задате |Если |Допустим |Дадено |Ва |Бирок |Аммо |Али |Але |Агар |А |І |Și |És |Zatati |Zakładając |Zadato |Zadate |Zadano |Zadani |Zadan |Youse know when youse got |Youse know like when |Yna |Ya know how |Ya gotta |Y |Wun |Wtedy |When y'all |When |Wenn |WEN |Và |Ve |Und |Un |Thì |Then y'all |Then |Tapi |Tak |Tada |Tad |Så |Stel |Soit |Siis |Si |Sed |Se |Quando |Quand |Quan |Pryd |Pokud |Pokiaľ |Però |Pero |Pak |Oraz |Onda |Ond |Oletetaan |Og |Och |O zaman |Når |När |Niin |Nhưng |N |Mutta |Men |Mas |Maka |Majd |Mais |Maar |Ma |Lorsque |Lorsqu'|Kun |Kuid |Kui |Khi |Keď |Ketika |Když |Kaj |Kai |Kada |Kad |Jeżeli |Ja |Ir |I CAN HAZ |I |Ha |Givun |Givet |Given y'all |Given |Gitt |Gegeven |Gegeben sei |Fakat |Eğer ki |Etant donné |Et |Então |Entonces |Entao |En |Eeldades |E |Duota |Dun |Donitaĵo |Donat |Donada |Do |Diyelim ki |Dengan |Den youse gotta |De |Dato |Dar |Dann |Dan |Dado |Dacă |Daca |DEN |Când |Cuando |Cho |Cept |Cand |Cal |But y'all |But |Buh |Biết |Bet |BUT |Atès |Atunci |Atesa |Anrhegedig a |Angenommen |And y'all |And |An |Ama |Als |Alors |Allora |Ali |Aleshores |Ale |Akkor |Aber |AN |A také |A |\* )`
|
||||
|
||||
var featureKeywords = `^(기능|機能|功能|フィーチャ|خاصية|תכונה|Функціонал|Функционалност|Функционал|Фича|Особина|Могућност|Özellik|Właściwość|Tính năng|Trajto|Savybė|Požiadavka|Požadavek|Osobina|Ominaisuus|Omadus|OH HAI|Mogućnost|Mogucnost|Jellemző|Fīča|Funzionalità|Funktionalität|Funkcionalnost|Funkcionalitāte|Funcționalitate|Functionaliteit|Functionalitate|Funcionalitat|Funcionalidade|Fonctionnalité|Fitur|Feature|Egenskap|Egenskab|Crikey|Característica|Arwedd)(:)(.*)$`
|
||||
|
||||
var featureElementKeywords = `^(\s*)(시나리오 개요|시나리오|배경|背景|場景大綱|場景|场景大纲|场景|劇本大綱|劇本|剧本大纲|剧本|テンプレ|シナリオテンプレート|シナリオテンプレ|シナリオアウトライン|シナリオ|سيناريو مخطط|سيناريو|الخلفية|תרחיש|תבנית תרחיש|רקע|Тарих|Сценарій|Сценарио|Сценарий структураси|Сценарий|Структура сценарію|Структура сценарија|Структура сценария|Скица|Рамка на сценарий|Пример|Предыстория|Предистория|Позадина|Передумова|Основа|Концепт|Контекст|Założenia|Wharrimean is|Tình huống|The thing of it is|Tausta|Taust|Tapausaihio|Tapaus|Szenariogrundriss|Szenario|Szablon scenariusza|Stsenaarium|Struktura scenarija|Skica|Skenario konsep|Skenario|Situācija|Senaryo taslağı|Senaryo|Scénář|Scénario|Schema dello scenario|Scenārijs pēc parauga|Scenārijs|Scenár|Scenaro|Scenariusz|Scenariul de şablon|Scenariul de sablon|Scenariu|Scenario Outline|Scenario Amlinellol|Scenario|Scenarijus|Scenarijaus šablonas|Scenarij|Scenarie|Rerefons|Raamstsenaarium|Primer|Pozadí|Pozadina|Pozadie|Plan du scénario|Plan du Scénario|Osnova scénáře|Osnova|Náčrt Scénáře|Náčrt Scenáru|Mate|MISHUN SRSLY|MISHUN|Kịch bản|Konturo de la scenaro|Kontext|Konteksts|Kontekstas|Kontekst|Koncept|Khung tình huống|Khung kịch bản|Háttér|Grundlage|Geçmiş|Forgatókönyv vázlat|Forgatókönyv|Fono|Esquema do Cenário|Esquema do Cenario|Esquema del escenario|Esquema de l'escenari|Escenario|Escenari|Dis is what went down|Dasar|Contexto|Contexte|Contesto|Condiţii|Conditii|Cenário|Cenario|Cefndir|Bối cảnh|Blokes|Bakgrunn|Bakgrund|Baggrund|Background|B4|Antecedents|Antecedentes|All y'all|Achtergrond|Abstrakt Scenario|Abstract Scenario)(:)(.*)$`
|
||||
|
||||
var examplesKeywords = `^(\s*)(예|例子|例|サンプル|امثلة|דוגמאות|Сценарији|Примери|Приклади|Мисоллар|Значения|Örnekler|Voorbeelden|Variantai|Tapaukset|Scenarios|Scenariji|Scenarijai|Příklady|Példák|Príklady|Przykłady|Primjeri|Primeri|Piemēri|Pavyzdžiai|Paraugs|Juhtumid|Exemplos|Exemples|Exemplele|Exempel|Examples|Esempi|Enghreifftiau|Ekzemploj|Eksempler|Ejemplos|EXAMPLZ|Dữ liệu|Contoh|Cobber|Beispiele)(:)(.*)$`
|
||||
|
||||
// Gherkin lexer.
|
||||
var Gherkin = internal.Register(MustNewLexer(
|
||||
var Gherkin = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Gherkin",
|
||||
Aliases: []string{"cucumber", "Cucumber", "gherkin", "Gherkin"},
|
||||
Filenames: []string{"*.feature", "*.FEATURE"},
|
||||
MimeTypes: []string{"text/x-gherkin"},
|
||||
},
|
||||
Rules{
|
||||
gherkinRules,
|
||||
))
|
||||
|
||||
func gherkinRules() Rules {
|
||||
stepKeywords := `^(\s*)(하지만|조건|먼저|만일|만약|단|그리고|그러면|那麼|那么|而且|當|当|前提|假設|假设|假如|假定|但是|但し|並且|并且|同時|同时|もし|ならば|ただし|しかし|かつ|و |متى |لكن |عندما |ثم |بفرض |اذاً |כאשר |וגם |בהינתן |אזי |אז |אבל |Якщо |Унда |То |Припустимо, що |Припустимо |Онда |Но |Нехай |Лекин |Когато |Када |Кад |К тому же |И |Задато |Задати |Задате |Если |Допустим |Дадено |Ва |Бирок |Аммо |Али |Але |Агар |А |І |Și |És |Zatati |Zakładając |Zadato |Zadate |Zadano |Zadani |Zadan |Youse know when youse got |Youse know like when |Yna |Ya know how |Ya gotta |Y |Wun |Wtedy |When y'all |When |Wenn |WEN |Và |Ve |Und |Un |Thì |Then y'all |Then |Tapi |Tak |Tada |Tad |Så |Stel |Soit |Siis |Si |Sed |Se |Quando |Quand |Quan |Pryd |Pokud |Pokiaľ |Però |Pero |Pak |Oraz |Onda |Ond |Oletetaan |Og |Och |O zaman |Når |När |Niin |Nhưng |N |Mutta |Men |Mas |Maka |Majd |Mais |Maar |Ma |Lorsque |Lorsqu'|Kun |Kuid |Kui |Khi |Keď |Ketika |Když |Kaj |Kai |Kada |Kad |Jeżeli |Ja |Ir |I CAN HAZ |I |Ha |Givun |Givet |Given y'all |Given |Gitt |Gegeven |Gegeben sei |Fakat |Eğer ki |Etant donné |Et |Então |Entonces |Entao |En |Eeldades |E |Duota |Dun |Donitaĵo |Donat |Donada |Do |Diyelim ki |Dengan |Den youse gotta |De |Dato |Dar |Dann |Dan |Dado |Dacă |Daca |DEN |Când |Cuando |Cho |Cept |Cand |Cal |But y'all |But |Buh |Biết |Bet |BUT |Atès |Atunci |Atesa |Anrhegedig a |Angenommen |And y'all |And |An |Ama |Als |Alors |Allora |Ali |Aleshores |Ale |Akkor |Aber |AN |A také |A |\* )`
|
||||
|
||||
featureKeywords := `^(기능|機能|功能|フィーチャ|خاصية|תכונה|Функціонал|Функционалност|Функционал|Фича|Особина|Могућност|Özellik|Właściwość|Tính năng|Trajto|Savybė|Požiadavka|Požadavek|Osobina|Ominaisuus|Omadus|OH HAI|Mogućnost|Mogucnost|Jellemző|Fīča|Funzionalità|Funktionalität|Funkcionalnost|Funkcionalitāte|Funcționalitate|Functionaliteit|Functionalitate|Funcionalitat|Funcionalidade|Fonctionnalité|Fitur|Feature|Egenskap|Egenskab|Crikey|Característica|Arwedd)(:)(.*)$`
|
||||
|
||||
featureElementKeywords := `^(\s*)(시나리오 개요|시나리오|배경|背景|場景大綱|場景|场景大纲|场景|劇本大綱|劇本|剧本大纲|剧本|テンプレ|シナリオテンプレート|シナリオテンプレ|シナリオアウトライン|シナリオ|سيناريو مخطط|سيناريو|الخلفية|תרחיש|תבנית תרחיש|רקע|Тарих|Сценарій|Сценарио|Сценарий структураси|Сценарий|Структура сценарію|Структура сценарија|Структура сценария|Скица|Рамка на сценарий|Пример|Предыстория|Предистория|Позадина|Передумова|Основа|Концепт|Контекст|Założenia|Wharrimean is|Tình huống|The thing of it is|Tausta|Taust|Tapausaihio|Tapaus|Szenariogrundriss|Szenario|Szablon scenariusza|Stsenaarium|Struktura scenarija|Skica|Skenario konsep|Skenario|Situācija|Senaryo taslağı|Senaryo|Scénář|Scénario|Schema dello scenario|Scenārijs pēc parauga|Scenārijs|Scenár|Scenaro|Scenariusz|Scenariul de şablon|Scenariul de sablon|Scenariu|Scenario Outline|Scenario Amlinellol|Scenario|Scenarijus|Scenarijaus šablonas|Scenarij|Scenarie|Rerefons|Raamstsenaarium|Primer|Pozadí|Pozadina|Pozadie|Plan du scénario|Plan du Scénario|Osnova scénáře|Osnova|Náčrt Scénáře|Náčrt Scenáru|Mate|MISHUN SRSLY|MISHUN|Kịch bản|Konturo de la scenaro|Kontext|Konteksts|Kontekstas|Kontekst|Koncept|Khung tình huống|Khung kịch bản|Háttér|Grundlage|Geçmiş|Forgatókönyv vázlat|Forgatókönyv|Fono|Esquema do Cenário|Esquema do Cenario|Esquema del escenario|Esquema de l'escenari|Escenario|Escenari|Dis is what went down|Dasar|Contexto|Contexte|Contesto|Condiţii|Conditii|Cenário|Cenario|Cefndir|Bối cảnh|Blokes|Bakgrunn|Bakgrund|Baggrund|Background|B4|Antecedents|Antecedentes|All y'all|Achtergrond|Abstrakt Scenario|Abstract Scenario)(:)(.*)$`
|
||||
|
||||
examplesKeywords := `^(\s*)(예|例子|例|サンプル|امثلة|דוגמאות|Сценарији|Примери|Приклади|Мисоллар|Значения|Örnekler|Voorbeelden|Variantai|Tapaukset|Scenarios|Scenariji|Scenarijai|Příklady|Példák|Príklady|Przykłady|Primjeri|Primeri|Piemēri|Pavyzdžiai|Paraugs|Juhtumid|Exemplos|Exemples|Exemplele|Exempel|Examples|Esempi|Enghreifftiau|Ekzemploj|Eksempler|Ejemplos|EXAMPLZ|Dữ liệu|Contoh|Cobber|Beispiele)(:)(.*)$`
|
||||
|
||||
return Rules{
|
||||
"comments": {
|
||||
{`\s*#.*$`, Comment, nil},
|
||||
},
|
||||
|
@ -114,5 +118,5 @@ var Gherkin = internal.Register(MustNewLexer(
|
|||
{examplesKeywords, ByGroups(NameFunction, Keyword, Keyword, NameFunction), Push("examplesTable")},
|
||||
{`(\s|.)`, NameFunction, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/g/glsl.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/g/glsl.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// GLSL lexer.
|
||||
var GLSL = internal.Register(MustNewLexer(
|
||||
var GLSL = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "GLSL",
|
||||
Aliases: []string{"glsl"},
|
||||
Filenames: []string{"*.vert", "*.frag", "*.geo"},
|
||||
MimeTypes: []string{"text/x-glslsrc"},
|
||||
},
|
||||
Rules{
|
||||
glslRules,
|
||||
))
|
||||
|
||||
func glslRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`^#.*`, CommentPreproc, nil},
|
||||
{`//.*`, CommentSingle, nil},
|
||||
|
@ -33,5 +37,5 @@ var GLSL = internal.Register(MustNewLexer(
|
|||
{`\.`, Punctuation, nil},
|
||||
{`\s+`, Text, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/g/gnuplot.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/g/gnuplot.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Gnuplot lexer.
|
||||
var Gnuplot = internal.Register(MustNewLexer(
|
||||
var Gnuplot = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Gnuplot",
|
||||
Aliases: []string{"gnuplot"},
|
||||
Filenames: []string{"*.plot", "*.plt"},
|
||||
MimeTypes: []string{"text/x-gnuplot"},
|
||||
},
|
||||
Rules{
|
||||
gnuplotRules,
|
||||
))
|
||||
|
||||
func gnuplotRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
Include("whitespace"),
|
||||
{`bind\b|bin\b|bi\b`, Keyword, Push("bind")},
|
||||
|
@ -113,5 +117,5 @@ var Gnuplot = internal.Register(MustNewLexer(
|
|||
{`functions\b|function\b|functio\b|functi\b|funct\b|func\b|fun\b|fu\b|f\b|set\b|se\b|s\b|terminal\b|termina\b|termin\b|termi\b|term\b|ter\b|te\b|t\b|variables\b|variable\b|variabl\b|variab\b|varia\b|vari\b|var\b|va\b|v\b`, NameBuiltin, nil},
|
||||
Include("genericargs"),
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
114
vendor/github.com/alecthomas/chroma/lexers/g/go.go
generated
vendored
114
vendor/github.com/alecthomas/chroma/lexers/g/go.go
generated
vendored
|
@ -9,7 +9,7 @@ import (
|
|||
)
|
||||
|
||||
// Go lexer.
|
||||
var Go = internal.Register(MustNewLexer(
|
||||
var Go = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Go",
|
||||
Aliases: []string{"go", "golang"},
|
||||
|
@ -17,7 +17,19 @@ var Go = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"text/x-gosrc"},
|
||||
EnsureNL: true,
|
||||
},
|
||||
Rules{
|
||||
goRules,
|
||||
).SetAnalyser(func(text string) float32 {
|
||||
if strings.Contains(text, "fmt.") && strings.Contains(text, "package ") {
|
||||
return 0.5
|
||||
}
|
||||
if strings.Contains(text, "package ") {
|
||||
return 0.1
|
||||
}
|
||||
return 0.0
|
||||
}))
|
||||
|
||||
func goRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\n`, Text, nil},
|
||||
{`\s+`, Text, nil},
|
||||
|
@ -37,8 +49,8 @@ var Go = internal.Register(MustNewLexer(
|
|||
{`\d+(\.\d+[eE][+\-]?\d+|\.\d*|[eE][+\-]?\d+)`, LiteralNumberFloat, nil},
|
||||
{`\.\d+([eE][+\-]?\d+)?`, LiteralNumberFloat, nil},
|
||||
{`0[0-7]+`, LiteralNumberOct, nil},
|
||||
{`0[xX][0-9a-fA-F]+`, LiteralNumberHex, nil},
|
||||
{`(0|[1-9][0-9]*)`, LiteralNumberInteger, nil},
|
||||
{`0[xX][0-9a-fA-F_]+`, LiteralNumberHex, nil},
|
||||
{`(0|[1-9][0-9_]*)`, LiteralNumberInteger, nil},
|
||||
{`'(\\['"\\abfnrtv]|\\x[0-9a-fA-F]{2}|\\[0-7]{1,3}|\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}|[^\\])'`, LiteralStringChar, nil},
|
||||
{"(`)([^`]*)(`)", ByGroups(LiteralString, Using(TypeRemappingLexer(GoTextTemplate, TypeMapping{{Other, LiteralString, nil}})), LiteralString), nil},
|
||||
{`"(\\\\|\\"|[^"])*"`, LiteralString, nil},
|
||||
|
@ -47,58 +59,52 @@ var Go = internal.Register(MustNewLexer(
|
|||
{`[|^<>=!()\[\]{}.,;:]`, Punctuation, nil},
|
||||
{`[^\W\d]\w*`, NameOther, nil},
|
||||
},
|
||||
},
|
||||
).SetAnalyser(func(text string) float32 {
|
||||
if strings.Contains(text, "fmt.") && strings.Contains(text, "package ") {
|
||||
return 0.5
|
||||
}
|
||||
if strings.Contains(text, "package ") {
|
||||
return 0.1
|
||||
}
|
||||
return 0.0
|
||||
}))
|
||||
|
||||
var goTemplateRules = Rules{
|
||||
"root": {
|
||||
{`{{[-]?`, CommentPreproc, Push("template")},
|
||||
{`[^{]+`, Other, nil},
|
||||
{`{`, Other, nil},
|
||||
},
|
||||
"template": {
|
||||
{`[-]?}}`, CommentPreproc, Pop(1)},
|
||||
{`/\*.*?\*/`, Comment, nil},
|
||||
{`(?=}})`, CommentPreproc, Pop(1)}, // Terminate the pipeline
|
||||
{`\(`, Operator, Push("subexpression")},
|
||||
{`"(\\\\|\\"|[^"])*"`, LiteralString, nil},
|
||||
Include("expression"),
|
||||
},
|
||||
"subexpression": {
|
||||
{`\)`, Operator, Pop(1)},
|
||||
Include("expression"),
|
||||
},
|
||||
"expression": {
|
||||
{`\s+`, Whitespace, nil},
|
||||
{`\(`, Operator, Push("subexpression")},
|
||||
{`(range|if|else|while|with|template|end|true|false|nil|and|call|html|index|js|len|not|or|print|printf|println|urlquery|eq|ne|lt|le|gt|ge)\b`, Keyword, nil},
|
||||
{`\||:=`, Operator, nil},
|
||||
{`[$]?[^\W\d]\w*`, NameOther, nil},
|
||||
{`[$]?\.(?:[^\W\d]\w*)?`, NameAttribute, nil},
|
||||
{`"(\\\\|\\"|[^"])*"`, LiteralString, nil},
|
||||
{`\d+i`, LiteralNumber, nil},
|
||||
{`\d+\.\d*([Ee][-+]\d+)?i`, LiteralNumber, nil},
|
||||
{`\.\d+([Ee][-+]\d+)?i`, LiteralNumber, nil},
|
||||
{`\d+[Ee][-+]\d+i`, LiteralNumber, nil},
|
||||
{`\d+(\.\d+[eE][+\-]?\d+|\.\d*|[eE][+\-]?\d+)`, LiteralNumberFloat, nil},
|
||||
{`\.\d+([eE][+\-]?\d+)?`, LiteralNumberFloat, nil},
|
||||
{`0[0-7]+`, LiteralNumberOct, nil},
|
||||
{`0[xX][0-9a-fA-F]+`, LiteralNumberHex, nil},
|
||||
{`(0|[1-9][0-9]*)`, LiteralNumberInteger, nil},
|
||||
{`'(\\['"\\abfnrtv]|\\x[0-9a-fA-F]{2}|\\[0-7]{1,3}|\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}|[^\\])'`, LiteralStringChar, nil},
|
||||
{"`[^`]*`", LiteralString, nil},
|
||||
},
|
||||
}
|
||||
|
||||
var GoHTMLTemplate = internal.Register(DelegatingLexer(h.HTML, MustNewLexer(
|
||||
func goTemplateRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`{{(- )?/\*(.|\n)*?\*/( -)?}}`, CommentMultiline, nil},
|
||||
{`{{[-]?`, CommentPreproc, Push("template")},
|
||||
{`[^{]+`, Other, nil},
|
||||
{`{`, Other, nil},
|
||||
},
|
||||
"template": {
|
||||
{`[-]?}}`, CommentPreproc, Pop(1)},
|
||||
{`(?=}})`, CommentPreproc, Pop(1)}, // Terminate the pipeline
|
||||
{`\(`, Operator, Push("subexpression")},
|
||||
{`"(\\\\|\\"|[^"])*"`, LiteralString, nil},
|
||||
Include("expression"),
|
||||
},
|
||||
"subexpression": {
|
||||
{`\)`, Operator, Pop(1)},
|
||||
Include("expression"),
|
||||
},
|
||||
"expression": {
|
||||
{`\s+`, Whitespace, nil},
|
||||
{`\(`, Operator, Push("subexpression")},
|
||||
{`(range|if|else|while|with|template|end|true|false|nil|and|call|html|index|js|len|not|or|print|printf|println|urlquery|eq|ne|lt|le|gt|ge)\b`, Keyword, nil},
|
||||
{`\||:?=|,`, Operator, nil},
|
||||
{`[$]?[^\W\d]\w*`, NameOther, nil},
|
||||
{`\$|[$]?\.(?:[^\W\d]\w*)?`, NameAttribute, nil},
|
||||
{`"(\\\\|\\"|[^"])*"`, LiteralString, nil},
|
||||
{`-?\d+i`, LiteralNumber, nil},
|
||||
{`-?\d+\.\d*([Ee][-+]\d+)?i`, LiteralNumber, nil},
|
||||
{`\.\d+([Ee][-+]\d+)?i`, LiteralNumber, nil},
|
||||
{`-?\d+[Ee][-+]\d+i`, LiteralNumber, nil},
|
||||
{`-?\d+(\.\d+[eE][+\-]?\d+|\.\d*|[eE][+\-]?\d+)`, LiteralNumberFloat, nil},
|
||||
{`-?\.\d+([eE][+\-]?\d+)?`, LiteralNumberFloat, nil},
|
||||
{`-?0[0-7]+`, LiteralNumberOct, nil},
|
||||
{`-?0[xX][0-9a-fA-F]+`, LiteralNumberHex, nil},
|
||||
{`-?(0|[1-9][0-9]*)`, LiteralNumberInteger, nil},
|
||||
{`'(\\['"\\abfnrtv]|\\x[0-9a-fA-F]{2}|\\[0-7]{1,3}|\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}|[^\\])'`, LiteralStringChar, nil},
|
||||
{"`[^`]*`", LiteralString, nil},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var GoHTMLTemplate = internal.Register(DelegatingLexer(h.HTML, MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Go HTML Template",
|
||||
Aliases: []string{"go-html-template"},
|
||||
|
@ -106,7 +112,7 @@ var GoHTMLTemplate = internal.Register(DelegatingLexer(h.HTML, MustNewLexer(
|
|||
goTemplateRules,
|
||||
)))
|
||||
|
||||
var GoTextTemplate = internal.Register(MustNewLexer(
|
||||
var GoTextTemplate = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Go Text Template",
|
||||
Aliases: []string{"go-text-template"},
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/g/graphql.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/g/graphql.go
generated
vendored
|
@ -6,13 +6,17 @@ import (
|
|||
)
|
||||
|
||||
// Go lexer.
|
||||
var Graphql = internal.Register(MustNewLexer(
|
||||
var Graphql = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "GraphQL",
|
||||
Aliases: []string{"graphql", "graphqls", "gql"},
|
||||
Filenames: []string{"*.graphql", "*.graphqls"},
|
||||
},
|
||||
Rules{
|
||||
graphqlRules,
|
||||
))
|
||||
|
||||
func graphqlRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`(query|mutation|subscription|fragment|scalar|implements|interface|union|enum|input|type)`, KeywordDeclaration, Push("type")},
|
||||
{`(on|extend|schema|directive|\.\.\.)`, KeywordDeclaration, nil},
|
||||
|
@ -41,5 +45,5 @@ var Graphql = internal.Register(MustNewLexer(
|
|||
{`[^\W\d]\w*`, NameClass, Pop(1)},
|
||||
Include("root"),
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
47
vendor/github.com/alecthomas/chroma/lexers/g/groff.go
generated
vendored
Normal file
47
vendor/github.com/alecthomas/chroma/lexers/g/groff.go
generated
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
package g
|
||||
|
||||
import (
|
||||
. "github.com/alecthomas/chroma" // nolint
|
||||
"github.com/alecthomas/chroma/lexers/internal"
|
||||
)
|
||||
|
||||
// Groff lexer.
|
||||
var Groff = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Groff",
|
||||
Aliases: []string{"groff", "nroff", "man"},
|
||||
Filenames: []string{"*.[1-9]", "*.1p", "*.3pm", "*.man"},
|
||||
MimeTypes: []string{"application/x-troff", "text/troff"},
|
||||
},
|
||||
func() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`(\.)(\w+)`, ByGroups(Text, Keyword), Push("request")},
|
||||
{`\.`, Punctuation, Push("request")},
|
||||
{`[^\\\n]+`, Text, Push("textline")},
|
||||
Default(Push("textline")),
|
||||
},
|
||||
"textline": {
|
||||
Include("escapes"),
|
||||
{`[^\\\n]+`, Text, nil},
|
||||
{`\n`, Text, Pop(1)},
|
||||
},
|
||||
"escapes": {
|
||||
{`\\"[^\n]*`, Comment, nil},
|
||||
{`\\[fn]\w`, LiteralStringEscape, nil},
|
||||
{`\\\(.{2}`, LiteralStringEscape, nil},
|
||||
{`\\.\[.*\]`, LiteralStringEscape, nil},
|
||||
{`\\.`, LiteralStringEscape, nil},
|
||||
{`\\\n`, Text, Push("request")},
|
||||
},
|
||||
"request": {
|
||||
{`\n`, Text, Pop(1)},
|
||||
Include("escapes"),
|
||||
{`"[^\n"]+"`, LiteralStringDouble, nil},
|
||||
{`\d+`, LiteralNumber, nil},
|
||||
{`\S+`, LiteralString, nil},
|
||||
{`\s+`, Text, nil},
|
||||
},
|
||||
}
|
||||
},
|
||||
))
|
12
vendor/github.com/alecthomas/chroma/lexers/g/groovy.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/g/groovy.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Groovy lexer.
|
||||
var Groovy = internal.Register(MustNewLexer(
|
||||
var Groovy = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Groovy",
|
||||
Aliases: []string{"groovy"},
|
||||
|
@ -14,7 +14,11 @@ var Groovy = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"text/x-groovy"},
|
||||
DotAll: true,
|
||||
},
|
||||
Rules{
|
||||
groovyRules,
|
||||
))
|
||||
|
||||
func groovyRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`#!(.*?)$`, CommentPreproc, Push("base")},
|
||||
Default(Push("base")),
|
||||
|
@ -54,5 +58,5 @@ var Groovy = internal.Register(MustNewLexer(
|
|||
"import": {
|
||||
{`[\w.]+\*?`, NameNamespace, Pop(1)},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
16
vendor/github.com/alecthomas/chroma/lexers/h/handlebars.go
generated
vendored
16
vendor/github.com/alecthomas/chroma/lexers/h/handlebars.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Handlebars lexer.
|
||||
var Handlebars = internal.Register(MustNewLexer(
|
||||
var Handlebars = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Handlebars",
|
||||
Aliases: []string{"handlebars"},
|
||||
Filenames: []string{"*.handlebars"},
|
||||
Aliases: []string{"handlebars", "hbs"},
|
||||
Filenames: []string{"*.handlebars", "*.hbs"},
|
||||
MimeTypes: []string{},
|
||||
},
|
||||
Rules{
|
||||
handlebarsRules,
|
||||
))
|
||||
|
||||
func handlebarsRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`[^{]+`, Other, nil},
|
||||
{`\{\{!.*\}\}`, Comment, nil},
|
||||
|
@ -52,5 +56,5 @@ var Handlebars = internal.Register(MustNewLexer(
|
|||
{`:?'(\\\\|\\'|[^'])*'`, LiteralStringSingle, nil},
|
||||
{`[0-9](\.[0-9]*)?(eE[+-][0-9])?[flFLdD]?|0[xX][0-9a-fA-F]+[Ll]?`, LiteralNumber, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/h/haskell.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/h/haskell.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Haskell lexer.
|
||||
var Haskell = internal.Register(MustNewLexer(
|
||||
var Haskell = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Haskell",
|
||||
Aliases: []string{"haskell", "hs"},
|
||||
Filenames: []string{"*.hs"},
|
||||
MimeTypes: []string{"text/x-haskell"},
|
||||
},
|
||||
Rules{
|
||||
haskellRules,
|
||||
))
|
||||
|
||||
func haskellRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\s+`, Text, nil},
|
||||
{`--(?![!#$%&*+./<=>?@^|_~:\\]).*?$`, CommentSingle, nil},
|
||||
|
@ -95,5 +99,5 @@ var Haskell = internal.Register(MustNewLexer(
|
|||
{`\d+`, LiteralStringEscape, Pop(1)},
|
||||
{`\s+\\`, LiteralStringEscape, Pop(1)},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/h/haxe.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/h/haxe.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Haxe lexer.
|
||||
var Haxe = internal.Register(MustNewLexer(
|
||||
var Haxe = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Haxe",
|
||||
Aliases: []string{"hx", "haxe", "hxsl"},
|
||||
|
@ -14,7 +14,11 @@ var Haxe = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"text/haxe", "text/x-haxe", "text/x-hx"},
|
||||
DotAll: true,
|
||||
},
|
||||
Rules{
|
||||
haxeRules,
|
||||
))
|
||||
|
||||
func haxeRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
Include("spaces"),
|
||||
Include("meta"),
|
||||
|
@ -609,8 +613,8 @@ var Haxe = internal.Register(MustNewLexer(
|
|||
{`\}`, Punctuation, Pop(1)},
|
||||
{`,`, Punctuation, Push("#pop", "object")},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
func haxePreProcMutator(state *LexerState) error {
|
||||
stack, ok := state.Get("haxe-pre-proc").([][]string)
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/h/hcl.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/h/hcl.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// HCL lexer.
|
||||
var HCL = internal.Register(MustNewLexer(
|
||||
var HCL = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "HCL",
|
||||
Aliases: []string{"hcl"},
|
||||
Filenames: []string{"*.hcl"},
|
||||
MimeTypes: []string{"application/x-hcl"},
|
||||
},
|
||||
Rules{
|
||||
hclRules,
|
||||
))
|
||||
|
||||
func hclRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
Include("string"),
|
||||
Include("punctuation"),
|
||||
|
@ -65,5 +69,5 @@ var HCL = internal.Register(MustNewLexer(
|
|||
{`\s+`, Text, nil},
|
||||
{`\\\n`, Text, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/h/hexdump.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/h/hexdump.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Hexdump lexer.
|
||||
var Hexdump = internal.Register(MustNewLexer(
|
||||
var Hexdump = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Hexdump",
|
||||
Aliases: []string{"hexdump"},
|
||||
Filenames: []string{},
|
||||
MimeTypes: []string{},
|
||||
},
|
||||
Rules{
|
||||
hexdumpRules,
|
||||
))
|
||||
|
||||
func hexdumpRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\n`, Text, nil},
|
||||
Include("offset"),
|
||||
|
@ -63,5 +67,5 @@ var Hexdump = internal.Register(MustNewLexer(
|
|||
{`\s`, Text, nil},
|
||||
{`^\*`, Punctuation, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package lexers
|
||||
package h
|
||||
|
||||
import (
|
||||
. "github.com/alecthomas/chroma" // nolint
|
||||
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// HLB lexer.
|
||||
var HLB = internal.Register(MustNewLexer(
|
||||
var HLB = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "HLB",
|
||||
Aliases: []string{"hlb"},
|
||||
Filenames: []string{"*.hlb"},
|
||||
MimeTypes: []string{},
|
||||
},
|
||||
Rules{
|
||||
hlbRules,
|
||||
))
|
||||
|
||||
func hlbRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`(#.*)`, ByGroups(CommentSingle), nil},
|
||||
{`((\b(0(b|B|o|O|x|X)[a-fA-F0-9]+)\b)|(\b(0|[1-9][0-9]*)\b))`, ByGroups(LiteralNumber), nil},
|
||||
|
@ -50,5 +54,5 @@ var HLB = internal.Register(MustNewLexer(
|
|||
{`(\n|\r|\r\n)`, Text, nil},
|
||||
{`.`, Text, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
12
vendor/github.com/alecthomas/chroma/lexers/h/html.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/h/html.go
generated
vendored
|
@ -8,7 +8,7 @@ import (
|
|||
)
|
||||
|
||||
// HTML lexer.
|
||||
var HTML = internal.Register(MustNewLexer(
|
||||
var HTML = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "HTML",
|
||||
Aliases: []string{"html"},
|
||||
|
@ -18,7 +18,11 @@ var HTML = internal.Register(MustNewLexer(
|
|||
DotAll: true,
|
||||
CaseInsensitive: true,
|
||||
},
|
||||
Rules{
|
||||
htmlRules,
|
||||
))
|
||||
|
||||
func htmlRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`[^<&]+`, Text, nil},
|
||||
{`&\S*?;`, NameEntity, nil},
|
||||
|
@ -55,5 +59,5 @@ var HTML = internal.Register(MustNewLexer(
|
|||
{`'.*?'`, LiteralString, Pop(1)},
|
||||
{`[^\s>]+`, LiteralString, Pop(1)},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
18
vendor/github.com/alecthomas/chroma/lexers/h/http.go
generated
vendored
18
vendor/github.com/alecthomas/chroma/lexers/h/http.go
generated
vendored
|
@ -8,7 +8,7 @@ import (
|
|||
)
|
||||
|
||||
// HTTP lexer.
|
||||
var HTTP = internal.Register(httpBodyContentTypeLexer(MustNewLexer(
|
||||
var HTTP = internal.Register(httpBodyContentTypeLexer(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "HTTP",
|
||||
Aliases: []string{"http"},
|
||||
|
@ -17,7 +17,11 @@ var HTTP = internal.Register(httpBodyContentTypeLexer(MustNewLexer(
|
|||
NotMultiline: true,
|
||||
DotAll: true,
|
||||
},
|
||||
Rules{
|
||||
httpRules,
|
||||
)))
|
||||
|
||||
func httpRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`(GET|POST|PUT|DELETE|HEAD|OPTIONS|TRACE|PATCH|CONNECT)( +)([^ ]+)( +)(HTTP)(/)([12]\.[01])(\r?\n|\Z)`, ByGroups(NameFunction, Text, NameNamespace, Text, KeywordReserved, Operator, LiteralNumber, Text), Push("headers")},
|
||||
{`(HTTP)(/)([12]\.[01])( +)(\d{3})( +)([^\r\n]+)(\r?\n|\Z)`, ByGroups(KeywordReserved, Operator, LiteralNumber, Text, LiteralNumber, Text, NameException, Text), Push("headers")},
|
||||
|
@ -30,17 +34,17 @@ var HTTP = internal.Register(httpBodyContentTypeLexer(MustNewLexer(
|
|||
"content": {
|
||||
{`.+`, EmitterFunc(httpContentBlock), nil},
|
||||
},
|
||||
},
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
func httpContentBlock(groups []string, lexer Lexer) Iterator {
|
||||
func httpContentBlock(groups []string, state *LexerState) Iterator {
|
||||
tokens := []Token{
|
||||
{Generic, groups[0]},
|
||||
}
|
||||
return Literator(tokens...)
|
||||
}
|
||||
|
||||
func httpHeaderBlock(groups []string, lexer Lexer) Iterator {
|
||||
func httpHeaderBlock(groups []string, state *LexerState) Iterator {
|
||||
tokens := []Token{
|
||||
{Name, groups[1]},
|
||||
{Text, groups[2]},
|
||||
|
@ -52,7 +56,7 @@ func httpHeaderBlock(groups []string, lexer Lexer) Iterator {
|
|||
return Literator(tokens...)
|
||||
}
|
||||
|
||||
func httpContinuousHeaderBlock(groups []string, lexer Lexer) Iterator {
|
||||
func httpContinuousHeaderBlock(groups []string, state *LexerState) Iterator {
|
||||
tokens := []Token{
|
||||
{Text, groups[1]},
|
||||
{Literal, groups[2]},
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/h/hy.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/h/hy.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Hy lexer.
|
||||
var Hy = internal.Register(MustNewLexer(
|
||||
var Hy = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Hy",
|
||||
Aliases: []string{"hylang"},
|
||||
Filenames: []string{"*.hy"},
|
||||
MimeTypes: []string{"text/x-hy", "application/x-hy"},
|
||||
},
|
||||
Rules{
|
||||
hyRules,
|
||||
))
|
||||
|
||||
func hyRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`;.*$`, CommentSingle, nil},
|
||||
{`[,\s]+`, Text, nil},
|
||||
|
@ -47,5 +51,5 @@ var Hy = internal.Register(MustNewLexer(
|
|||
{`(?<!\.)(self|None|Ellipsis|NotImplemented|False|True|cls)\b`, NameBuiltinPseudo, nil},
|
||||
{Words(`(?<!\.)`, `\b`, `ArithmeticError`, `AssertionError`, `AttributeError`, `BaseException`, `DeprecationWarning`, `EOFError`, `EnvironmentError`, `Exception`, `FloatingPointError`, `FutureWarning`, `GeneratorExit`, `IOError`, `ImportError`, `ImportWarning`, `IndentationError`, `IndexError`, `KeyError`, `KeyboardInterrupt`, `LookupError`, `MemoryError`, `NameError`, `NotImplemented`, `NotImplementedError`, `OSError`, `OverflowError`, `OverflowWarning`, `PendingDeprecationWarning`, `ReferenceError`, `RuntimeError`, `RuntimeWarning`, `StandardError`, `StopIteration`, `SyntaxError`, `SyntaxWarning`, `SystemError`, `SystemExit`, `TabError`, `TypeError`, `UnboundLocalError`, `UnicodeDecodeError`, `UnicodeEncodeError`, `UnicodeError`, `UnicodeTranslateError`, `UnicodeWarning`, `UserWarning`, `ValueError`, `VMSError`, `Warning`, `WindowsError`, `ZeroDivisionError`), NameException, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/i/idris.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/i/idris.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Idris lexer.
|
||||
var Idris = internal.Register(MustNewLexer(
|
||||
var Idris = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Idris",
|
||||
Aliases: []string{"idris", "idr"},
|
||||
Filenames: []string{"*.idr"},
|
||||
MimeTypes: []string{"text/x-idris"},
|
||||
},
|
||||
Rules{
|
||||
idrisRules,
|
||||
))
|
||||
|
||||
func idrisRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`^(\s*)(%lib|link|flag|include|hide|freeze|access|default|logging|dynamic|name|error_handlers|language)`, ByGroups(Text, KeywordReserved), nil},
|
||||
{`(\s*)(--(?![!#$%&*+./<=>?@^|_~:\\]).*?)$`, ByGroups(Text, CommentSingle), nil},
|
||||
|
@ -76,5 +80,5 @@ var Idris = internal.Register(MustNewLexer(
|
|||
{`\d+`, LiteralStringEscape, Pop(1)},
|
||||
{`\s+\\`, LiteralStringEscape, Pop(1)},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/i/igor.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/i/igor.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// Igor lexer.
|
||||
var Igor = internal.Register(MustNewLexer(
|
||||
var Igor = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Igor",
|
||||
Aliases: []string{"igor", "igorpro"},
|
||||
|
@ -14,7 +14,11 @@ var Igor = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"text/ipf"},
|
||||
CaseInsensitive: true,
|
||||
},
|
||||
Rules{
|
||||
igorRules,
|
||||
))
|
||||
|
||||
func igorRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`//.*$`, CommentSingle, nil},
|
||||
{`"([^"\\]|\\.)*"`, LiteralString, nil},
|
||||
|
@ -28,5 +32,5 @@ var Igor = internal.Register(MustNewLexer(
|
|||
{`.`, Text, nil},
|
||||
{`\n|\r`, Text, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/i/ini.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/i/ini.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Ini lexer.
|
||||
var Ini = internal.Register(MustNewLexer(
|
||||
var Ini = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "INI",
|
||||
Aliases: []string{"ini", "cfg", "dosini"},
|
||||
Filenames: []string{"*.ini", "*.cfg", "*.inf", ".gitconfig", ".editorconfig"},
|
||||
MimeTypes: []string{"text/x-ini", "text/inf"},
|
||||
},
|
||||
Rules{
|
||||
iniRules,
|
||||
))
|
||||
|
||||
func iniRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\s+`, Text, nil},
|
||||
{`[;#].*`, CommentSingle, nil},
|
||||
|
@ -21,5 +25,5 @@ var Ini = internal.Register(MustNewLexer(
|
|||
{`(.*?)([ \t]*)(=)([ \t]*)(.*(?:\n[ \t].+)*)`, ByGroups(NameAttribute, Text, Operator, Text, LiteralString), nil},
|
||||
{`(.+?)$`, NameAttribute, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/i/io.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/i/io.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// Io lexer.
|
||||
var Io = internal.Register(MustNewLexer(
|
||||
var Io = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Io",
|
||||
Aliases: []string{"io"},
|
||||
Filenames: []string{"*.io"},
|
||||
MimeTypes: []string{"text/x-iosrc"},
|
||||
},
|
||||
Rules{
|
||||
ioRules,
|
||||
))
|
||||
|
||||
func ioRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\n`, Text, nil},
|
||||
{`\s+`, Text, nil},
|
||||
|
@ -36,5 +40,5 @@ var Io = internal.Register(MustNewLexer(
|
|||
{`\+/`, CommentMultiline, Pop(1)},
|
||||
{`[+/]`, CommentMultiline, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
44
vendor/github.com/alecthomas/chroma/lexers/internal/api.go
generated
vendored
44
vendor/github.com/alecthomas/chroma/lexers/internal/api.go
generated
vendored
|
@ -11,6 +11,19 @@ import (
|
|||
"github.com/alecthomas/chroma"
|
||||
)
|
||||
|
||||
var (
|
||||
ignoredSuffixes = [...]string{
|
||||
// Editor backups
|
||||
"~", ".bak", ".old", ".orig",
|
||||
// Debian and derivatives apt/dpkg backups
|
||||
".dpkg-dist", ".dpkg-old",
|
||||
// Red Hat and derivatives rpm backups
|
||||
".rpmnew", ".rpmorig", ".rpmsave",
|
||||
// Build system input/template files
|
||||
".in",
|
||||
}
|
||||
)
|
||||
|
||||
// Registry of Lexers.
|
||||
var Registry = struct {
|
||||
Lexers chroma.Lexers
|
||||
|
@ -93,6 +106,13 @@ func Match(filename string) chroma.Lexer {
|
|||
for _, glob := range config.Filenames {
|
||||
if fnmatch.Match(glob, filename, 0) {
|
||||
matched = append(matched, lexer)
|
||||
} else {
|
||||
for _, suf := range &ignoredSuffixes {
|
||||
if fnmatch.Match(glob+suf, filename, 0) {
|
||||
matched = append(matched, lexer)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,6 +127,13 @@ func Match(filename string) chroma.Lexer {
|
|||
for _, glob := range config.AliasFilenames {
|
||||
if fnmatch.Match(glob, filename, 0) {
|
||||
matched = append(matched, lexer)
|
||||
} else {
|
||||
for _, suf := range &ignoredSuffixes {
|
||||
if fnmatch.Match(glob+suf, filename, 0) {
|
||||
matched = append(matched, lexer)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -146,16 +173,19 @@ func Register(lexer chroma.Lexer) chroma.Lexer {
|
|||
return lexer
|
||||
}
|
||||
|
||||
// Used for the fallback lexer as well as the explicit plaintext lexer
|
||||
var PlaintextRules = chroma.Rules{
|
||||
"root": []chroma.Rule{
|
||||
{`.+`, chroma.Text, nil},
|
||||
{`\n`, chroma.Text, nil},
|
||||
},
|
||||
// PlaintextRules is used for the fallback lexer as well as the explicit
|
||||
// plaintext lexer.
|
||||
func PlaintextRules() chroma.Rules {
|
||||
return chroma.Rules{
|
||||
"root": []chroma.Rule{
|
||||
{`.+`, chroma.Text, nil},
|
||||
{`\n`, chroma.Text, nil},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback lexer if no other is found.
|
||||
var Fallback chroma.Lexer = chroma.MustNewLexer(&chroma.Config{
|
||||
var Fallback chroma.Lexer = chroma.MustNewLazyLexer(&chroma.Config{
|
||||
Name: "fallback",
|
||||
Filenames: []string{"*"},
|
||||
}, PlaintextRules)
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/j/j.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/j/j.go
generated
vendored
|
@ -6,14 +6,18 @@ import (
|
|||
)
|
||||
|
||||
// J lexer.
|
||||
var J = internal.Register(MustNewLexer(
|
||||
var J = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "J",
|
||||
Aliases: []string{"j"},
|
||||
Filenames: []string{"*.ijs"},
|
||||
MimeTypes: []string{"text/x-j"},
|
||||
},
|
||||
Rules{
|
||||
jRules,
|
||||
))
|
||||
|
||||
func jRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`#!.*$`, CommentPreproc, nil},
|
||||
{`NB\..*`, CommentSingle, nil},
|
||||
|
@ -69,5 +73,5 @@ var J = internal.Register(MustNewLexer(
|
|||
{`''`, LiteralString, nil},
|
||||
{`'`, LiteralString, Pop(1)},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
13
vendor/github.com/alecthomas/chroma/lexers/j/java.go
generated
vendored
13
vendor/github.com/alecthomas/chroma/lexers/j/java.go
generated
vendored
|
@ -6,15 +6,20 @@ import (
|
|||
)
|
||||
|
||||
// Java lexer.
|
||||
var Java = internal.Register(MustNewLexer(
|
||||
var Java = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "Java",
|
||||
Aliases: []string{"java"},
|
||||
Filenames: []string{"*.java"},
|
||||
MimeTypes: []string{"text/x-java"},
|
||||
DotAll: true,
|
||||
EnsureNL: true,
|
||||
},
|
||||
Rules{
|
||||
javaRules,
|
||||
))
|
||||
|
||||
func javaRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`[^\S\n]+`, Text, nil},
|
||||
{`//.*?\n`, CommentSingle, nil},
|
||||
|
@ -47,5 +52,5 @@ var Java = internal.Register(MustNewLexer(
|
|||
"import": {
|
||||
{`[\w.]+\*?`, NameNamespace, Pop(1)},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
9
vendor/github.com/alecthomas/chroma/lexers/j/javascript.go
generated
vendored
9
vendor/github.com/alecthomas/chroma/lexers/j/javascript.go
generated
vendored
|
@ -26,11 +26,11 @@ var JavascriptRules = Rules{
|
|||
{`\A#! ?/.*?\n`, CommentHashbang, nil},
|
||||
{`^(?=\s|/|<!--)`, Text, Push("slashstartsregex")},
|
||||
Include("commentsandwhitespace"),
|
||||
{`(\.\d+|[0-9]+\.[0-9]*)([eE][-+]?[0-9]+)?`, LiteralNumberFloat, nil},
|
||||
{`\d+(\.\d*|[eE][+\-]?\d+)`, LiteralNumberFloat, nil},
|
||||
{`0[bB][01]+`, LiteralNumberBin, nil},
|
||||
{`0[oO][0-7]+`, LiteralNumberOct, nil},
|
||||
{`0[xX][0-9a-fA-F]+`, LiteralNumberHex, nil},
|
||||
{`[0-9]+`, LiteralNumberInteger, nil},
|
||||
{`[0-9_]+`, LiteralNumberInteger, nil},
|
||||
{`\.\.\.|=>`, Punctuation, nil},
|
||||
{`\+\+|--|~|&&|\?|:|\|\||\\(?=\n)|(<<|>>>?|==?|!=?|[-<>+*%&|^/])=?`, Operator, Push("slashstartsregex")},
|
||||
{`[{(\[;,]`, Punctuation, Push("slashstartsregex")},
|
||||
|
@ -49,6 +49,7 @@ var JavascriptRules = Rules{
|
|||
{"`", LiteralStringBacktick, Pop(1)},
|
||||
{`\\\\`, LiteralStringBacktick, nil},
|
||||
{"\\\\`", LiteralStringBacktick, nil},
|
||||
{"\\\\[^`\\\\]", LiteralStringBacktick, nil},
|
||||
{`\$\{`, LiteralStringInterpol, Push("interp-inside")},
|
||||
{`\$`, LiteralStringBacktick, nil},
|
||||
{"[^`\\\\$]+", LiteralStringBacktick, nil},
|
||||
|
@ -60,11 +61,11 @@ var JavascriptRules = Rules{
|
|||
}
|
||||
|
||||
// Javascript lexer.
|
||||
var Javascript = internal.Register(MustNewLexer(
|
||||
var Javascript = internal.Register(MustNewLexer( // nolint: forbidigo
|
||||
&Config{
|
||||
Name: "JavaScript",
|
||||
Aliases: []string{"js", "javascript"},
|
||||
Filenames: []string{"*.js", "*.jsm"},
|
||||
Filenames: []string{"*.js", "*.jsm", "*.mjs"},
|
||||
MimeTypes: []string{"application/javascript", "application/x-javascript", "text/x-javascript", "text/javascript"},
|
||||
DotAll: true,
|
||||
EnsureNL: true,
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/j/json.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/j/json.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// JSON lexer.
|
||||
var JSON = internal.Register(MustNewLexer(
|
||||
var JSON = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "JSON",
|
||||
Aliases: []string{"json"},
|
||||
|
@ -15,7 +15,11 @@ var JSON = internal.Register(MustNewLexer(
|
|||
NotMultiline: true,
|
||||
DotAll: true,
|
||||
},
|
||||
Rules{
|
||||
jsonRules,
|
||||
))
|
||||
|
||||
func jsonRules() Rules {
|
||||
return Rules{
|
||||
"whitespace": {
|
||||
{`\s+`, Text, nil},
|
||||
},
|
||||
|
@ -51,5 +55,5 @@ var JSON = internal.Register(MustNewLexer(
|
|||
"root": {
|
||||
Include("value"),
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
12
vendor/github.com/alecthomas/chroma/lexers/j/jsx.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/j/jsx.go
generated
vendored
|
@ -8,7 +8,7 @@ import (
|
|||
// JSX lexer.
|
||||
//
|
||||
// This was generated from https://github.com/fcurella/jsx-lexer
|
||||
var JSX = internal.Register(MustNewLexer(
|
||||
var JSX = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "react",
|
||||
Aliases: []string{"jsx", "react"},
|
||||
|
@ -16,7 +16,11 @@ var JSX = internal.Register(MustNewLexer(
|
|||
MimeTypes: []string{"text/jsx", "text/typescript-jsx"},
|
||||
DotAll: true,
|
||||
},
|
||||
Rules{
|
||||
jsxRules,
|
||||
))
|
||||
|
||||
func jsxRules() Rules {
|
||||
return Rules{
|
||||
"commentsandwhitespace": {
|
||||
{`\s+`, Text, nil},
|
||||
{`<!--`, Comment, nil},
|
||||
|
@ -91,5 +95,5 @@ var JSX = internal.Register(MustNewLexer(
|
|||
{`}`, Punctuation, Pop(1)},
|
||||
Include("root"),
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user