分类 Go 下的文章

“Go是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。 罗伯特·格瑞史莫、罗勃·派克及肯·汤普逊于2007年9月开始设计Go,稍后伊恩·兰斯·泰勒、拉斯·考克斯加入项目。Go是基于Inferno操作系统所开发的。”

使用openssl 生成rsa-pss 密钥

openssl genpkey -algorithm rsa-pss          \
    -pkeyopt rsa_keygen_bits:2048           \
    -pkeyopt rsa_pss_keygen_md:sha256       \
    -pkeyopt rsa_pss_keygen_mgf1_md:sha256  \
    -pkeyopt rsa_pss_keygen_saltlen:32      \
    -out rsa-pss-privateKey.pem

cat rsa-pss-privateKey.pem

-----BEGIN PRIVATE KEY-----
MIIE7gIBADA9BgkqhkiG9w0BAQowMKANMAsGCWCGSAFlAwQCAaEaMBgGCSqGSIb3
DQEBCDALBglghkgBZQMEAgGiAwIBIASCBKgwggSkAgEAAoIBAQCVDnc3tuB3do2g
I2V08eEAMF1pJd5nUJ6SYnBOqKEQ2ZNsU6OV51WGx3leN9gjEdkKjErUi8N0YMo9
TMK0cXpZzHmn/lU6HY3qe/i5ZGhSWWPtC1jE6Tt1BgnfXR9jc9S/+lxfZm9UFSsc
JMwBivbvPEXIyauWA3ww7A7oDh6oC4J5u7clgfbzRGJKLBD2raEMmnTVJoiVTshn
9Wyrm+B/mJK2YhG5pxAQ7pwaK6/eMDn1hLWAJIIS5USz50AC04T9fpenz14ITiWd
9lbKOVBzjHmo67UnhhrNoB8Kf8W6Ti4XEOBwdg/Kaa4hFofk8mV2ymJYYZ6scHbd
2pFcJQWlAgMBAAECggEAded7ZhbCd7zPSly1ZEvwLrYTLZlG03Jx/FjhfVbmEO4K
LyX5wBm9DV+8IUsLLLJxfGZ8yqPDd8sYLmUJnrIkleOoV7pWsCGwoEpv9DX4Tytm
X5saHKhg37BnHsgKjCCTqUfgyZW9ekVEVH7G4HGL4rFKggkEMSWQlyIiqGyC02kS
PEdPcMuBx1AKHWVjtQLc5E4v2lYmhlqVX1N97XcNrbNRdTjOpL4eyf6zkb0IJjuu
9FZYVIDjRe+HI0xMUxTobJXuP5amL9upegCF5hiL0oxUM7kK/UVwPK+SjtV0T3sC
BImxfCAefzOX9K7IGbtECSDPxh+UEIYXv2p+YwEQAQKBgQDF2vcU75Rbv4hgy/iP
16n7XfzZ0+kmfoxetiMM6s/LX3kv85KFyu3+Zm4NZG9gATjs412GoP4YcHzfF9O5
pRNAMaGxBAVzDUG0QGxuwqBPImkKhPBHp46R19UzBuoOKD2N6U3ko0sv567H0+wJ
10dknIn3urNCSeJiTYouxL3y+QKBgQDA3EWGHwod9B7X3brEoBaFkVOM5gemh+ZO
OngnzsH+MDx3a4fIyLvlYQh4gVjx0oR4ctaHJ2acfBKu1xTetIAiBgYrv5Ov2Of4
1/VdF+HEG0pu0wISNZ08dzdAaDT9jRctI5caHQqBjFv4bvMzG466WhHVkH0+cFT+
GNYVuYnnDQKBgENWp9tPQv4K7P6MzTcfnnG35lO4xNReI6YkdT9zN2+vOc6xJoA0
tdVsxS33rdRN9jLhmzYz2uc0ebtwH5ZCcY/alH5rsPMcYu1XM9Bqmybzvi5fWmv4
whQvEhfA1a4l0fVXnzQew3s1bg4CuYYL5/d9M5PFzjbUcKEmZM5QFZn5AoGBAK+7
xuoIfIqAuF4Qn6+tA/ifTJd1v4DiElwz8Oqs/p2kzGQwqmCtcHD5suNDUY3AOo8a
bRpoL5rlf4yrVUv9A0h9XsAcZ/Fy3yUje2NhcInmKDPFt/xpuCWxp7nbenWTS4wJ
AxV7Yuhawi8kwhxOvwZVLi0A5O6xIvEKJoFTODI9AoGBAIF9u17oUZK59dnxA1v1
kv06VvC8JxB95lbc5FlK8ZOeNxxvPf6Y2DqbtkmK8Mc2gfTFH1e6+i6Qr0AE5MBC
2icqlbWAyCbuwlLr9cvbG8Pp/qTrs4dTXWVE4+JRaYytpEt/0395ohAjH+9uvfxr
WuP6176mGPZ4FF1/cIqesl/N
-----END PRIVATE KEY-----

openssl rsa -in rsa-pss-privateKey.pem -pubout -out rsa-pss-publicKey.pem

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlQ53N7bgd3aNoCNldPHh
ADBdaSXeZ1CekmJwTqihENmTbFOjledVhsd5XjfYIxHZCoxK1IvDdGDKPUzCtHF6
Wcx5p/5VOh2N6nv4uWRoUllj7QtYxOk7dQYJ310fY3PUv/pcX2ZvVBUrHCTMAYr2
7zxFyMmrlgN8MOwO6A4eqAuCebu3JYH280RiSiwQ9q2hDJp01SaIlU7IZ/Vsq5vg
f5iStmIRuacQEO6cGiuv3jA59YS1gCSCEuVEs+dAAtOE/X6Xp89eCE4lnfZWyjlQ
c4x5qOu1J4YazaAfCn/Fuk4uFxDgcHYPymmuIRaH5PJldspiWGGerHB23dqRXCUF
pQIDAQAB
-----END PUBLIC KEY-----

echo -n "hello world" > tbs.txt
openssl dgst -sha256 -sign rsa-pss-privateKey.pem -out tbs.sign tbs.txt 
hexdump -C tbs.sign 

00000000 10 34 d7 ae 8d 29 b3 bb 81 b1 24 f8 e7 b5 55 95 |.4...)....$...U.|
00000010 8c 60 4b 70 1d 66 c8 e1 99 8a cb 7c 77 e9 dd 6e |.`Kp.f.....|w..n|
00000020 39 8c b7 91 1d a0 a3 f6 2c ef ee 1d 9f 4c e1 ae |9.......,....L..|
00000030 4c 78 10 37 cb aa 11 c8 cd 2a f7 a4 91 8a 6c 83 |Lx.7.....*....l.|
00000040 2c 32 fa 37 42 71 1d 5a bc 8d 2c d2 54 74 38 f5 |,2.7Bq.Z..,.Tt8.|
00000050 ca 33 a3 e9 54 f2 1b a2 72 71 9f 3c aa 7c c2 1c |.3..T...rq.<.|..|
00000060 e8 33 9f f8 a6 9a 9d ac f5 c4 cb e6 a9 da 66 7b |.3............f{|
00000070 6f f2 a9 cf 6b 9f 91 d8 f7 3d ec 74 f0 77 76 07 |o...k....=.t.wv.|
00000080 ec 60 32 bd cf 7f 22 f1 94 66 be 03 c3 1b 8d b3 |.`2..."..f......|
00000090 8c 21 a9 da d1 72 3c a0 f0 91 1d ae 05 18 13 ab |.!...r<.........|
000000a0 e6 3e c0 44 ea b6 43 f5 e2 8d 57 a7 8a 1d e3 75 |.>.D..C...W....u|
000000b0 bd b1 0e aa 4e b9 16 a9 56 67 4c 11 75 da b2 08 |....N...VgL.u...|
000000c0 bc bc 9a 1a 98 60 2b cc 51 6a b8 4d 2d 07 5c 61 |.....`+.Qj.M-.a|
000000d0 c3 89 00 a4 0a cd aa 17 50 ac 2a 3c 4d 28 3b 8d |........P.*<M(;.|
000000e0 32 29 75 f9 d6 79 72 34 f4 07 db 9f 42 25 ef 7a |2)u..yr4....B%.z|
000000f0 9c d2 b0 24 fd e0 91 d9 be 02 d3 ae da 38 28 f8 |...$.........8(.|

openssl dgst -sha256 -verify rsa-pss-publicKey.pem  -signature  tbs.sign -sigopt rsa_padding_mode:pss tbs.txt 

Verified OK

使用不带pkeyopt的rsa密钥实现rsa-pss签名与验签时,使用

openssl dgst -sign [private_key_file] -sha256 -sigopt rsa_padding_mode:pss -out [output_file] [input_file]
openssl dgst -verify [public_key_file] -signature [signature_file] -sigopt rsa_padding_mode:pss [signature_message_file]

参考:https://linuxcommandlibrary.com/man/openssl-dgst

使用openssl pkeyutl 签名验签

openssl dgst -sha256 -binary -out tbs.sha256 tbs.txt
openssl pkeyutl -sign \
  -in tbs.sha256 -inkey rsa-pss-privateKey.pem \
  -out tbs.sign \
  -pkeyopt digest:sha256 \
  -pkeyopt rsa_padding_mode:pss \
  -pkeyopt rsa_pss_saltlen:-1

  openssl pkeyutl -verify \
  -in tbs.sha256 -sigfile tbs.sign \
  -pkeyopt rsa_padding_mode:pss \
  -pubin -inkey rsa-pss-publicKey.pem \
  -pkeyopt rsa_pss_saltlen:-1 \
  -pkeyopt digest:sha256

Signature Verified Successfully

GO 读取带pkeyopt的密钥

func pem_to_pri(pripem string) *rsa.PrivateKey {

    block, _ := pem.Decode([]byte(pripem))
    if block == nil || (block.Type != "PRIVATE KEY" && block.Type != "RSA PRIVATE KEY") {
        log.Fatal("failed to decode PEM", block)
        return nil
    }
    var oidPrivateKeyRsaPss = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 10}
    type pkcs8 struct {
        Version    int
        Algo       pkix.AlgorithmIdentifier
        PrivateKey []byte
    }
    var privKey pkcs8
    if _, err := asn1.Unmarshal(block.Bytes, &privKey); err != nil {
        return nil
    }

    if privKey.Algo.Algorithm.Equal(oidPrivateKeyRsaPss) {
        rsaPrivKey, err := x509.ParsePKCS1PrivateKey(privKey.PrivateKey)
        if err == nil {
            return rsaPrivKey
        }
    }
    rsaPrivKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)

    if err != nil {
        log.Println(err)
        return nil
    }

    return rsaPrivKey
}

parsing the rsa pss key manually

func loadPrivateKey(pemEncodedPK string) (crypto.PrivateKey, error) {
    var oidPrivateKeyRsaPss = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 10}
    block, _ := pem.Decode([]byte(pemEncodedPK))
    if block == nil {
        return nil, errors.New("empty block")
    }

    // taken from crypto/x509/pkcs8.go
    type pkcs8 struct {
        Version    int
        Algo       pkix.AlgorithmIdentifier
        PrivateKey []byte
        // optional attributes omitted.
    }
    var privKey pkcs8
    if _, err := asn1.Unmarshal(block.Bytes, &privKey); err != nil {
        return nil, err
    }

    if privKey.Algo.Algorithm.Equal(oidPrivateKeyRsaPss) {
        rsaPrivKey, err := x509.ParsePKCS1PrivateKey(privKey.PrivateKey)
        if err == nil {
            return rsaPrivKey, nil
        }
    }

    return nil, errors.New("unknown algorithm")
}

In order to let the client reuse the underlying connection we just need to read the body entirely and close it before we issue a new HTTP request.

package main

import (
    "context"
    "io"
    "io/ioutil"
    "log"
    "net/http"
    "net/http/httptrace"
)

func main() {
    // client trace to log whether the request's underlying tcp connection was re-used
    clientTrace := &httptrace.ClientTrace{
        GotConn: func(info httptrace.GotConnInfo) { log.Printf("conn was reused: %t", info.Reused) },
    }
    traceCtx := httptrace.WithClientTrace(context.Background(), clientTrace)

    // 1st request
    req, err := http.NewRequestWithContext(traceCtx, http.MethodGet, "http://example.com", nil)
    if err != nil {
        log.Fatal(err)
    }
    res, err := http.DefaultClient.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    if _, err := io.Copy(ioutil.Discard, res.Body); err != nil {
        log.Fatal(err)
    }
    res.Body.Close()
    // 2nd request
    req, err = http.NewRequestWithContext(traceCtx, http.MethodGet, "http://example.com", nil)
    if err != nil {
        log.Fatal(err)
    }
    _, err = http.DefaultClient.Do(req)
    if err != nil {
        log.Fatal(err)
    }
}

go http 参数设置示例

newClient := &http.Client{

        Timeout: time.Minute * 1, //设置超时时间

        Transport: &http.Transport{

            Dial: (&net.Dialer{

                Timeout:   30 * time.Second, //限制建立TCP连接的时间

                KeepAlive: 30 * time.Second,

            }).Dial,

            TLSHandshakeTimeout:   10 * time.Second, //限制 TLS握手的时间

            ResponseHeaderTimeout: 10 * time.Second, //限制读取response header的时间,默认 timeout + 5*time.Second

            ExpectContinueTimeout: 1 * time.Second,  //限制client在发送包含 Expect: 100-continue的header到收到继续发送body的response之间的时间等待。

            MaxIdleConns:          2,                //所有host的连接池最大连接数量,默认无穷大

            MaxIdleConnsPerHost:   1,                //每个host的连接池最大空闲连接数,默认2

            MaxConnsPerHost:       1,                //每个host的最大连接数量

            IdleConnTimeout:       3 * time.Minute,  //how long an idle connection is kept in the connection pool.
            TLSClientConfig:     &tls.Config{InsecureSkipVerify: true},

        },

    }

golang 获取指定uid 的用户目录

package main

import (
    "fmt"
    "os/user"
)

func main() {
    u, err := user.Current()
    if err != nil {
        fmt.Println("error")
    }
    fmt.Printf("u.Uid: %s, u.Gid: %s, u.Name: %s, u.HomeDir: %s, u.Username: %s\n",
        u.Uid, u.Gid, u.Name, u.HomeDir, u.Username)

    lu, err := user.Lookup("wohu")
    if err != nil {
        fmt.Println("error")
    }
    fmt.Printf("lu.Uid: %s, lu.Gid: %s, lu.Name: %s, lu.HomeDir: %s, lu.Username: %s\n",
        lu.Uid, lu.Gid, lu.Name, lu.HomeDir, lu.Username)

    li, err := user.LookupId("1000")
    if err != nil {
        fmt.Println("error")
    }
    fmt.Printf("li.Uid: %s, li.Gid: %s, li.Name: %s, li.HomeDir: %s, li.Username: %s\n",
        li.Uid, li.Gid, li.Name, li.HomeDir, li.Username)

    lg, err := user.LookupGroup("wohu")
    if err != nil {
        fmt.Println("error")
    }
    fmt.Printf("lg.Gid: %s, lg.Name: %s\n",
        lg.Gid, lg.Name)

    lgi, err := user.LookupGroupId("1000")
    if err != nil {
        fmt.Println("error")
    }
    fmt.Printf("lgi.Gid: %s, lgi.Name: %s\n",
        lgi.Gid, lgi.Name)

}

Referenced from:https://blog.csdn.net/wohu1104/article/details/106433469

cat main.go 

package main

import (
    "github.com/gotk3/gotk3/gtk"
    "log"
)

func main() {
    // Initialize GTK without parsing any command line arguments.
    gtk.Init(nil)

    // Create a new toplevel window, set its title, and connect it to the
    // "destroy" signal to exit the GTK main loop when it is destroyed.
    win, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
    if err != nil {
        log.Fatal("Unable to create window:", err)
    }
    win.SetTitle("Simple Example")
    win.Connect("destroy", func() {
        gtk.MainQuit()
    })

    // Create a new label widget to show in the window.
    l, err := gtk.LabelNew("Hello, gotk3!")
    if err != nil {
        log.Fatal("Unable to create label:", err)
    }

    // Add the label to the window.
    win.Add(l)

    // Set the default window size.
    win.SetDefaultSize(1920, 1080)
    //win.Move(100,100)

    // Recursively show all widgets contained in this window.
    win.ShowAll()

    // Begin executing the GTK main loop.  This blocks until
    // gtk.MainQuit() is run.
    gtk.Main()
}

go build -tags glib_2_66 .