Compare commits
8 Commits
304a33528e
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
d75363f2ee
|
|||
|
ebb2161ca4
|
|||
|
c68d63fe52
|
|||
|
508c355b86
|
|||
|
6bcd031b5b
|
|||
|
c82444eda2
|
|||
|
36eacab2cd
|
|||
|
3e93661b67
|
42
fyne-gui-test/go.mod
Normal file
42
fyne-gui-test/go.mod
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
module fyne-gui-test
|
||||||
|
|
||||||
|
go 1.24.3
|
||||||
|
|
||||||
|
require (
|
||||||
|
fyne.io/fyne/v2 v2.6.3
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
fyne.io/systray v1.11.0 // indirect
|
||||||
|
github.com/BurntSushi/toml v1.4.0 // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/fredbi/uri v1.1.0 // indirect
|
||||||
|
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||||
|
github.com/fyne-io/gl-js v0.2.0 // indirect
|
||||||
|
github.com/fyne-io/glfw-js v0.3.0 // indirect
|
||||||
|
github.com/fyne-io/image v0.1.1 // indirect
|
||||||
|
github.com/fyne-io/oksvg v0.1.0 // indirect
|
||||||
|
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 // indirect
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a // indirect
|
||||||
|
github.com/go-text/render v0.2.0 // indirect
|
||||||
|
github.com/go-text/typesetting v0.2.1 // indirect
|
||||||
|
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||||
|
github.com/hack-pad/go-indexeddb v0.3.2 // indirect
|
||||||
|
github.com/hack-pad/safejs v0.1.0 // indirect
|
||||||
|
github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade // indirect
|
||||||
|
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect
|
||||||
|
github.com/kr/text v0.2.0 // indirect
|
||||||
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||||
|
github.com/nicksnyder/go-i18n/v2 v2.5.1 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/rymdport/portal v0.4.1 // indirect
|
||||||
|
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c // indirect
|
||||||
|
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef // indirect
|
||||||
|
github.com/stretchr/testify v1.10.0 // indirect
|
||||||
|
github.com/yuin/goldmark v1.7.8 // indirect
|
||||||
|
golang.org/x/image v0.24.0 // indirect
|
||||||
|
golang.org/x/net v0.35.0 // indirect
|
||||||
|
golang.org/x/sys v0.30.0 // indirect
|
||||||
|
golang.org/x/text v0.22.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
)
|
||||||
133
fyne-gui-test/go.sum
Normal file
133
fyne-gui-test/go.sum
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
fyne.io/fyne v1.4.3 h1:356CnXCiYrrfaLGsB7qLK3c6ktzyh8WR05v/2RBu51I=
|
||||||
|
fyne.io/fyne v1.4.3/go.mod h1:8kiPBNSDmuplxs9WnKCkaWYqbcXFy0DeAzwa6PBO9Z8=
|
||||||
|
fyne.io/fyne/v2 v2.6.3 h1:cvtM2KHeRuH+WhtHiA63z5wJVBkQ9+Ay0UMl9PxFHyA=
|
||||||
|
fyne.io/fyne/v2 v2.6.3/go.mod h1:NGSurpRElVoI1G3h+ab2df3O5KLGh1CGbsMMcX0bPIs=
|
||||||
|
fyne.io/systray v1.11.0 h1:D9HISlxSkx+jHSniMBR6fCFOUjk1x/OOOJLa9lJYAKg=
|
||||||
|
fyne.io/systray v1.11.0/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs=
|
||||||
|
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
||||||
|
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||||
|
github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9/go.mod h1:7uhhqiBaR4CpN0k9rMjOtjpcfGd6DG2m04zQxKnWQ0I=
|
||||||
|
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
|
||||||
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
|
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/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=
|
||||||
|
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
|
||||||
|
github.com/fredbi/uri v1.1.0 h1:OqLpTXtyRg9ABReqvDGdJPqZUxs8cyBDOMXBbskCaB8=
|
||||||
|
github.com/fredbi/uri v1.1.0/go.mod h1:aYTUoAXBOq7BLfVJ8GnKmfcuURosB1xyHDIfWeC/iW4=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
|
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||||
|
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||||
|
github.com/fyne-io/gl-js v0.2.0 h1:+EXMLVEa18EfkXBVKhifYB6OGs3HwKO3lUElA0LlAjs=
|
||||||
|
github.com/fyne-io/gl-js v0.2.0/go.mod h1:ZcepK8vmOYLu96JoxbCKJy2ybr+g1pTnaBDdl7c3ajI=
|
||||||
|
github.com/fyne-io/glfw-js v0.3.0 h1:d8k2+Y7l+zy2pc7wlGRyPfTgZoqDf3AI4G+2zOWhWUk=
|
||||||
|
github.com/fyne-io/glfw-js v0.3.0/go.mod h1:Ri6te7rdZtBgBpxLW19uBpp3Dl6K9K/bRaYdJ22G8Jk=
|
||||||
|
github.com/fyne-io/image v0.1.1 h1:WH0z4H7qfvNUw5l4p3bC1q70sa5+YWVt6HCj7y4VNyA=
|
||||||
|
github.com/fyne-io/image v0.1.1/go.mod h1:xrfYBh6yspc+KjkgdZU/ifUC9sPA5Iv7WYUBzQKK7JM=
|
||||||
|
github.com/fyne-io/mobile v0.1.2/go.mod h1:/kOrWrZB6sasLbEy2JIvr4arEzQTXBTZGb3Y96yWbHY=
|
||||||
|
github.com/fyne-io/oksvg v0.1.0 h1:7EUKk3HV3Y2E+qypp3nWqMXD7mum0hCw2KEGhI1fnBw=
|
||||||
|
github.com/fyne-io/oksvg v0.1.0/go.mod h1:dJ9oEkPiWhnTFNCmRgEze+YNprJF7YRbpjgpWS4kzoI=
|
||||||
|
github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk=
|
||||||
|
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 h1:5BVwOaUSBTlVZowGO6VZGw2H/zl9nrd3eCZfYV+NfQA=
|
||||||
|
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw=
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200625191551-73d3c3675aa3/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a h1:vxnBhFDDT+xzxf1jTJKMKZw3H0swfWk9RpWbBbDK5+0=
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
github.com/go-text/render v0.2.0 h1:LBYoTmp5jYiJ4NPqDc2pz17MLmA3wHw1dZSVGcOdeAc=
|
||||||
|
github.com/go-text/render v0.2.0/go.mod h1:CkiqfukRGKJA5vZZISkjSYrcdtgKQWRa2HIzvwNN5SU=
|
||||||
|
github.com/go-text/typesetting v0.2.1 h1:x0jMOGyO3d1qFAPI0j4GSsh7M0Q3Ypjzr4+CEVg82V8=
|
||||||
|
github.com/go-text/typesetting v0.2.1/go.mod h1:mTOxEwasOFpAMBjEQDhdWRckoLLeI/+qrQeBCTGEt6M=
|
||||||
|
github.com/go-text/typesetting-utils v0.0.0-20241103174707-87a29e9e6066 h1:qCuYC+94v2xrb1PoS4NIDe7DGYtLnU2wWiQe9a1B1c0=
|
||||||
|
github.com/go-text/typesetting-utils v0.0.0-20241103174707-87a29e9e6066/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o=
|
||||||
|
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||||
|
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff h1:W71vTCKoxtdXgnm1ECDFkfQnpdqAO00zzGXLA5yaEX8=
|
||||||
|
github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff/go.mod h1:wfqRWLHRBsRgkp5dmbG56SA0DmVtwrF5N3oPdI8t+Aw=
|
||||||
|
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y=
|
||||||
|
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
|
||||||
|
github.com/hack-pad/go-indexeddb v0.3.2 h1:DTqeJJYc1usa45Q5r52t01KhvlSN02+Oq+tQbSBI91A=
|
||||||
|
github.com/hack-pad/go-indexeddb v0.3.2/go.mod h1:QvfTevpDVlkfomY498LhstjwbPW6QC4VC/lxYb0Kom0=
|
||||||
|
github.com/hack-pad/safejs v0.1.0 h1:qPS6vjreAqh2amUqj4WNG1zIw7qlRQJ9K10eDKMCnE8=
|
||||||
|
github.com/hack-pad/safejs v0.1.0/go.mod h1:HdS+bKF1NrE72VoXZeWzxFOVQVUSqZJAG0xNCnb+Tio=
|
||||||
|
github.com/jackmordaunt/icns v0.0.0-20181231085925-4f16af745526/go.mod h1:UQkeMHVoNcyXYq9otUupF7/h/2tmHlhrS2zw7ZVvUqc=
|
||||||
|
github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade h1:FmusiCI1wHw+XQbvL9M+1r/C3SPqKrmBaIOYwVfQoDE=
|
||||||
|
github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade/go.mod h1:ZDXo8KHryOWSIqnsb/CiDq7hQUYryCgdVnxbj8tDG7o=
|
||||||
|
github.com/josephspurrier/goversioninfo v0.0.0-20200309025242-14b0ab84c6ca/go.mod h1:eJTEwMjXb7kZ633hO3Ln9mBUCOjX2+FlTljvpl9SYdE=
|
||||||
|
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 h1:YLvr1eE6cdCqjOe972w/cYF+FjW34v27+9Vo5106B4M=
|
||||||
|
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25/go.mod h1:kLgvv7o6UM+0QSf0QjAse3wReFDsb9qbZJdfexWlrQw=
|
||||||
|
github.com/kr/pty v1.1.1/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/lucor/goinfo v0.0.0-20200401173949-526b5363a13a/go.mod h1:ORP3/rB5IsulLEBwQZCJyyV6niqmI7P4EWSmkug+1Ng=
|
||||||
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||||
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||||
|
github.com/nicksnyder/go-i18n/v2 v2.5.1 h1:IxtPxYsR9Gp60cGXjfuR/llTqV8aYMsC472zD0D1vHk=
|
||||||
|
github.com/nicksnyder/go-i18n/v2 v2.5.1/go.mod h1:DrhgsSDZxoAfvVrBVLXoxZn/pN5TXqaDbq7ju94viiQ=
|
||||||
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA=
|
||||||
|
github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo=
|
||||||
|
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/rymdport/portal v0.4.1 h1:2dnZhjf5uEaeDjeF/yBIeeRo6pNI2QAKm7kq1w/kbnA=
|
||||||
|
github.com/rymdport/portal v0.4.1/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4=
|
||||||
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564/go.mod h1:afMbS0qvv1m5tfENCwnOdZGOF8RGR/FsZ7bvBxQGZG4=
|
||||||
|
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c h1:km8GpoQut05eY3GiYWEedbTT0qnSxrCjsVbb7yKY1KE=
|
||||||
|
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q=
|
||||||
|
github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9/go.mod h1:mvWM0+15UqyrFKqdRjY6LuAVJR0HOVhJlEgZ5JWtSWU=
|
||||||
|
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ=
|
||||||
|
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
|
||||||
|
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
|
golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
|
golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ=
|
||||||
|
golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8=
|
||||||
|
golang.org/x/mod v0.2.0/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-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||||
|
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||||
|
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/sys v0.0.0-20190215142949-d0b11bdaac8a/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-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200720211630-cb9d2d5c5666/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||||
|
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
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.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||||
|
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190808195139-e713427fea3f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20200328031815-3db5fc6bac03/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||||
|
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=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
43
fyne-gui-test/main.go
Normal file
43
fyne-gui-test/main.go
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/app"
|
||||||
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/widget"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
myApp := app.New()
|
||||||
|
window := myApp.NewWindow("Hello World.")
|
||||||
|
window.Resize(fyne.NewSize(700, 400))
|
||||||
|
// window.SetFixedSize(true)
|
||||||
|
|
||||||
|
textEntry := widget.NewMultiLineEntry()
|
||||||
|
textEntry.Wrapping = fyne.TextWrapWord
|
||||||
|
// textEntry.Disable()
|
||||||
|
|
||||||
|
initialText := "This is text"
|
||||||
|
textEntry.SetText(initialText)
|
||||||
|
textEntry.OnChanged = func(text string) {
|
||||||
|
if text != initialText {
|
||||||
|
textEntry.SetText(initialText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button := widget.NewButton(" [ Close ] ", func() {
|
||||||
|
myApp.Quit()
|
||||||
|
})
|
||||||
|
|
||||||
|
content := container.NewBorder(
|
||||||
|
nil, // top
|
||||||
|
container.NewBorder(nil, nil, nil, button, nil), // bottom
|
||||||
|
nil, // left
|
||||||
|
nil, // right
|
||||||
|
textEntry, // center
|
||||||
|
)
|
||||||
|
|
||||||
|
window.SetContent(content)
|
||||||
|
window.CenterOnScreen()
|
||||||
|
window.ShowAndRun()
|
||||||
|
}
|
||||||
3
go-ca/go.mod
Normal file
3
go-ca/go.mod
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module git.hatter.ink/golang-tests/go-ca
|
||||||
|
|
||||||
|
go 1.24.3
|
||||||
75
go-ca/main.go
Normal file
75
go-ca/main.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/elliptic"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/sha1"
|
||||||
|
"crypto/x509"
|
||||||
|
"crypto/x509/pkix"
|
||||||
|
"encoding/pem"
|
||||||
|
"math"
|
||||||
|
"math/big"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
err := innerMain()
|
||||||
|
if err == nil {
|
||||||
|
println("Success")
|
||||||
|
} else {
|
||||||
|
println("Error: ", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func innerMain() error {
|
||||||
|
rootKey, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rootCert, err := issueRootCertificate(&rootKey.PublicKey, rootKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
println(string(pem.EncodeToMemory(&pem.Block{
|
||||||
|
Type: "CERTIFICATE",
|
||||||
|
Bytes: rootCert,
|
||||||
|
})))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func issueRootCertificate(pubKey, parentPrivKey any) ([]byte, error) {
|
||||||
|
now := time.Now()
|
||||||
|
template := x509.Certificate{
|
||||||
|
SerialNumber: generateSerialNumber(),
|
||||||
|
Subject: pkix.Name{
|
||||||
|
CommonName: "Root CA",
|
||||||
|
},
|
||||||
|
NotBefore: now.UTC(),
|
||||||
|
NotAfter: now.AddDate(100, 0, 0).UTC(),
|
||||||
|
BasicConstraintsValid: true,
|
||||||
|
IsCA: true,
|
||||||
|
MaxPathLen: 10,
|
||||||
|
// MaxPathLenZero: true,
|
||||||
|
SubjectKeyId: getKeyId(pubKey),
|
||||||
|
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
|
||||||
|
}
|
||||||
|
parentCert := &template
|
||||||
|
return x509.CreateCertificate(rand.Reader, &template, parentCert, pubKey, parentPrivKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getKeyId(pubKey any) []byte {
|
||||||
|
pubKeyBytes, err := x509.MarshalPKIXPublicKey(pubKey)
|
||||||
|
if err != nil {
|
||||||
|
panic("Should not happen")
|
||||||
|
}
|
||||||
|
return sha1.New().Sum(pubKeyBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateSerialNumber() *big.Int {
|
||||||
|
randInt, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64))
|
||||||
|
if err != nil {
|
||||||
|
panic("Should not happen")
|
||||||
|
}
|
||||||
|
return randInt
|
||||||
|
}
|
||||||
8
go-tpm-non-restricted-key/go.mod
Normal file
8
go-tpm-non-restricted-key/go.mod
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
module git.hatter.ink/go-tpm-non-restricted-key
|
||||||
|
|
||||||
|
go 1.24.3
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/google/go-tpm v0.9.5 // indirect
|
||||||
|
golang.org/x/sys v0.8.0 // indirect
|
||||||
|
)
|
||||||
4
go-tpm-non-restricted-key/go.sum
Normal file
4
go-tpm-non-restricted-key/go.sum
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
github.com/google/go-tpm v0.9.5 h1:ocUmnDebX54dnW+MQWGQRbdaAcJELsa6PqZhJ48KwVU=
|
||||||
|
github.com/google/go-tpm v0.9.5/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
|
||||||
|
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||||
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
211
go-tpm-non-restricted-key/main.go
Normal file
211
go-tpm-non-restricted-key/main.go
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto"
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/sha256"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/asn1"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"math/big"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/google/go-tpm/legacy/tpm2"
|
||||||
|
"github.com/google/go-tpm/tpmutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func generateSrk(f *os.File) {
|
||||||
|
tmpl := tpm2.Public{
|
||||||
|
Type: tpm2.AlgRSA,
|
||||||
|
NameAlg: tpm2.AlgSHA256,
|
||||||
|
Attributes: tpm2.FlagFixedTPM | // Key can't leave the TPM.
|
||||||
|
tpm2.FlagFixedParent | // Key can't change parent.
|
||||||
|
tpm2.FlagSensitiveDataOrigin | // Key created by the TPM (not imported).
|
||||||
|
tpm2.FlagUserWithAuth | // Uses (empty) password.
|
||||||
|
tpm2.FlagNoDA | // This flag doesn't do anything, but it's in the spec.
|
||||||
|
tpm2.FlagRestricted | // Key used for TPM challenges, not general decryption.
|
||||||
|
tpm2.FlagDecrypt, // Key can be used to decrypt data.
|
||||||
|
RSAParameters: &tpm2.RSAParams{
|
||||||
|
Symmetric: &tpm2.SymScheme{Alg: tpm2.AlgAES, KeyBits: 128, Mode: tpm2.AlgCFB},
|
||||||
|
KeyBits: 2048,
|
||||||
|
ModulusRaw: make([]byte, 256),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
srk, _, err := tpm2.CreatePrimary(f, tpm2.HandleOwner, tpm2.PCRSelection{}, "", "", tmpl)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("creating srk: %v", err)
|
||||||
|
}
|
||||||
|
out, err := tpm2.ContextSave(f, srk)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("saving context: %v", err)
|
||||||
|
}
|
||||||
|
if err := os.WriteFile("srk.ctx", out, 0644); err != nil {
|
||||||
|
log.Fatalf("writing context: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateAppKey(f *os.File) {
|
||||||
|
srkCtx, err := os.ReadFile("srk.ctx")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("read srk: %v", err)
|
||||||
|
}
|
||||||
|
srk, err := tpm2.ContextLoad(f, srkCtx)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("load srk: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpl := tpm2.Public{
|
||||||
|
Type: tpm2.AlgECC,
|
||||||
|
NameAlg: tpm2.AlgSHA256,
|
||||||
|
Attributes: tpm2.FlagFixedTPM | // Key can't leave the TPM.
|
||||||
|
tpm2.FlagFixedParent | // Key can't change parent.
|
||||||
|
tpm2.FlagSensitiveDataOrigin | // Key created by the TPM (not imported).
|
||||||
|
tpm2.FlagUserWithAuth | // Uses (empty) password.
|
||||||
|
tpm2.FlagSign, // Key can be used to sign data.
|
||||||
|
ECCParameters: &tpm2.ECCParams{
|
||||||
|
Sign: &tpm2.SigScheme{Alg: tpm2.AlgECDSA, Hash: tpm2.AlgSHA256},
|
||||||
|
CurveID: tpm2.CurveNISTP256,
|
||||||
|
Point: tpm2.ECPoint{
|
||||||
|
XRaw: make([]byte, 32),
|
||||||
|
YRaw: make([]byte, 32),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
privBlob, pubBlob, _, hash, ticket, err := tpm2.CreateKey(f, srk, tpm2.PCRSelection{}, "", "", tmpl)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("create aik: %v", err)
|
||||||
|
}
|
||||||
|
log.Printf("privBlob: %x\n", privBlob)
|
||||||
|
log.Printf("pubBlob: %x\n", pubBlob)
|
||||||
|
log.Printf("hash: %x\n", hash)
|
||||||
|
log.Printf("ticket: %v %s\n", ticket.Type, ticket.Digest)
|
||||||
|
|
||||||
|
appKey, _, err := tpm2.Load(f, srk, "", pubBlob, privBlob)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("load app key: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write key context to disk.
|
||||||
|
appKeyCtx, err := tpm2.ContextSave(f, appKey)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("saving context: %v", err)
|
||||||
|
}
|
||||||
|
if err := os.WriteFile("app.ctx", appKeyCtx, 0644); err != nil {
|
||||||
|
log.Fatalf("writing context: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func fileExists(filename string) bool {
|
||||||
|
_, err := os.Stat(filename)
|
||||||
|
if err == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
panic("Should not happen")
|
||||||
|
}
|
||||||
|
|
||||||
|
type tpmSinger struct {
|
||||||
|
tpm io.ReadWriter
|
||||||
|
h tpmutil.Handle
|
||||||
|
pub crypto.PublicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *tpmSinger) Public() crypto.PublicKey {
|
||||||
|
return s.pub
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *tpmSinger) Sign(r io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) {
|
||||||
|
sig, err := tpm2.Sign(s.tpm, s.h, "", digest, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("signing data: %v", err)
|
||||||
|
}
|
||||||
|
if sig.RSA != nil {
|
||||||
|
return sig.RSA.Signature, nil
|
||||||
|
}
|
||||||
|
if sig.ECC != nil {
|
||||||
|
return asn1.Marshal(struct {
|
||||||
|
R *big.Int
|
||||||
|
S *big.Int
|
||||||
|
}{sig.ECC.R, sig.ECC.S})
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("unsupported signature type: %v", sig.Alg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSigner(tpm io.ReadWriter, h tpmutil.Handle) (*tpmSinger, error) {
|
||||||
|
tpmPub, _, _, err := tpm2.ReadPublic(tpm, h)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("read public blob: %v", err)
|
||||||
|
}
|
||||||
|
pub, err := tpmPub.Key()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("decode public key: %v", err)
|
||||||
|
}
|
||||||
|
return &tpmSinger{tpm, h, pub}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSinger(f *os.File) (*tpmSinger, error) {
|
||||||
|
keyCtx, err := os.ReadFile("app.ctx")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("read app key: %v", err)
|
||||||
|
}
|
||||||
|
key, err := tpm2.ContextLoad(f, keyCtx)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("load app key: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return newSigner(f, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// reference: https://ericchiang.github.io/post/tpm-keys/
|
||||||
|
func main() {
|
||||||
|
f, err := os.OpenFile("/dev/tpmrm0", os.O_RDWR, 0)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("opening tpm: %v", err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
if !fileExists("srk.ctx") {
|
||||||
|
generateSrk(f)
|
||||||
|
}
|
||||||
|
if !fileExists("app.ctx") {
|
||||||
|
generateAppKey(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
priv, err := getSinger(f)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("create signer: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
publicKeyDer, err := x509.MarshalPKIXPublicKey(priv.Public())
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("public key: %v", err)
|
||||||
|
} else {
|
||||||
|
log.Printf("public key pem: %s\n", base64.StdEncoding.EncodeToString(publicKeyDer))
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := []byte("Hello world!")
|
||||||
|
digest := sha256.Sum256(msg)
|
||||||
|
|
||||||
|
sig, err := priv.Sign(rand.Reader, digest[:], crypto.SHA256)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("signing data: %v", err)
|
||||||
|
}
|
||||||
|
log.Printf("sig: %s\n", hex.EncodeToString(sig))
|
||||||
|
pub, ok := priv.Public().(*ecdsa.PublicKey)
|
||||||
|
if !ok {
|
||||||
|
log.Fatalf("expected ecdsa.PublicKey got: %T", priv.Public())
|
||||||
|
}
|
||||||
|
if !ecdsa.VerifyASN1(pub, digest[:], sig) {
|
||||||
|
log.Fatalf("failed to verify signature")
|
||||||
|
}
|
||||||
|
}
|
||||||
7
go-tpm-rand/go.mod
Normal file
7
go-tpm-rand/go.mod
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
module git.hatter.ink/go-tpm-rand
|
||||||
|
|
||||||
|
go 1.24.3
|
||||||
|
|
||||||
|
require github.com/google/go-tpm v0.9.5
|
||||||
|
|
||||||
|
require golang.org/x/sys v0.8.0 // indirect
|
||||||
4
go-tpm-rand/go.sum
Normal file
4
go-tpm-rand/go.sum
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
github.com/google/go-tpm v0.9.5 h1:ocUmnDebX54dnW+MQWGQRbdaAcJELsa6PqZhJ48KwVU=
|
||||||
|
github.com/google/go-tpm v0.9.5/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
|
||||||
|
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||||
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
24
go-tpm-rand/main.go
Normal file
24
go-tpm-rand/main.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/google/go-tpm/legacy/tpm2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// reference: https://ericchiang.github.io/post/tpm-keys/
|
||||||
|
func main() {
|
||||||
|
f, err := os.OpenFile("/dev/tpmrm0", os.O_RDWR, 0)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("opening tpm: %v", err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
out, err := tpm2.GetRandom(f, 16)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("getting random bytes: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("%x\n", out)
|
||||||
|
}
|
||||||
5
okta-bcrypt-issue/go.mod
Normal file
5
okta-bcrypt-issue/go.mod
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module git.hatter.ink/okta-bcrypt-issue
|
||||||
|
|
||||||
|
go 1.24.1
|
||||||
|
|
||||||
|
require golang.org/x/crypto v0.40.0 // indirect
|
||||||
2
okta-bcrypt-issue/go.sum
Normal file
2
okta-bcrypt-issue/go.sum
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||||
|
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||||
44
okta-bcrypt-issue/main.go
Normal file
44
okta-bcrypt-issue/main.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// https://n0rdy.foo/posts/20250121/okta-bcrypt-lessons-for-better-apis/
|
||||||
|
func main() {
|
||||||
|
// 18 + 55 + 1 = 74, so above 72 characters' limit of BCrypt
|
||||||
|
userId := randomString(18)
|
||||||
|
username := randomString(55)
|
||||||
|
password := "super-duper-secure-password"
|
||||||
|
|
||||||
|
combinedString := fmt.Sprintf("%s:%s:%s", userId, username, password)
|
||||||
|
|
||||||
|
combinedHash, err := bcrypt.GenerateFromPassword([]byte(combinedString), bcrypt.DefaultCost)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// let's try to break it
|
||||||
|
wrongPassword := "wrong-password"
|
||||||
|
wrongCombinedString := fmt.Sprintf("%s:%s:%s", userId, username, wrongPassword)
|
||||||
|
|
||||||
|
err = bcrypt.CompareHashAndPassword(combinedHash, []byte(wrongCombinedString))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Password is incorrect")
|
||||||
|
} else {
|
||||||
|
fmt.Println("Password is correct")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func randomString(length int) string {
|
||||||
|
bytes := make([]byte, length)
|
||||||
|
_, err := rand.Read(bytes)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return base64.URLEncoding.EncodeToString(bytes)[:length]
|
||||||
|
}
|
||||||
26
sha256_length_extension_attacks/README.md
Normal file
26
sha256_length_extension_attacks/README.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
> Copied from: https://github.com/skerkour/kerkour.com/tree/main/blog/2023/sha256_length_extension_attacks
|
||||||
|
|
||||||
|
# [Breaking SHA256: length extension attacks in practice](https://kerkour.com/sha256-length-extension-attacks)
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ go run ./ -verbose
|
||||||
|
SecretKey: 7365637265747365637265747365637265747365637265747365637265747365
|
||||||
|
Legitimate Data: user_id=1&role=user
|
||||||
|
Legitimate Signature SHA256(SecretKey || LegitimateData): 5b0b4b2472778fea87faac08a72a47d24538bff9d7f19a3a85d069893e2b08ab
|
||||||
|
Verify LegitimateSignature == SHA256(SecretKey || LegitimateData): true
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Malicious Data: &something=true&role=admin
|
||||||
|
Malicious Message (LegitimateData || padding || MaliciousData):
|
||||||
|
00000000 75 73 65 72 5f 69 64 3d 31 26 72 6f 6c 65 3d 75 |user_id=1&role=u|
|
||||||
|
00000010 73 65 72 80 00 00 00 00 00 00 00 00 00 00 01 98 |ser.............|
|
||||||
|
00000020 26 73 6f 6d 65 74 68 69 6e 67 3d 74 72 75 65 26 |&something=true&|
|
||||||
|
00000030 72 6f 6c 65 3d 61 64 6d 69 6e |role=admin|
|
||||||
|
|
||||||
|
Malicious Signature: 8c37e11e8397b39cba72fa0e4769716c69a7ba9e29cfaf00d4601e086e85dd8f
|
||||||
|
Verify MaliciousSignature == SHA256(SecretKey, MaliciousMessage): true
|
||||||
|
```
|
||||||
3
sha256_length_extension_attacks/go.mod
Normal file
3
sha256_length_extension_attacks/go.mod
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module sha256_length_extension_attacks
|
||||||
|
|
||||||
|
go 1.22
|
||||||
200
sha256_length_extension_attacks/main.go
Normal file
200
sha256_length_extension_attacks/main.go
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"crypto/subtle"
|
||||||
|
"encoding/binary"
|
||||||
|
"encoding/hex"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
var verbose bool
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.BoolVar(&verbose, "verbose", false, "verbose")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
// 256 bits secretKey
|
||||||
|
// in real life it should be generated using crypto.Rand
|
||||||
|
secretKey := []byte("secretsecretsecretsecretsecretse")
|
||||||
|
|
||||||
|
legitimateData := []byte("user_id=1&role=user")
|
||||||
|
legitimateSignature := sign(secretKey, legitimateData)
|
||||||
|
|
||||||
|
// sha256 := append(make([]byte, 0), secretKey...)
|
||||||
|
// // sha256 := make([]byte, 0)
|
||||||
|
// sha256 = append(sha256, legitimateData...)
|
||||||
|
// oadding := generatePadding(uint64(len(secretKey)), uint64(len(legitimateData)))
|
||||||
|
// sha256 = append(sha256, oadding...)
|
||||||
|
// fmt.Println(hex.Dump(sha256))
|
||||||
|
|
||||||
|
fmt.Printf("SecretKey: %s\n", hex.EncodeToString(secretKey))
|
||||||
|
fmt.Printf("Legitimate Data: %s\n", string(legitimateData))
|
||||||
|
fmt.Printf("Legitimate Signature SHA256(SecretKey || LegitimateData): %s\n", hex.EncodeToString(legitimateSignature))
|
||||||
|
fmt.Printf("Verify LegitimateSignature == SHA256(SecretKey || LegitimateData): %v\n", verifySignature(secretKey, legitimateSignature, legitimateData))
|
||||||
|
|
||||||
|
fmt.Println("\n---------------------------------------------------------------------------------------------------\n")
|
||||||
|
|
||||||
|
maliciousData := []byte("&something=true&role=admin")
|
||||||
|
maliciousMessage := generateMaliciousMessage(uint64(len(secretKey)), legitimateData, maliciousData)
|
||||||
|
maliciousSignature := forgeSignature(legitimateSignature, maliciousData, uint64(len(secretKey)+len(legitimateData)))
|
||||||
|
|
||||||
|
fmt.Printf("Malicious Data: %s\n", string(maliciousData))
|
||||||
|
if verbose {
|
||||||
|
fmt.Println("Malicious Message (LegitimateData || padding || MaliciousData):")
|
||||||
|
fmt.Println(hex.Dump(maliciousMessage))
|
||||||
|
}
|
||||||
|
fmt.Printf("Malicious Signature: %s\n", hex.EncodeToString(maliciousSignature))
|
||||||
|
fmt.Printf("Verify MaliciousSignature == SHA256(SecretKey, MaliciousMessage): %v\n", verifySignature(secretKey, maliciousSignature, maliciousMessage))
|
||||||
|
}
|
||||||
|
|
||||||
|
// forgeSignature performs a length extension attack by loading a SHA256 hash from the legitimate signature
|
||||||
|
// and appending the malicious data.
|
||||||
|
func forgeSignature(legitimateSignature []byte, maliciousData []byte, secretKeyAndDataLength uint64) (forgedSignature []byte) {
|
||||||
|
digest := loadSha256(legitimateSignature, secretKeyAndDataLength)
|
||||||
|
|
||||||
|
digest.Write(maliciousData)
|
||||||
|
hash := digest.Sum(nil)
|
||||||
|
forgedSignature = hash[:]
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateMaliciousMessage generates the malicious message used to forge a signature without knowing the
|
||||||
|
// secretKey. The message has the following format: (legitimateData || padding || maliciousData)
|
||||||
|
func generateMaliciousMessage(secretKeyLength uint64, legitimateData []byte, maliciousData []byte) (message []byte) {
|
||||||
|
padding := generatePadding(secretKeyLength + uint64(len(legitimateData)))
|
||||||
|
message = make([]byte, 0, len(legitimateData)+len(padding)+len(maliciousData))
|
||||||
|
|
||||||
|
message = append(message, legitimateData...)
|
||||||
|
message = append(message, padding...)
|
||||||
|
message = append(message, maliciousData...)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// generatePadding generates the required padding to fill SHA256 blocks of 512 bits (64 bytes)
|
||||||
|
// with (secretKey || data || padding)
|
||||||
|
// The padding format is defined in RFC6234: https://www.rfc-editor.org/rfc/rfc6234#page-8
|
||||||
|
// inspired by `sha256.go`
|
||||||
|
func generatePadding(secretKeyAndDataLength uint64) []byte {
|
||||||
|
var tmp [64 + 8]byte // padding + length buffer
|
||||||
|
var t uint64
|
||||||
|
|
||||||
|
// Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
|
||||||
|
tmp[0] = 0x80
|
||||||
|
if secretKeyAndDataLength%64 < 56 {
|
||||||
|
t = 56 - secretKeyAndDataLength%64
|
||||||
|
} else {
|
||||||
|
t = 64 + 56 - secretKeyAndDataLength%64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Length in bits.
|
||||||
|
secretKeyAndDataLength <<= 3
|
||||||
|
padlen := tmp[:t+8]
|
||||||
|
binary.BigEndian.PutUint64(padlen[t+0:], secretKeyAndDataLength)
|
||||||
|
|
||||||
|
return padlen
|
||||||
|
}
|
||||||
|
|
||||||
|
// verifySignature verifies that Signature == SHA256(secretKey || data)
|
||||||
|
func verifySignature(secretKey []byte, signatureToVerify []byte, data []byte) (isValid bool) {
|
||||||
|
isValid = false
|
||||||
|
signature := sign(secretKey, data)
|
||||||
|
|
||||||
|
if subtle.ConstantTimeCompare(signature, signatureToVerify) == 1 {
|
||||||
|
isValid = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// sign generates a SHA256 MAC such as SHA256(secretKey || data)
|
||||||
|
func sign(secretKey []byte, data []byte) (signature []byte) {
|
||||||
|
hasher := sha256.New()
|
||||||
|
|
||||||
|
hasher.Write(secretKey)
|
||||||
|
hasher.Write(data)
|
||||||
|
hash := hasher.Sum(nil)
|
||||||
|
signature = hash[:]
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadSha256 is a slightly modified version of digest.UnmarshalBinary in order to load the state from a
|
||||||
|
// normal SHA256 hash instead of the "proprietary version" generated by digest.MarshalBinary
|
||||||
|
func loadSha256(hashBytes []byte, secretKeyAndDataLength uint64) (hash *digest) {
|
||||||
|
if len(hashBytes) != sha256.Size {
|
||||||
|
panic("loadSha256: not a valid SHA256 hash")
|
||||||
|
}
|
||||||
|
|
||||||
|
hash = new(digest)
|
||||||
|
hash.Reset()
|
||||||
|
|
||||||
|
hashBytes, hash.h[0] = consumeUint32(hashBytes)
|
||||||
|
hashBytes, hash.h[1] = consumeUint32(hashBytes)
|
||||||
|
hashBytes, hash.h[2] = consumeUint32(hashBytes)
|
||||||
|
hashBytes, hash.h[3] = consumeUint32(hashBytes)
|
||||||
|
hashBytes, hash.h[4] = consumeUint32(hashBytes)
|
||||||
|
hashBytes, hash.h[5] = consumeUint32(hashBytes)
|
||||||
|
hashBytes, hash.h[6] = consumeUint32(hashBytes)
|
||||||
|
_, hash.h[7] = consumeUint32(hashBytes)
|
||||||
|
// hash.len is the nearest upper multiple of 64 of the hashed data (secretKeyAndDataLength)
|
||||||
|
// hash.len = secretKeyAndDataLength + 64 - (secretKeyAndDataLength % 64)
|
||||||
|
// hash.nx = int(hash.len % chunk)
|
||||||
|
// hash.len is the length of consumed bytes, including the paddings
|
||||||
|
hash.len = secretKeyAndDataLength + uint64(len(generatePadding(secretKeyAndDataLength)))
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// func signBinary(secretKey []byte, data []byte) (signature []byte) {
|
||||||
|
// hasher := new(digest)
|
||||||
|
// hasher.Reset()
|
||||||
|
|
||||||
|
// hasher.Write(secretKey)
|
||||||
|
// hasher.Write(data)
|
||||||
|
// hash := hasher.checkSum()
|
||||||
|
// signature = hash[:]
|
||||||
|
|
||||||
|
// if verbose {
|
||||||
|
// binary, _ := hasher.MarshalBinary()
|
||||||
|
// fmt.Println("SHA256 Binary:")
|
||||||
|
// fmt.Println(hex.Dump(binary))
|
||||||
|
// }
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func loadSha256Binary(hashBytes []byte, secretKeyAndDataLength uint64) (hash *digest) {
|
||||||
|
// digestBinary := make([]byte, 0, marshaledSize)
|
||||||
|
// digestBinary = append(digestBinary, []byte(magic256)...)
|
||||||
|
// digestBinary = append(digestBinary, hashBytes...)
|
||||||
|
// digestBinary = append(digestBinary, make([]byte, chunk)...)
|
||||||
|
// digestBinary = binary.BigEndian.AppendUint64(digestBinary, secretKeyAndDataLength+64-(secretKeyAndDataLength%64))
|
||||||
|
|
||||||
|
// hash = new(digest)
|
||||||
|
// hash.Reset()
|
||||||
|
// err := hash.UnmarshalBinary(digestBinary)
|
||||||
|
// if err != nil {
|
||||||
|
// panic(err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if verbose {
|
||||||
|
// fmt.Println("SHA256 state:")
|
||||||
|
// fmt.Println(hex.Dump(digestBinary))
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
// dumpBinary prints 00000000 00000000 00000000 00000001
|
||||||
|
// func dumpBinary(data []byte) {
|
||||||
|
// for i, n := range data {
|
||||||
|
// fmt.Printf("%08b ", n)
|
||||||
|
// if (i+1)%4 == 0 && i != 0 {
|
||||||
|
// fmt.Println("")
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// fmt.Println("")
|
||||||
|
// }
|
||||||
261
sha256_length_extension_attacks/sha256.go
Normal file
261
sha256_length_extension_attacks/sha256.go
Normal file
@@ -0,0 +1,261 @@
|
|||||||
|
// Copyright 2009 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 sha256 implements the SHA224 and SHA256 hash algorithms as defined
|
||||||
|
// in FIPS 180-4.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto"
|
||||||
|
// "crypto/internal/boring"
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
"hash"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
crypto.RegisterHash(crypto.SHA224, New224)
|
||||||
|
crypto.RegisterHash(crypto.SHA256, New)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The size of a SHA256 checksum in bytes.
|
||||||
|
const Size = 32
|
||||||
|
|
||||||
|
// The size of a SHA224 checksum in bytes.
|
||||||
|
const Size224 = 28
|
||||||
|
|
||||||
|
// The blocksize of SHA256 and SHA224 in bytes.
|
||||||
|
const BlockSize = 64
|
||||||
|
|
||||||
|
const (
|
||||||
|
chunk = 64
|
||||||
|
init0 = 0x6A09E667
|
||||||
|
init1 = 0xBB67AE85
|
||||||
|
init2 = 0x3C6EF372
|
||||||
|
init3 = 0xA54FF53A
|
||||||
|
init4 = 0x510E527F
|
||||||
|
init5 = 0x9B05688C
|
||||||
|
init6 = 0x1F83D9AB
|
||||||
|
init7 = 0x5BE0CD19
|
||||||
|
init0_224 = 0xC1059ED8
|
||||||
|
init1_224 = 0x367CD507
|
||||||
|
init2_224 = 0x3070DD17
|
||||||
|
init3_224 = 0xF70E5939
|
||||||
|
init4_224 = 0xFFC00B31
|
||||||
|
init5_224 = 0x68581511
|
||||||
|
init6_224 = 0x64F98FA7
|
||||||
|
init7_224 = 0xBEFA4FA4
|
||||||
|
)
|
||||||
|
|
||||||
|
// digest represents the partial evaluation of a checksum.
|
||||||
|
type digest struct {
|
||||||
|
h [8]uint32
|
||||||
|
x [chunk]byte
|
||||||
|
nx int
|
||||||
|
len uint64
|
||||||
|
is224 bool // mark if this digest is SHA-224
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
magic224 = "sha\x02"
|
||||||
|
magic256 = "sha\x03"
|
||||||
|
marshaledSize = len(magic256) + 8*4 + chunk + 8
|
||||||
|
)
|
||||||
|
|
||||||
|
func (d *digest) MarshalBinary() ([]byte, error) {
|
||||||
|
b := make([]byte, 0, marshaledSize)
|
||||||
|
if d.is224 {
|
||||||
|
b = append(b, magic224...)
|
||||||
|
} else {
|
||||||
|
b = append(b, magic256...)
|
||||||
|
}
|
||||||
|
b = binary.BigEndian.AppendUint32(b, d.h[0])
|
||||||
|
b = binary.BigEndian.AppendUint32(b, d.h[1])
|
||||||
|
b = binary.BigEndian.AppendUint32(b, d.h[2])
|
||||||
|
b = binary.BigEndian.AppendUint32(b, d.h[3])
|
||||||
|
b = binary.BigEndian.AppendUint32(b, d.h[4])
|
||||||
|
b = binary.BigEndian.AppendUint32(b, d.h[5])
|
||||||
|
b = binary.BigEndian.AppendUint32(b, d.h[6])
|
||||||
|
b = binary.BigEndian.AppendUint32(b, d.h[7])
|
||||||
|
b = append(b, d.x[:d.nx]...)
|
||||||
|
b = b[:len(b)+len(d.x)-d.nx] // already zero
|
||||||
|
b = binary.BigEndian.AppendUint64(b, d.len)
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest) UnmarshalBinary(b []byte) error {
|
||||||
|
if len(b) < len(magic224) || (d.is224 && string(b[:len(magic224)]) != magic224) || (!d.is224 && string(b[:len(magic256)]) != magic256) {
|
||||||
|
return errors.New("crypto/sha256: invalid hash state identifier")
|
||||||
|
}
|
||||||
|
if len(b) != marshaledSize {
|
||||||
|
return errors.New("crypto/sha256: invalid hash state size")
|
||||||
|
}
|
||||||
|
b = b[len(magic224):]
|
||||||
|
b, d.h[0] = consumeUint32(b)
|
||||||
|
b, d.h[1] = consumeUint32(b)
|
||||||
|
b, d.h[2] = consumeUint32(b)
|
||||||
|
b, d.h[3] = consumeUint32(b)
|
||||||
|
b, d.h[4] = consumeUint32(b)
|
||||||
|
b, d.h[5] = consumeUint32(b)
|
||||||
|
b, d.h[6] = consumeUint32(b)
|
||||||
|
b, d.h[7] = consumeUint32(b)
|
||||||
|
b = b[copy(d.x[:], b):]
|
||||||
|
b, d.len = consumeUint64(b)
|
||||||
|
d.nx = int(d.len % chunk)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func consumeUint64(b []byte) ([]byte, uint64) {
|
||||||
|
_ = b[7]
|
||||||
|
x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
|
||||||
|
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
|
||||||
|
return b[8:], x
|
||||||
|
}
|
||||||
|
|
||||||
|
func consumeUint32(b []byte) ([]byte, uint32) {
|
||||||
|
_ = b[3]
|
||||||
|
x := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
|
||||||
|
return b[4:], x
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest) Reset() {
|
||||||
|
if !d.is224 {
|
||||||
|
d.h[0] = init0
|
||||||
|
d.h[1] = init1
|
||||||
|
d.h[2] = init2
|
||||||
|
d.h[3] = init3
|
||||||
|
d.h[4] = init4
|
||||||
|
d.h[5] = init5
|
||||||
|
d.h[6] = init6
|
||||||
|
d.h[7] = init7
|
||||||
|
} else {
|
||||||
|
d.h[0] = init0_224
|
||||||
|
d.h[1] = init1_224
|
||||||
|
d.h[2] = init2_224
|
||||||
|
d.h[3] = init3_224
|
||||||
|
d.h[4] = init4_224
|
||||||
|
d.h[5] = init5_224
|
||||||
|
d.h[6] = init6_224
|
||||||
|
d.h[7] = init7_224
|
||||||
|
}
|
||||||
|
d.nx = 0
|
||||||
|
d.len = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new hash.Hash computing the SHA256 checksum. The Hash
|
||||||
|
// also implements encoding.BinaryMarshaler and
|
||||||
|
// encoding.BinaryUnmarshaler to marshal and unmarshal the internal
|
||||||
|
// state of the hash.
|
||||||
|
func New() hash.Hash {
|
||||||
|
d := new(digest)
|
||||||
|
d.Reset()
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// New224 returns a new hash.Hash computing the SHA224 checksum.
|
||||||
|
func New224() hash.Hash {
|
||||||
|
d := new(digest)
|
||||||
|
d.is224 = true
|
||||||
|
d.Reset()
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest) Size() int {
|
||||||
|
if !d.is224 {
|
||||||
|
return Size
|
||||||
|
}
|
||||||
|
return Size224
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest) BlockSize() int { return BlockSize }
|
||||||
|
|
||||||
|
func (d *digest) Write(p []byte) (nn int, err error) {
|
||||||
|
nn = len(p)
|
||||||
|
d.len += uint64(nn)
|
||||||
|
if d.nx > 0 {
|
||||||
|
n := copy(d.x[d.nx:], p)
|
||||||
|
d.nx += n
|
||||||
|
if d.nx == chunk {
|
||||||
|
block(d, d.x[:])
|
||||||
|
d.nx = 0
|
||||||
|
}
|
||||||
|
p = p[n:]
|
||||||
|
}
|
||||||
|
if len(p) >= chunk {
|
||||||
|
n := len(p) &^ (chunk - 1)
|
||||||
|
block(d, p[:n])
|
||||||
|
p = p[n:]
|
||||||
|
}
|
||||||
|
if len(p) > 0 {
|
||||||
|
d.nx = copy(d.x[:], p)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest) Sum(in []byte) []byte {
|
||||||
|
// Make a copy of d so that caller can keep writing and summing.
|
||||||
|
d0 := *d
|
||||||
|
hash := d0.checkSum()
|
||||||
|
if d0.is224 {
|
||||||
|
return append(in, hash[:Size224]...)
|
||||||
|
}
|
||||||
|
return append(in, hash[:]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest) checkSum() [Size]byte {
|
||||||
|
len := d.len
|
||||||
|
// Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
|
||||||
|
var tmp [64 + 8]byte // padding + length buffer
|
||||||
|
tmp[0] = 0x80
|
||||||
|
var t uint64
|
||||||
|
if len%64 < 56 {
|
||||||
|
t = 56 - len%64
|
||||||
|
} else {
|
||||||
|
t = 64 + 56 - len%64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Length in bits.
|
||||||
|
len <<= 3
|
||||||
|
padlen := tmp[:t+8]
|
||||||
|
binary.BigEndian.PutUint64(padlen[t+0:], len)
|
||||||
|
d.Write(padlen)
|
||||||
|
|
||||||
|
if d.nx != 0 {
|
||||||
|
panic("d.nx != 0")
|
||||||
|
}
|
||||||
|
|
||||||
|
var digest [Size]byte
|
||||||
|
|
||||||
|
binary.BigEndian.PutUint32(digest[0:], d.h[0])
|
||||||
|
binary.BigEndian.PutUint32(digest[4:], d.h[1])
|
||||||
|
binary.BigEndian.PutUint32(digest[8:], d.h[2])
|
||||||
|
binary.BigEndian.PutUint32(digest[12:], d.h[3])
|
||||||
|
binary.BigEndian.PutUint32(digest[16:], d.h[4])
|
||||||
|
binary.BigEndian.PutUint32(digest[20:], d.h[5])
|
||||||
|
binary.BigEndian.PutUint32(digest[24:], d.h[6])
|
||||||
|
if !d.is224 {
|
||||||
|
binary.BigEndian.PutUint32(digest[28:], d.h[7])
|
||||||
|
}
|
||||||
|
|
||||||
|
return digest
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sum256 returns the SHA256 checksum of the data.
|
||||||
|
func Sum256(data []byte) [Size]byte {
|
||||||
|
var d digest
|
||||||
|
d.Reset()
|
||||||
|
d.Write(data)
|
||||||
|
return d.checkSum()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sum224 returns the SHA224 checksum of the data.
|
||||||
|
func Sum224(data []byte) [Size224]byte {
|
||||||
|
var d digest
|
||||||
|
d.is224 = true
|
||||||
|
d.Reset()
|
||||||
|
d.Write(data)
|
||||||
|
sum := d.checkSum()
|
||||||
|
ap := (*[Size224]byte)(sum[:])
|
||||||
|
return *ap
|
||||||
|
}
|
||||||
128
sha256_length_extension_attacks/sha256block.go
Normal file
128
sha256_length_extension_attacks/sha256block.go
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
// Copyright 2009 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.
|
||||||
|
|
||||||
|
// SHA256 block step.
|
||||||
|
// In its own file so that a faster assembly or C version
|
||||||
|
// can be substituted easily.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "math/bits"
|
||||||
|
|
||||||
|
var _K = []uint32{
|
||||||
|
0x428a2f98,
|
||||||
|
0x71374491,
|
||||||
|
0xb5c0fbcf,
|
||||||
|
0xe9b5dba5,
|
||||||
|
0x3956c25b,
|
||||||
|
0x59f111f1,
|
||||||
|
0x923f82a4,
|
||||||
|
0xab1c5ed5,
|
||||||
|
0xd807aa98,
|
||||||
|
0x12835b01,
|
||||||
|
0x243185be,
|
||||||
|
0x550c7dc3,
|
||||||
|
0x72be5d74,
|
||||||
|
0x80deb1fe,
|
||||||
|
0x9bdc06a7,
|
||||||
|
0xc19bf174,
|
||||||
|
0xe49b69c1,
|
||||||
|
0xefbe4786,
|
||||||
|
0x0fc19dc6,
|
||||||
|
0x240ca1cc,
|
||||||
|
0x2de92c6f,
|
||||||
|
0x4a7484aa,
|
||||||
|
0x5cb0a9dc,
|
||||||
|
0x76f988da,
|
||||||
|
0x983e5152,
|
||||||
|
0xa831c66d,
|
||||||
|
0xb00327c8,
|
||||||
|
0xbf597fc7,
|
||||||
|
0xc6e00bf3,
|
||||||
|
0xd5a79147,
|
||||||
|
0x06ca6351,
|
||||||
|
0x14292967,
|
||||||
|
0x27b70a85,
|
||||||
|
0x2e1b2138,
|
||||||
|
0x4d2c6dfc,
|
||||||
|
0x53380d13,
|
||||||
|
0x650a7354,
|
||||||
|
0x766a0abb,
|
||||||
|
0x81c2c92e,
|
||||||
|
0x92722c85,
|
||||||
|
0xa2bfe8a1,
|
||||||
|
0xa81a664b,
|
||||||
|
0xc24b8b70,
|
||||||
|
0xc76c51a3,
|
||||||
|
0xd192e819,
|
||||||
|
0xd6990624,
|
||||||
|
0xf40e3585,
|
||||||
|
0x106aa070,
|
||||||
|
0x19a4c116,
|
||||||
|
0x1e376c08,
|
||||||
|
0x2748774c,
|
||||||
|
0x34b0bcb5,
|
||||||
|
0x391c0cb3,
|
||||||
|
0x4ed8aa4a,
|
||||||
|
0x5b9cca4f,
|
||||||
|
0x682e6ff3,
|
||||||
|
0x748f82ee,
|
||||||
|
0x78a5636f,
|
||||||
|
0x84c87814,
|
||||||
|
0x8cc70208,
|
||||||
|
0x90befffa,
|
||||||
|
0xa4506ceb,
|
||||||
|
0xbef9a3f7,
|
||||||
|
0xc67178f2,
|
||||||
|
}
|
||||||
|
|
||||||
|
func block(dig *digest, p []byte) {
|
||||||
|
var w [64]uint32
|
||||||
|
h0, h1, h2, h3, h4, h5, h6, h7 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7]
|
||||||
|
for len(p) >= chunk {
|
||||||
|
// Can interlace the computation of w with the
|
||||||
|
// rounds below if needed for speed.
|
||||||
|
for i := 0; i < 16; i++ {
|
||||||
|
j := i * 4
|
||||||
|
w[i] = uint32(p[j])<<24 | uint32(p[j+1])<<16 | uint32(p[j+2])<<8 | uint32(p[j+3])
|
||||||
|
}
|
||||||
|
for i := 16; i < 64; i++ {
|
||||||
|
v1 := w[i-2]
|
||||||
|
t1 := (bits.RotateLeft32(v1, -17)) ^ (bits.RotateLeft32(v1, -19)) ^ (v1 >> 10)
|
||||||
|
v2 := w[i-15]
|
||||||
|
t2 := (bits.RotateLeft32(v2, -7)) ^ (bits.RotateLeft32(v2, -18)) ^ (v2 >> 3)
|
||||||
|
w[i] = t1 + w[i-7] + t2 + w[i-16]
|
||||||
|
}
|
||||||
|
|
||||||
|
a, b, c, d, e, f, g, h := h0, h1, h2, h3, h4, h5, h6, h7
|
||||||
|
|
||||||
|
for i := 0; i < 64; i++ {
|
||||||
|
t1 := h + ((bits.RotateLeft32(e, -6)) ^ (bits.RotateLeft32(e, -11)) ^ (bits.RotateLeft32(e, -25))) + ((e & f) ^ (^e & g)) + _K[i] + w[i]
|
||||||
|
|
||||||
|
t2 := ((bits.RotateLeft32(a, -2)) ^ (bits.RotateLeft32(a, -13)) ^ (bits.RotateLeft32(a, -22))) + ((a & b) ^ (a & c) ^ (b & c))
|
||||||
|
|
||||||
|
h = g
|
||||||
|
g = f
|
||||||
|
f = e
|
||||||
|
e = d + t1
|
||||||
|
d = c
|
||||||
|
c = b
|
||||||
|
b = a
|
||||||
|
a = t1 + t2
|
||||||
|
}
|
||||||
|
|
||||||
|
h0 += a
|
||||||
|
h1 += b
|
||||||
|
h2 += c
|
||||||
|
h3 += d
|
||||||
|
h4 += e
|
||||||
|
h5 += f
|
||||||
|
h6 += g
|
||||||
|
h7 += h
|
||||||
|
|
||||||
|
p = p[chunk:]
|
||||||
|
}
|
||||||
|
|
||||||
|
dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] = h0, h1, h2, h3, h4, h5, h6, h7
|
||||||
|
}
|
||||||
29
swift-from-go/Package.swift
Normal file
29
swift-from-go/Package.swift
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// swift-tools-version:4.2
|
||||||
|
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||||
|
|
||||||
|
import PackageDescription
|
||||||
|
|
||||||
|
let package = Package(
|
||||||
|
name: "go-swift",
|
||||||
|
products: [
|
||||||
|
// Products define the executables and libraries produced by a package, and make them visible to other packages.
|
||||||
|
.library(
|
||||||
|
name: "go_swift",
|
||||||
|
type: .dynamic,
|
||||||
|
targets: ["go-swift"]),
|
||||||
|
],
|
||||||
|
dependencies: [
|
||||||
|
// Dependencies declare other packages that this package depends on.
|
||||||
|
// .package(url: /* package url */, from: "1.0.0"),
|
||||||
|
],
|
||||||
|
targets: [
|
||||||
|
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
|
||||||
|
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
|
||||||
|
.target(
|
||||||
|
name: "go-swift",
|
||||||
|
dependencies: []),
|
||||||
|
.testTarget(
|
||||||
|
name: "go-swiftTests",
|
||||||
|
dependencies: ["go-swift"]),
|
||||||
|
]
|
||||||
|
)
|
||||||
15
swift-from-go/README.md
Normal file
15
swift-from-go/README.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# go-swift
|
||||||
|
|
||||||
|
> Clone from: https://github.com/onderweg/swift-from-go
|
||||||
|
|
||||||
|
Example code, complementing the blog post: ["Calling Swift from Go"](https://dev.to/gerwert/calling-swift-from-go-5dbk)
|
||||||
|
|
||||||
|
_Note: this repo is more than 3 years old. Feel free to use it as reference, but don't expect it to work with current versions of Go and Swift._
|
||||||
|
|
||||||
|
## Building & Running
|
||||||
|
|
||||||
|
```
|
||||||
|
$ swift build
|
||||||
|
$ go build -o hello
|
||||||
|
$ ./hello
|
||||||
|
```
|
||||||
7
swift-from-go/Sources/go-swift/go_swift.swift
Normal file
7
swift-from-go/Sources/go-swift/go_swift.swift
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
@_cdecl("sayHello") // export to C as `sayHello``
|
||||||
|
public func sayHello(namePtr: UnsafePointer<CChar>?) {
|
||||||
|
// Creates a new string by copying the null-terminated UTF-8 data (C String)
|
||||||
|
// referenced by the given pointer.
|
||||||
|
let name = String(cString: namePtr!)
|
||||||
|
print("Welcome, \(name)!")
|
||||||
|
}
|
||||||
7
swift-from-go/Tests/LinuxMain.swift
Normal file
7
swift-from-go/Tests/LinuxMain.swift
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import XCTest
|
||||||
|
|
||||||
|
import go_swiftTests
|
||||||
|
|
||||||
|
var tests = [XCTestCaseEntry]()
|
||||||
|
tests += go_swiftTests.allTests()
|
||||||
|
XCTMain(tests)
|
||||||
9
swift-from-go/Tests/go-swiftTests/XCTestManifests.swift
Normal file
9
swift-from-go/Tests/go-swiftTests/XCTestManifests.swift
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import XCTest
|
||||||
|
|
||||||
|
#if !os(macOS)
|
||||||
|
public func allTests() -> [XCTestCaseEntry] {
|
||||||
|
return [
|
||||||
|
testCase(go_swiftTests.allTests),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
#endif
|
||||||
15
swift-from-go/Tests/go-swiftTests/go_swiftTests.swift
Normal file
15
swift-from-go/Tests/go-swiftTests/go_swiftTests.swift
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import XCTest
|
||||||
|
@testable import go_swift
|
||||||
|
|
||||||
|
final class go_swiftTests: XCTestCase {
|
||||||
|
func testExample() {
|
||||||
|
// This is an example of a functional test case.
|
||||||
|
// Use XCTAssert and related functions to verify your tests produce the correct
|
||||||
|
// results.
|
||||||
|
XCTAssertEqual(go_swift().text, "Hello, World!")
|
||||||
|
}
|
||||||
|
|
||||||
|
static var allTests = [
|
||||||
|
("testExample", testExample),
|
||||||
|
]
|
||||||
|
}
|
||||||
2
swift-from-go/include/go_swift.h
Normal file
2
swift-from-go/include/go_swift.h
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
// Manually crafted header file for C Library
|
||||||
|
void sayHello(char* name);
|
||||||
22
swift-from-go/main.go
Normal file
22
swift-from-go/main.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo CFLAGS: -I./include
|
||||||
|
#cgo LDFLAGS: -L.build/debug/ -lgo_swift
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "include/go_swift.h"
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Convert Go string to C string
|
||||||
|
cstr := C.CString("Bob")
|
||||||
|
|
||||||
|
// Call Swift function `sayHello``
|
||||||
|
C.sayHello(cstr)
|
||||||
|
|
||||||
|
// The C string is allocated in the C heap using malloc.
|
||||||
|
// Therefore memory must be freed when we're done
|
||||||
|
C.free(unsafe.Pointer(cstr))
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user