Twitter OCaml中的HMAC-SHA1签名?

Twitter OCaml中的HMAC-SHA1签名?,twitter,ocaml,sha1,hmac,reason,Twitter,Ocaml,Sha1,Hmac,Reason,我试图向Twitter API发出请求,他们要求我签署请求。最后一部分需要通过HMAC-SHA1哈希算法进行签名。有没有一种简单的方法可以得到它?Hannes伸出手来给我答案(用下面的ReasonML语法,而不是OCaml): 有了它,这里有一个从转换而来的签名函数(参数和值也取自该页面,因此输出可验证为正确): 编辑:我最初说Hannes是OCaml的nocrypto库的作者——实际上是David Kaloper。对此非常抱歉,感谢Daniel Bünzli指出这一点 汉内斯不是《nocryp

我试图向Twitter API发出请求,他们要求我签署请求。最后一部分需要通过HMAC-SHA1哈希算法进行签名。有没有一种简单的方法可以得到它?

Hannes伸出手来给我答案(用下面的ReasonML语法,而不是OCaml):

有了它,这里有一个从转换而来的签名函数(参数和值也取自该页面,因此输出可验证为正确):


编辑:我最初说Hannes是OCaml的nocrypto库的作者——实际上是David Kaloper。对此非常抱歉,感谢Daniel Bünzli指出这一点

汉内斯不是《nocrypto》的作者。《nocrypto》的作者是大卫·卡洛普。请参阅,一旦我从Nocrypto.Hash.SHA1.hmac获得了输出,我需要通过B64.encode运行它,以获得与您的测试用例相匹配的
hCtSmYh+iHYCEqBWrE7C7hYmtUk=
Nocrypto.Hash.SHA1.hmac key::(Cstruct.of_string signingKey) (Cstruct.of_string output) |> Cstruct.to_string
let signRequest clientId clientSecret method uri params :string => {
  let tmp = params |> List.sort (fun (a, _) (b, _) => compare a b);
  let collectedParamsString =
    List.map
      (
        fun (header: string, values: list string) => {
          let nextStr =
            List.fold_left
              (
                fun innerAcc value => {
                  let nextItem =
                    /* Using `Userinfo here is weird, but it's the only component I could get to properly percent-encode things in the same way Twitter expects it */
                    Uri.pct_encode component::`Query_key header ^
                    "=" ^ Uri.pct_encode component::`Userinfo value;
                  let final = innerAcc @ [nextItem];
                  print_endline (value ^ " => " ^ String.concat "&" final);
                  final
                }
              )
              []
              values |>
            String.concat "&";
          nextStr
        }
      )
      tmp |>
    String.concat "&";
  let output =
    String.uppercase_ascii method ^
    "&" ^
    Uri.pct_encode component::`Userinfo uri ^
    "&" ^ Uri.pct_encode component::`Userinfo collectedParamsString;
  let signingKey =
    Uri.pct_encode component::`Userinfo clientId ^
    "&" ^ Uri.pct_encode component::`Userinfo clientSecret;
  Cstruct.to_string (
    Nocrypto.Hash.SHA1.hmac key::(Cstruct.of_string signingKey) (Cstruct.of_string output)
  )
};

let signature =
  signRequest
    "post"
    "https://api.twitter.com/1.1/statuses/update.json"
    "kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw"
    "LswwdoUaIvS8ltyTt5jkRh4J50vUPVVHtR2YPi5kE"
    [
      ("status", ["Hello Ladies + Gentlemen, a signed OAuth request!"]),
      ("include_entities", ["true"]),
      ("oauth_consumer_key", ["xvz1evFS4wEEPTGEFPHBog"]),
      ("oauth_nonce", ["kYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg"]),
      ("oauth_signature_method", ["HMAC-SHA1"]),
      ("oauth_timestamp", ["1318622958"]),
      ("oauth_token", ["370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb"]),
      ("oauth_version", ["1.0"])
    ];
/* let signature : string = "hCtSmYh+iHYCEqBWrE7C7hYmtUk */