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

Twitter Arduino HMAC-SHA1的base64编码格式输出与JAVA/python/online工具不匹配,twitter,oauth,arduino,Twitter,Oauth,Arduino,我正在从事一个Arduino项目,该项目需要基于OAuth 1.0的授权认证才能连接到云。这与[授权对Twitter API的请求][1]类似,我被困在[创建签名][2]的步骤中。创建签名的整个过程需要像encodeURL、base64encode和hmac-sha1这样的算法。在我的Arduino项目中,我对hmac-sha1使用Cryptosuite(链接3)库,对base64encode使用Arduino-base64(链接4)库。他们两人各自工作得很好。但是,我需要获得hmac-sha1

我正在从事一个Arduino项目,该项目需要基于OAuth 1.0的授权认证才能连接到云。这与[授权对Twitter API的请求][1]类似,我被困在[创建签名][2]的步骤中。创建签名的整个过程需要像encodeURL、base64encode和hmac-sha1这样的算法。在我的Arduino项目中,我对hmac-sha1使用Cryptosuite(链接3)库,对base64encode使用Arduino-base64(链接4)库。他们两人各自工作得很好。但是,我需要获得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() {
}
#包括
#包括
#包括
输入,输出,i;
char b64[29];
静态常量字符程序b64chars[]=“ABCDEFGHIJKLMNOPQRSTUVWXYZABCDFGHIJKLMNOPQRSTUVWXYZ0123456789+/”;
char key[]=“testKey”;
char basestring[]=“测试”;
无效打印哈希(uint8\u t*hash){
int i;
对于(i=0;i>4]);
Serial.print(“0123456789abcdef”[hash[i]&0xf]);
}
Serial.println();
}
无效设置(){
序列号开始(115200);
序列号。打印(“结果:”);
Sha1.initHmac((uint8_t*)键,strlen(键));
Sha1.打印(基线);
printHash(Sha1.resulthac());
Serial.println();
//编码
字符*输入;
输入=(char*)(Sha1.resultHmac());
int inputLen=strlen(输入);
int encodedLen=base64_enc_len(inputLen);
字符编码的[encodedLen];
//注:此步骤消耗输入:之后输入为空
base64_编码(编码、输入、输入);
Serial.print(“base64结果:”);
Serial.println(编码);
}
void循环(){
}
我得到的printHash的输出是60d41271d43b875b791e2d54c34bf3f018a29763,这与在线验证工具(链接5)完全相同。 但是,对于base64结果,我应该得到YNQScdQ7h1t5Hi1Uw0vz8Biil2M=的值。但我得到了L18B0HicKRhuxmB6SIFpZP+DpHxU,这似乎是错误的。我还尝试编写了一个JAVA程序和一个python程序,其中还提到base64结果的输出应该是YNQScdQ7h1t5Hi1Uw0vz8Biil2M=

我还发现了这篇文章:Arduino SHA1-HMAC与base64编码和Python之间的问题(链接6)。我还尝试了Adafruit推特收据中提到的tidy功能(链接7)

//base64编码SHA-1哈希输出。这不是通用base64
//编码器!它是为固定长度散列而精简的--总是20
//字节输入,总是27个字符输出+'='。
对于(in=Sha1.resultHmac(),out=0;in+=3){//八位字节到六位字节
b64[out++]=in[0]>>2;
b64[out++]=((in[0]&0x03)>4);
如果(输出>=26)中断;
b64[out++]=((in[1]&0x0f)>6);
b64[out++]=in[2]&0x3f;
}

b64[out]=(in[1]&0x0f)因此完整示例如下:

#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() { }

因此,完整的示例将是:

#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() { }

错误警报,我尝试访问Sha1.resultmac()两次。这使得sha结果不同。如果出现错误警报,我尝试访问Sha1.resultHmac()两次。这使得sha结果不同。
Input:              testing
Key:                testKey
Hmac-sha1 (hex):    60d41271d43b875b791e2d54c34bf3f018a29763
Hmac-sha1 (base64): YNQScdQ7h1t5Hi1Uw0vz8Biil2M=