Go言語(golang)でWSSE認証する
某ブログサービスでコマンドラインからAPIで記事を投稿するのに、
WSSE認証とBasic認証の二択だったので書いてみました。
なにか書き方が間違ってるのか、たまにエラーになります。
結局、はてなブログにしたので、そこらへんは未検証のままです。
package main import ( "crypto/rand" "crypto/sha1" "encoding/base64" "fmt" "net/http" "time" ) type WSSE struct { username string password string nonceSize int } func New(username, password string, nonceSize int) *WSSE { if nonceSize < 1 { nonceSize = 20 } return &WSSE{ username: username, password: password, nonceSize: nonceSize, } } func createNonce(size int) (string, error) { nonce := make([]byte, size) _, err := rand.Read(nonce) if err != nil { return "", err } return fmt.Sprintf("%x", nonce), nil } func (w *WSSE) Create() (string, error) { created := time.Now().Format(`2006-01-02T15:04:05Z`) n, err := createNonce(w.nonceSize) if err != nil { return "", err } h := sha1.New() h.Write([]byte(n)) h.Write([]byte(created)) h.Write([]byte(w.password)) digest := base64.URLEncoding.EncodeToString(h.Sum(nil)) nonce := base64.URLEncoding.EncodeToString([]byte(n)) format := `UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"` return fmt.Sprintf(format, w.username, digest, nonce, created), nil } func main() { w := New("username", "password", 14) req, err := http.NewRequest("GET", "https://example.com", nil) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } s, err := w.Create() if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } req.Header.Set("X-WSSE", s) resp, err := http.DefaultClient.Do(req) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } }