Glad Larry has working code now... As I mentioned before in this thread, I'm working on this functional interface for the message-digesting/secure-hashing, and this whole discussion reads like a use case for the "why?" ;-)
It "proofs" to me that there may be real value in a more user-friendly approach than the one offered by java.security.MessageDigest. So instead of writing: (let [... nonce-as-bytes (.getBytes nonce) created-as-bytes (.getBytes created) secret-as-bytes (.getBytes secret) digest (.digest (doto (java.security.MessageDigest/getInstance "sha1") .reset (.update nonce-as-bytes) (.update created-as-bytes) (.update secret-as-bytes))) …] my library lets you write: (let [… digest (md/digest :sha-1 :utf-8 nonce created secret) …] and the advantages of the more functional approach is much more than just saving a few lines of code! Although it still needs some more work, any feedback on "https://github.com/franks42/clj.security.message-digest" is much appreciated. Regards, FrankS. On Mar 4, 2013, at 1:31 PM, larry google groups <lawrencecloj...@gmail.com> wrote: > I finally got this to work. Many thanks for all of the help that I was > given here. > > The final, winning combination was: > > (let [username (get-in @um/interactions [:omniture-api- > credentials :username]) > secret (get-in @um/interactions [:omniture-api-credentials :shared- > secret]) > random-number (math/round (* (rand 1 ) 1000000)) > nonce (DigestUtils/md5Hex (str random-number)) > nonce-encoded-base64 (base64-encode (.getBytes nonce)) > date-formatter (new SimpleDateFormat "yyyy-MM-dd'T'HH:mm:ss") > created (.format date-formatter (new Date)) > nonce-as-bytes (.getBytes nonce) > created-as-bytes (.getBytes created) > secret-as-bytes (.getBytes secret) > digest (.digest > (doto (java.security.MessageDigest/getInstance > "sha1") > .reset > (.update nonce-as-bytes) > (.update created-as-bytes) > (.update secret-as-bytes))) > digest-base64 (base64-encode digest) > header (apply str " UsernameToken Username=\"" username "\" > PasswordDigest=\"" digest-base64 "\" Nonce=\"" nonce-encoded-base64 > "\" Created=\"" created "\"")] > header) > > > > On Mar 4, 10:47 am, larry google groups <lawrencecloj...@gmail.com> > wrote: >> I have been having problems making an API call to Omniture. I have >> exchanged a dozen emails with a developer at Omniture, and he gave me >> the impression that I was constructing my security codes incorrectly. >> So now I am confronting my ignorance over how Java handles certain >> conversions. >> >> The developer at Omniture sent me this explanation in an email: >> >> " The security digest is formed from a sha1 hash of the following >> string concatenation: >> digest = sha1( Binary Nonce + Created Time String + API Secret Hex >> String (32 bytes) ) " >> >> I have been struggling with this for several days and I have tried at >> least (literally) 200 variations on this bit of code: >> >> (let [username (get-in @um/interactions [:omniture-api- >> credentials :username]) >> secret (get-in @um/interactions [:omniture-api- >> credentials :shared-secret]) >> nonce (DigestUtils/md5Hex (random-string 32)) >> nonce-encoded-base64 (Base64/encodeBase64 (.getBytes nonce)) >> date-formatter (new SimpleDateFormat "yyyy-MM- >> dd'T'HH:mm:ss'Z'") >> created (.format date-formatter (new Date)) >> digest-as-string (apply str (.getBytes nonce) created secret) >> digest (.digest (java.security.MessageDigest/getInstance "sha1") >> digest-as-string) >> header (apply str " UsernameToken Username=\"" username "\" >> PasswordDigest=\"" digest "\" Nonce=\"" nonce-encoded-base64 "\" >> Created=\"" created "\"")] >> header) >> >> This version gives me: >> >> "Exception in the main function: " #<ClassCastException >> java.lang.ClassCastException: java.lang.String cannot be cast to [B> >> >> For a long time I was using this for the last 3 lines: >> >> digest-as-string (apply str nonce created secret) >> digest (.digest (java.security.MessageDigest/getInstance "sha1") >> (.getByes digest-as-string)) >> header (apply str " UsernameToken Username=\"" username "\" >> PasswordDigest=\"" digest "\" Nonce=\"" nonce-encoded-base64 "\" >> Created=\"" created "\"") >> >> Here I wrapped the whole digest-as-string in (.getBytes) so there was >> no Java error, but this simply did not work when I pinged Omniture. >> >> In his email, he seems to suggest that the nonce should be binary but >> that the date and the secret should be strings: >> >> digest = sha1( Binary Nonce + Created Time String + API Secret Hex >> String (32 bytes) ) " >> >> But, as I said, when I tried this I got the ClassCastException. >> >> No doubt some of my confusion is due to my ignorance of Java. >> >> I was able to take their sample PHP code and get that to successfully >> ping their API, however, my company has an official policy of moving >> to the JVM, and of course I have a personal preference to work with >> Clojure. So I'd like to figure out how to get this to work in Clojure. >> (Needless to say that Omniture doesn't offer sample code in Clojure.) >> >> I have been using clj-http to make the actual POST calls to Omniture. >> Since I am on a Mac, I have been using the excellent Charles network >> debugger (http://www.charlesproxy.com/) to watch the actual posts >> being made. Everything looks correct, except that in the end the >> requests fails, apparently because the digest is malformed. >> >> Any suggestions? > > -- > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with your > first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en > --- > You received this message because you are subscribed to the Google Groups > "Clojure" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to clojure+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/groups/opt_out. > > -- -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.