Flutter / Dart:避免以纯文本格式存储密码

时间:2018-08-02 15:27:08

标签: dart flutter

我在Flutter中使用Dart邮件程序,并且有一条评论说:

  

如何使用和存储密码由您决定。谨防将密码存储在纯文本中。

有什么方法可以哈希密码?如何避免将其存储为纯文本格式?

3 个答案:

答案 0 :(得分:1)

将密码以纯文本格式存储在任何地方通常不是一个好主意。但是,您处理密码的方式取决于平台。

颤振

flutter_secure_storage软件包使用iOS上的Keychain和Android上的KeyStore来存储密码(或令牌)。

// Create storage
final storage = FlutterSecureStorage();

// Read secret 
String value = await storage.read(key: key);

// Write secret 
await storage.write(key: key, value: value);

请注意,对于Android,最小API是18。

Dart服务器

如果要制造服务器,则更重要的是不要以纯文本形式存储用户密码。如果服务器受到攻击,攻击者将可以访问所有密码,并且许多用户在多个帐户中使用相同的密码。

最好使用OAuth2将身份验证交给Google或Facebook或其他受信任的第三方。但是,如果您要进行自己的授权,则应使用盐对密码进行哈希处理并保存哈希,而不要保存密码本身。如果服务器受到威胁,这会使攻击者更难获得用户密码。

基本实现可以使用Dart团队的crypto软件包。

// import 'package:crypto/crypto.dart';
// import 'dart:convert';

var password = 'password123';
var salt = 'UVocjgjgXg8P7zIsC93kKlRU8sPbTBhsAMFLnLUPDRYFIWAk';
var saltedPassword = salt + password;
var bytes = utf8.encode(saltedPassword);
var hash = sha256.convert(bytes);

保存盐和哈希。放弃密码。为每个用户使用不同的盐。

要使暴力破解更加困难,还可以签出dbcrypt软件包。

答案 1 :(得分:0)

如果您想散列

使用password_hash软件包。他们的示例代码非常易于使用:

var generator = new PBKDF2();
var salt = Salt.generateAsBase64String();
var hash = generator.generateKey("mytopsecretpassword", salt, 1000, 32);

同时存储hashsalt,然后可以通过使用其他人的密码和保存的盐运行generator.generateKey函数来验证其他人的密码尝试。

您真正想要的

如果您尝试自动登录,那么您当然需要原始密码,而不是哈希。您有几种选择

  1. 如果将要安装您的应用程序的设备是安全的,例如它是某些公司拥有的设备,必须由员工登录,则请以纯文本格式进行安装。没关系就像任何公司的安全政策一样,您必须确保在清理电子设备之前先擦拭硬盘驱动器(并确保没有人可以走进来拿走iPad或其他东西)。

  2. 如果组织外部的未知人员将安装您的应用,则必须让他们登录并使用他们的电子邮件,或者打开一个API来代表他们发送电子邮件(以防止从您的电子邮件中发送垃圾邮件)。该应用程序将向该API发送POST以发送电子邮件。如果您在应用程序中具有纯文本密码,他们可以在自己的设备上找到该密码并将其滥用。

答案 2 :(得分:0)

此回复来晚了,但这是我存储和使用密码的方法,该密码用于使用Flutter中的mailer向收件人发送电子邮件。希望对任何遇到此问题的人都有帮助。

首先,我下载了crypton package。然后,我创建了一个单独的dart文件,在其中处理与发送邮件有关的所有事情,我将其称为mailer。在该文件中,我指定了密码,使用密码加密,然后使用解密的密码发送电子邮件。

下面是我的mailer.dart文件的代码:

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:mailer/mailer.dart';
import 'package:mailer/smtp_server.dart';
import 'package:intl/intl.dart';
import 'package:crypton/crypton.dart';

class Mailer {
  //the variable below we use to encrypt and decrypt the password
  RSAKeypair _rsaKeypair = RSAKeypair.fromRandom();
  //Below we set the password as a private variable
  String _password = 'mySecurePassword';
  
  //We set an encrypted variable that will store the encrypted password;
  String _encrypted;

  //The function below sets the encrypted variable by assigning it the encrypted value of the password
  void setEncrypt () {
    _encrypted = _rsaKeypair.publicKey.encrypt(_password);
  }

  //The function below is responsible for sending the email to the recipients and it is what we call when we want to send an email   
  emailSender({@required String emailRecipient, @required List<String> paths}) async {
    //We call the setEncrypt() function to assign the correct value to the encrypted variable
    setEncrypt();
    String username = 'email@email.com';
    //We asign the decrypted value of encrypted to the password we provide to the smtpServer 
    String password = _rsaKeypair.privateKey.decrypt(_encrypted);

    //The rest of sending an email is the same.

    final smtpServer = gmail(username, password);
    // Use the SmtpServer class to configure an SMTP server:
    // final smtpServer = SmtpServer('smtp.domain.com');
    // See the named arguments of SmtpServer for further configuration
    // options.

    // Create our message.
    Message message = Message()
      ..from = Address(username, 'Your name')
      ..recipients.add(emailRecipient)
      ..ccRecipients.addAll(['secondEmail@email.com'])
      ..subject = 'Date: ${DateFormat('dd/MM/yyyy').format(DateTime.now())}'
      ..text = 'This is the plain text.\nThis is line 2 of the text part.'
      ..html = "<h1>Hi:</h1>\n<p>This is some html</p>\n<p>Greetings, mailer.dart</p>";

    for (String path in paths) {
      message
        ..attachments.add(
          FileAttachment(
            File(
              path,
            ),
          ),
        );
    }
    var connection = PersistentConnection(smtpServer);

    // Send the first message
    await connection.send(message);

    // send the equivalent message
    //await connection.send(equivalentMessage);

    // close the connection
    await connection.close();
  }
}

这是我用于解决使用邮件程序包或任何类似目的的程序包将密码存储为纯文本格式以发送电子邮件的问题的方法。