1

我一直在使用 AWS Lambda in Action - Poccia 的源代码在用户池和身份池中创建用户。我不断收到错误:

Response:
{
  "errorMessage": "RequestId: f6511085-f22c-11e7-be27-534dfc5d6456 Process exited before completing request"
}

Request ID:
"f6511085-f22c-11e7-be27-534dfc5d6456"

Function Logs:
START RequestId: f6511085-f22c-11e7-be27-534dfc5d6456 Version: $LATEST
2018-01-05T15:27:38.890Z    f6511085-f22c-11e7-be27-534dfc5d6456    TypeError: Pass phrase must be a buffer
    at TypeError (native)
    at pbkdf2 (crypto.js:576:20)
    at Object.exports.pbkdf2 (crypto.js:558:10)
    at computeHash (/var/task/lib/cryptoUtils.js:10:10)
    at InternalFieldObject.ondone (/var/task/lib/cryptoUtils.js:19:4)
END RequestId: f6511085-f22c-11e7-be27-534dfc5d6456
REPORT RequestId: f6511085-f22c-11e7-be27-534dfc5d6456  Duration: 113.62 ms Billed Duration: 200 ms     Memory Size: 128 MB Max Memory Used: 33 MB  
RequestId: f6511085-f22c-11e7-be27-534dfc5d6456 Process exited before completing request

我是 AWS 服务的新手,不确定为什么会发生此错误。下面是我尝试使用的 Lambda 函数,下面是它引用的 cryptoUtils.js 脚本。

console.log('Loading function');
//Loading standard module, such as crypto and the AWS SDK
var AWS = require('aws-sdk');
var crypto = require('crypto');
var cryptoUtils = require('./lib/cryptoUtils.js'); //Loading the cryptoUtils.js module shared code, included in the uploaded ZIP archive
var config = require('./config.json'); //Loading the configuration in the config.json file, included in the uploaded ZIP archive


var dynamodb = new AWS.DynamoDB({
  accessKeyId: 'usingKEYfromIAM',
  secretAccessKey: 'usingKEYfromIAM',
}); //Getting the Amazon DynamoDB service object
var ses = new AWS.SES(); //Getting Amazon SES service object

function storeUser(email, password, salt, fn) { //The storeUser() function stores the new user in the DynamoDB table.
  var len = 128;
  crypto.randomBytes(len, function(err, token) { //Arandom token sent in the validation email and used to validate a user
    if (err) return fn(err);
    token = token.toString('hex');
    dynamodb.putItem({ //Putting an item in the DynamoDB table
      TableName: config.DDB_TABLE, //The table name is taken from the config.json configuration file.
      //Most of the data is string ("S"), but the verifiede attribute is Boollean ("BOOL"), 
      //new users aren't verified (false), and the randomly generated token is stored in the "verifyToken" attribute
      Item: {
        email: {
          S: email
        },
        passwordHash: {
          S: password
        },
        passwordSalt: {
          S: salt
        },
        verified: {
          BOOL: false
        },
        verifyToken: {
          S: token
        }
      },
      ConditionExpression: 'attribute_not_exists (email)' //This condition avoids overwriting existing users (with the same email).
    }, function(err, data) {
      if (err) return fn(err);
      else fn(null, token); //The storeUser() function returns the randomly generated token.
    });
  });
}

function sendVerificationEmail(email, token, fn) { //The send-VerificationEmail() funciton sends the verification email to the new user.
  var subject = 'Verification Email for ' + config.EXTERNAL_NAME;
  //The verification link, to the verify.hrml page, passes the randomly generated token as a query parameter.
  var verificationLink = config.VERIFICATION_PAGE + '?email=' + encodeURIComponent(email) + '&verify=' + token;
  ses.sendEmail({ //Sending the email in HTML format
    Source: config.EMAIL_SOURCE,
    Destination: {
      ToAddresses: [
        email
      ]
    },
    Message: {
      Subject: {
        Data: subject
      },
      Body: {
        Html: {
          Data: '<html><head>' + '<meta http-equiv= "Content-Type" content="test/html; charset=UTF-8" />' +
            '<title>' + subject + '</title>' + '</head><body>' + 'Please <a href="' + verificationLink +
            '">click here to verify your email address</a> or a copy & paste the following link in a browser:' +
            '<br><br>' + '<a href="' + verificationLink + '">' + verificationLink + '</a>' + '</body></html>'
        }
      }
    }
  }, fn);
}

exports.handler = (event, context, callback) => { //The function that's exported and can be invoked using AWS Lambda as createUser
  //Getting the input parameters (email, password) from the event
  var email = event.email;
  var clearPassword = event.password;

  //Using compute-Hash() from cryptoUtils.js to salt the password.
  cryptoUtils.computeHash(clearPassword, function(err, salt, hash) {
    if (err) {
      callback('Error in hash: ' + err);
    } else {
      storeUser(email, hash, salt, function(err, token) { //Storing the user via the storeUser()function
        if (err) {
          if (err.code == 'ConditionalCheckFailedException') { //Checking if the database error is due to the email being already prsent in the database
            //userID already found
            callback(null, {
              created: false
            });
          } else {
            callback('Error in storUser: ' + err);
          }
        } else {
          sendVerificationEmail(email, token, function(err, data) { //Sending the verification email
            if (err) {
              callback('Error in sendVerificationEmail: ' + err);
            } else {
              callback(null, {
                created: true
              });
            }
          });
        }
      });
    }
  });
};

var crypto = require('crypto');

function computeHash(password, salt, fn) {
  var len = 512;
  var iterations = 4096;
  var digest = 'sha512';


  if (3 == arguments.length) {
    crypto.pbkdf2(password, salt, iterations, len, digest, function(err, derivedKey) {
      if (err) return fn(err);
      else fn(null, salt, derivedKey.toString('base64'));
    });
  } else {
    fn = salt;
    crypto.randomBytes(len, function(err, solat) {
      if (err) return fn(err);
      salt = salt.toString('base64');
      computeHash(password, salt, fn);
    });
  }
}

module.exports.computeHash = computeHash;

如果有人有任何建议或需要更多信息来帮助我确定错误发生的原因,我将不胜感激。谢谢你。

4

3 回答 3

0

你传递的密码是一个数字?

如果是这样:

  • 将其转换为字符串。

  • 如果你不想这样做,你可以传递一个 Buffer 对象:

使用类方法传递一个 Buffer 对象Buffer.from(string[, encoding])
https://nodejs.org/api/buffer.html#buffer_class_method_buffer_from_string_encoding

crypto.pbkdf2(Buffer.from(password, 'utf8'), salt, iterations, len, digest, function(err, derivedKey) {
    if (err) return fn(err);
    else fn(null, salt, derivedKey.toString('base64'));
});

希望能帮助到你!

于 2018-01-05T18:13:35.133 回答
0

错误“TypeError:密码短语必须是缓冲区”

确实建议尝试输入字符串的缓冲区转换

在你的测试之前 Buffer.from(password, 'utf8')

您是否验证输入值是编码“utf8”,而不是其他一些编码,例如 base64 或 latin1?

Node.js 支持的编码列表

于 2018-07-30T01:49:01.623 回答
0

var crypto = require('crypto');

function computeHash(password, salt, fn) {
	// Bytesize. The larger the numbers, the better the security, but the longer it will take to complete
	var len = 512;
	var iterations = 4096;
	var digest = 'sha512';

	if (3 == arguments.length) {
	crypto.pbkdf2(Buffer.from(password, 'utf8'), salt, iterations, len, digest, function(err, derivedKey) {
    if (err) return fn(err);
    else fn(null, salt, derivedKey.toString('base64'));
});
	} else {
		fn = salt;
		crypto.randomBytes(len, function(err, salt) {
			if (err) return fn(err);
			salt = salt.toString('base64');
			computeHash(password, salt, fn);
		});
	}
}

module.exports.computeHash = computeHash;

于 2018-01-05T21:32:10.067 回答