Arduino HMAC-SHA1的base64编码格式输出与JAVA / python / online工具

时间:2015-08-17 11:36:08

标签: twitter oauth arduino

我正在开发一个Arduino项目,该项目需要基于OAuth 1.0的授权身份验证才能连接到云。这类似于[授权对Twitter API的请求] [1],我陷入了[创建签名] [2]的步骤。创建签名的整个过程需要像encodeURL,base64encode和hmac-sha1这样的算法。在我的Arduino项目中,我使用Cryptosuite(链接3)库为hmac-sha1和arduino-base64(链接4)库为base64encode。他们两个都分开工作。但是,我需要获得hmac-sha1的base64格式输出。所以我试过这个:

#include <avr/pgmspace.h>
#include <sha1.h>
#include <Base64.h>

uint8_t *in, out, i;
char b64[29];
static const char PROGMEM b64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char key[] = "testKey";
char basestring[] = "testing";


void printHash(uint8_t* hash) {
  int i;
  for (i=0; i<20; i++) {
    Serial.print("0123456789abcdef"[hash[i]>>4]);
    Serial.print("0123456789abcdef"[hash[i]&0xf]);
  }
  Serial.println();
}

void setup() {
  Serial.begin(115200);

  Serial.print("Result:");
  Sha1.initHmac((uint8_t*)key, strlen(key));
  Sha1.print(basestring);
  printHash(Sha1.resultHmac());
  Serial.println();

  // encoding
  char* input;
  input = (char*)(Sha1.resultHmac());
  int inputLen = strlen(input);
  int encodedLen = base64_enc_len(inputLen);
  char encoded[encodedLen];

  // note input is consumed in this step: it will be empty afterwards
  base64_encode(encoded, input, inputLen); 

  Serial.print("base64 result: ");
  Serial.println(encoded);

}

void loop() {
}

我得到的printHash的输出是60d41271d43b875b791e2d54c34bf3f018a29763,这与在线验证工具(链接5)完全相同。 但是,我应该为base64结果得到YNQScdQ7h1t5Hi1Uw0vz8Biil2M =。但我得到了L18B0HicKRhuxmB6SIFpZP + DpHxU似乎错了。我也试过编写一个JAVA程序和一个python程序,它也说base64结果的输出应该是YNQScdQ7h1t5Hi1Uw0vz8Biil2M =

我还发现了这篇文章:Arduino SHA1-HMAC与base64编码和Python之间的问题(链接6)。我也尝试过Adafruit-Tweet-Receipt提到的整洁功能(链接7)。

  // base64-encode SHA-1 hash output.  This is NOT a general-purpose base64
  // encoder!  It's stripped down for the fixed-length hash -- always 20
  // bytes input, always 27 chars output + '='.
  for(in = Sha1.resultHmac(), out=0; ; in += 3) { // octets to sextets
    b64[out++] =   in[0] >> 2;
    b64[out++] = ((in[0] & 0x03) << 4) | (in[1] >> 4);
    if(out >= 26) break;
    b64[out++] = ((in[1] & 0x0f) << 2) | (in[2] >> 6);
    b64[out++] =   in[2] & 0x3f;
  }
  b64[out] = (in[1] & 0x0f) << 2;
  // Remap sextets to base64 ASCII chars
  for(i=0; i<=out; i++) b64[i] = pgm_read_byte(&b64chars[b64[i]]);
  b64[i++] = '=';
  b64[i++] = 0;

我在这里犯过什么错误? 谢谢!

1 个答案:

答案 0 :(得分:0)

完整的例子将是:

#include <avr/pgmspace.h>
#include <sha1.h>
#include <Base64.h>

char key[] = "testKey";
char basestring[] = "testing";

void printHash(uint8_t* hash) {  
  for (int i=0; i<20; i++) {
    Serial.print("0123456789abcdef"[hash[i]>>4]);
    Serial.print("0123456789abcdef"[hash[i]&0xf]);
  }
  Serial.println();
}

void setup() {
  Serial.begin(115200);

  Serial.print("Input:              ");
  Serial.println(basestring);

  Serial.print("Key:                ");
  Serial.println(key);

  Serial.print("Hmac-sha1 (hex):    ");
  Sha1.initHmac((uint8_t*)key, strlen(key));
  Sha1.print(basestring);

  uint8_t *hash;
  hash = Sha1.resultHmac();
  printHash(hash);

  // base64 encoding
  char* input = (char*) hash;
  int inputLen = strlen(input) - 1; // skip null termination

  int encodedLen = base64_enc_len(inputLen);
  char encoded[encodedLen];

  // note input is consumed in this step: it will be empty afterwards
  base64_encode(encoded, input, inputLen); 
  Serial.print("Hmac-sha1 (base64): ");
  Serial.println(encoded);
}

void loop() { }

输出:

Input:              testing
Key:                testKey
Hmac-sha1 (hex):    60d41271d43b875b791e2d54c34bf3f018a29763
Hmac-sha1 (base64): YNQScdQ7h1t5Hi1Uw0vz8Biil2M=