30

値を指定して定数の名前を取得するにはどうすればよいですか?

より具体的には(そしてより読みやすい理解を得るために)、私はcrypto/tlsパッケージで作業しています。暗号スイートは定数として定義されます。

const (
    TLS_RSA_WITH_RC4_128_SHA            uint16 = 0x0005
    TLS_RSA_WITH_3DES_EDE_CBC_SHA       uint16 = 0x000a
    TLS_RSA_WITH_AES_128_CBC_SHA        uint16 = 0x002f
    TLS_RSA_WITH_AES_256_CBC_SHA        uint16 = 0x0035
    TLS_ECDHE_RSA_WITH_RC4_128_SHA      uint16 = 0xc011
    TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012
    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA  uint16 = 0xc013
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA  uint16 = 0xc014
)

サーバーとのハンドシェイクが成功すると、接続を介して合意された Ciphersuite に到達できます。

c, _ := tls.Dial("tcp", "somedomain.com:443", nil)
// Suppose everything went right

// This is the Ciphersuite for the conn:
cipher := c.ConnectionState().Ciphersuite

cipherここにuint16があります。TLS_RSA_WITH_3DES_EDE_CBC_SHAたとえば、それが合意されたものである場合、文字列として表示する方法はありますか?

4

3 に答える 3

26

: Go 1.4 以降、コマンドと組み合わせString()て Go の新機能を使用して、以下のコードを自動生成できます。詳細については、こちらを参照してください。generatestringer

ANisusの回答とは別に、次のことができます。

package main

import "fmt"
import "crypto/tls"

type Ciphersuite uint16

const (
    TLS_RSA_WITH_RC4_128_SHA            = Ciphersuite(tls.TLS_RSA_WITH_RC4_128_SHA)
    TLS_RSA_WITH_3DES_EDE_CBC_SHA       = Ciphersuite(tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA)
    TLS_RSA_WITH_AES_128_CBC_SHA        = Ciphersuite(tls.TLS_RSA_WITH_AES_128_CBC_SHA)
    TLS_RSA_WITH_AES_256_CBC_SHA        = Ciphersuite(tls.TLS_RSA_WITH_AES_256_CBC_SHA)
    TLS_ECDHE_RSA_WITH_RC4_128_SHA      = Ciphersuite(tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA)
    TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = Ciphersuite(tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA)
    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA  = Ciphersuite(tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA  = Ciphersuite(tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA)
)

func (cs Ciphersuite) String() string {
    switch cs {
    case TLS_RSA_WITH_RC4_128_SHA:
        return "TLS_RSA_WITH_RC4_128_SHA"
    case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
        return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"
    case TLS_RSA_WITH_AES_128_CBC_SHA:
        return "TLS_RSA_WITH_AES_128_CBC_SHA"
    case TLS_RSA_WITH_AES_256_CBC_SHA:
        return "TLS_RSA_WITH_AES_256_CBC_SHA"
    case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
        return "TLS_ECDHE_RSA_WITH_RC4_128_SHA"
    case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
        return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"
    case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
        return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"
    case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
        return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"
    }
    return "Unknown"
}

func main() {
    cs := TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
    fmt.Printf("0x%04x = %s\n", uint16(cs), cs)

    cs = TLS_RSA_WITH_RC4_128_SHA
    fmt.Printf("0x%04x = %s\n", uint16(cs), cs)

    cs = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
    fmt.Printf("0x%04x = %s\n", uint16(cs), cs)
}

外出先の遊び場でテストできます。

于 2013-10-03T09:23:49.803 に答える
22

それは不可能だと思います。
定数はコンパイル時に解決され、reflectパッケージには名前を取得できるものは何もありません。

私が提案するのは、次の名前のマップを作成することです。

var constLookup = map[uint16]string{
    tls.TLS_RSA_WITH_RC4_128_SHA:      `TLS_RSA_WITH_RC4_128_SHA`,
    tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA: `TLS_RSA_WITH_3DES_EDE_CBC_SHA`,
    ...
}
于 2013-10-03T09:05:30.010 に答える