ColdFusion oAuth RSA-SHA1 authorisation for Xero wrapper -


i'm writing wrapper xero api, using oauth , two-legged authentication. "private" application, xero calls it, requires rsa-sha1 signature. coldfusion oauth wrapper doesn't have function encrypting in rsa-sha1, hmac-sha1. on cf9.

consequently, in course of running request, following error:

signature_method_rejected private applications must use rsa-sha1 signature method 

so, looks call working, issue signature method. found thought looked solution created, follows:

<cffunction name="rsa_sha1" returntype="string" access="public" descrition="rsa-sha1 computation based on supplied private key , supplied base signature string.">                <cfargument name="signkey" type="string" required="true" hint="base64 formatted pkcs8 private key">                <cfargument name="signmessage" type="string" required="true" hint="msg sign">                <cfargument name="sformat" type="string" required="false" default="utf-8">                 <cfset var jkey = javacast("string", arguments.signkey)>                <cfset var jmsg = javacast("string",arguments.signmessage).getbytes(arguments.sformat)>                 <cfset var key = createobject("java", "java.security.privatekey")>                <cfset var keyspec = createobject("java","java.security.spec.pkcs8encodedkeyspec")>                <cfset var keyfactory = createobject("java","java.security.keyfactory")>                <cfset var b64dec = createobject("java", "sun.misc.base64decoder")>                 <cfset var sig = createobject("java", "java.security.signature")>                 <cfset var byteclass = createobject("java", "java.lang.class")>                <cfset var bytearray = createobject("java","java.lang.reflect.array")>                 <cfset byteclass = byteclass.forname(javacast("string","java.lang.byte"))>                <cfset keybytes = bytearray.newinstance(byteclass, javacast("int","1024"))>                <cfset keybytes = b64dec.decodebuffer(jkey)>                <!--- keybytes = 48-111-10345-125-5349-114-581835-28-330-3984120-2848-4384-1-43 --->                 <cfset sig = sig.getinstance("sha1withrsa", "sunjsse")> <!--- error occurs on line below --->                <cfset sig.initsign(keyfactory.getinstance("rsa").generateprivate(keyspec.init(keybytes)))>                 <cfset sig.update(jmsg)>                <cfset signbytes = sig.sign()>                 <cfreturn tobase64(signbytes)>          </cffunction> 

it receives following arguments:

sformat     utf-8 signkey     0jxxxxxxxxxxxxxxxxxxxp& signmessage     get&https%3a%2f%2fapi.xero.com%2fapi.xro%2f2.0%2fcontacts&contactid%3d%26contactnumber%3d%26name%3d7-eleven%26oauth_consumer_key%3dxxxxxxxxxxxxxxxx%26oauth_nonce%3dxxxxxxxxxxxxxxxx%26oauth_signature_method%3drsa-sha1%26oauth_timestamp%3d1339055484%26oauth_version%3d1.0  

however, produces following error:

could not read ber data.(asn1lengths.determinelengthlen: length greater 0x7fff,ffff.)  coldfusion cannot determine line of template caused error. caused error in exception handling subsystem.  

can shed light on this?

edit ----

enter image description here

there link uploading public cert, did. there note saying: "note, private applications, consumer token , secret used access token , secret.". assuming need "consumer secret" value shown there in order sign request. being case, how convert secret key value rsa-sh1 format signature?

(summary comments)

according their api private applications must generate rsa public/private pair (one time event). upload public certificate server, , use private key sign requests using rsa-sha1. if followed instructions in link private key in pem format, key value encoded in base64, enclosed within begin/end wrapper:

    -----begin rsa private key-----     xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx     xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx     ....     -----end rsa private key----- 

you need extract portion between wrapper before using key pkcs8encodedkeyspec. there @ least 3 ways that. simplest option use string functions:

    // read in  key file , remove wrapper     pathtokey = "c:/path/to/file/privatekey.pem";     rawkey = fileread( pathtokey );     rawkey = replace( rawkey, "-----begin rsa private key-----"& chr(10), "" );     rawkey = replace( rawkey, "-----end rsa private key-----", "" );      yourmessage = "get&https%3a%2f%2fapi.xero.com%2fapi.xro%2f2.0%2f...";     signature = rsa_sha1( rawkey, yourmessage, "utf-8" ); 

another option use bouncycastle pemreader class. (and supports password protected keys).

    pathtokey  = "c:/path/to/file/privatekey.pem";     provider   = createobject("java", "org.bouncycastle.jce.provider.bouncycastleprovider").init();     security   = createobject("java", "java.security.security").addprovider( provider );     filereader = createobject("java", "java.io.filereader").init( pathtokey );     keyreader  = createobject("java", "org.bouncycastle.openssl.pemreader").init( filereader);     privatekey = keyreader.readobject().getprivate();     rawkey     = binaryencode( privatekey.getencoded(), "base64" );     yourmessage = "get&https%3a%2f%2fapi.xero.com%2fapi.xro%2f2.0%2fcontacts&....";     signature  = rsa_sha1( rawkey, yourmessage, "utf-8" ); 

yet option convert key der format openssl

    $ openssl pkcs8 -topk8 -in privatekey.pem -outform der -nocrypt -out privatekey.pk8      pathtokey = "c:/path/to/file/privatekey.pk8";     bytes = binaryencode( filereadbinary(pathtokey), "base64");     yourmessage = "get&https%3a%2f%2fapi.xero.com%2fapi.xro%2f2.0%2f...";     signature = rsa_sha1(rawkey, testmessage, "utf-8"); 

note if posted actual private key here (or on forum), compromised. recommend generating new keys.


Comments

Popular posts from this blog

django - How can I change user group without delete record -

java - Need to add SOAP security token -

java - EclipseLink JPA Object is not a known entity type -