安全地保存密码有没有人有一种安全的方法来存储密码,以便用户不必每次都输入密码?
我不想将密码以纯文本形式存储在首选项文件或类似文件中。
Names default to here(1);
nw = new window("Login",
lineupbox(ncol(2),
textbox("Username"), teb_uid = texteditbox("Vincent", <<SET width=""></SET>回复:安全保存密码这是一个使用 powershell 中可用模块的版本,也许这是一个选项?
Names default to here(1);
loadmodule = "
if (!(Get-Module -ListAvailable -Name CredentialManager)) {
Install-Module CredentialManager -force -Scope CurrentUser
}
";
//Function to run command in powershell, strips trailing line breaks
RunPowershell = Function( {command},
Regex(RunProgram(
Executable( "powershell.exe" ),
Options( {"/c", command } ),
ReadFunction( "text" )
), "^(.*?)[\r\n]+$", "\1")
);
// Set password
SetPass = Function( {target,user,pass},
RunPowershell(
"$target = '" || target || "'
$usr = '" || user || "'
$pswd = '" || pass || "'
" || loadmodule || "
New-StoredCredential -Target $target -UserName $usr -Password $pswd"
);
1; //password is returned as free text, don't return the response
);
// Get password
GetPass = Function( {target},
RunPowershell(
"$target = '" || target || "'
" || loadmodule || "
$creds = Get-StoredCredential -Target $target
$creds.GetNetworkCredential().Password"
)
);
// Get username
GetUser = Function( {target},
RunPowershell(
"$target = '" || target || "'
" || loadmodule || "
$creds = Get-StoredCredential -Target $target
$creds.GetNetworkCredential().UserName"
)
);
// Set and retrieve credentials
SetPass("testcredential", "myusername3", "mypassword3");
GetPass("testcredential");
GetUser("testcredential");
//You can delete these test credentials using the 'windows credential store'.回复:安全保存密码在 Windows 上相信可以使用 JSL 和命令行重新创建此代码以与 Windows 凭据管理器交互,但可能是错误的。也许有一天我会承担这个任务;在这里分享它,以防其他人先弄清楚。 
<SPAN class="com">#include</SPAN> <SPAN class="str"><WINDOWS.H></WINDOWS.H></SPAN>
<SPAN class="com">#include</SPAN> <SPAN class="str"><WINCRED.H></WINCRED.H></SPAN>
<SPAN class="com">#include</SPAN> <SPAN class="str"><TCHAR.H></TCHAR.H></SPAN>
<SPAN class="com">#pragma</SPAN><SPAN class="pln"> hdrstop
</SPAN><SPAN class="kwd">void</SPAN><SPAN class="pln"> main </SPAN><SPAN class="pun">()</SPAN>
<SPAN class="pun">{</SPAN>
<SPAN class="pun">{</SPAN> <SPAN class="com">//--- SAVE</SPAN>
<SPAN class="kwd">char</SPAN><SPAN class="pun">*</SPAN><SPAN class="pln"> password </SPAN><SPAN class="pun">=</SPAN> <SPAN class="str">"brillant"</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"> DWORD cbCreds </SPAN><SPAN class="pun">=</SPAN> <SPAN class="lit">1</SPAN> <SPAN class="pun">+</SPAN><SPAN class="pln"> strlen</SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">password</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln">
CREDENTIALW cred </SPAN><SPAN class="pun">=</SPAN> <SPAN class="pun">{</SPAN><SPAN class="lit">0</SPAN><SPAN class="pun">};</SPAN><SPAN class="pln"> cred</SPAN><SPAN class="pun">.</SPAN><SPAN class="typ">Type</SPAN> <SPAN class="pun">=</SPAN><SPAN class="pln"> CRED_TYPE_GENERIC</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"> cred</SPAN><SPAN class="pun">.</SPAN><SPAN class="typ">TargetName</SPAN> <SPAN class="pun">=</SPAN><SPAN class="pln"> L</SPAN><SPAN class="str">"FOO/account"</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"> cred</SPAN><SPAN class="pun">.</SPAN><SPAN class="typ">CredentialBlobSize</SPAN> <SPAN class="pun">=</SPAN><SPAN class="pln"> cbCreds</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"> cred</SPAN><SPAN class="pun">.</SPAN><SPAN class="typ">CredentialBlob</SPAN> <SPAN class="pun">=</SPAN> <SPAN class="pun">(</SPAN><SPAN class="pln">LPBYTE</SPAN><SPAN class="pun">)</SPAN><SPAN class="pln"> password</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"> cred</SPAN><SPAN class="pun">.</SPAN><SPAN class="typ">Persist</SPAN> <SPAN class="pun">=</SPAN><SPAN class="pln"> CRED_PERSIST_LOCAL_MACHINE</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"> cred</SPAN><SPAN class="pun">.</SPAN><SPAN class="typ">UserName</SPAN> <SPAN class="pun">=</SPAN><SPAN class="pln"> L</SPAN><SPAN class="str">"paula"</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln">
BOOL ok </SPAN><SPAN class="pun">=</SPAN> <SPAN class="pun">::</SPAN><SPAN class="typ">CredWriteW</SPAN> <SPAN class="pun">(&</SPAN><SPAN class="pln">cred</SPAN><SPAN class="pun">,</SPAN> <SPAN class="lit">0</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"> wprintf </SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">L</SPAN><SPAN class="str">"CredWrite() - errno %d\n"</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> ok </SPAN><SPAN class="pun">?</SPAN> <SPAN class="lit">0</SPAN> <SPAN class="pun">:</SPAN> <SPAN class="pun">::</SPAN><SPAN class="typ">GetLastError</SPAN><SPAN class="pun">());</SPAN>
<SPAN class="kwd">if</SPAN> <SPAN class="pun">(!</SPAN><SPAN class="pln">ok</SPAN><SPAN class="pun">)</SPAN> <SPAN class="kwd">exit</SPAN><SPAN class="pun">(</SPAN><SPAN class="lit">1</SPAN><SPAN class="pun">);</SPAN>
<SPAN class="pun">}</SPAN>
<SPAN class="pun">{</SPAN> <SPAN class="com">//--- RETRIEVE</SPAN><SPAN class="pln"> PCREDENTIALW pcred</SPAN><SPAN class="pun">;</SPAN><SPAN class="pln"> BOOL ok </SPAN><SPAN class="pun">=</SPAN> <SPAN class="pun">::</SPAN><SPAN class="typ">CredReadW</SPAN> <SPAN class="pun">(</SPAN><SPAN class="pln">L</SPAN><SPAN class="str">"FOO/account"</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> CRED_TYPE_GENERIC</SPAN><SPAN class="pun">,</SPAN> <SPAN class="lit">0</SPAN><SPAN class="pun">,</SPAN> <SPAN class="pun">&</SPAN><SPAN class="pln">pcred</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"> wprintf </SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">L</SPAN><SPAN class="str">"CredRead() - errno %d\n"</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> ok </SPAN><SPAN class="pun">?</SPAN> <SPAN class="lit">0</SPAN> <SPAN class="pun">:</SPAN> <SPAN class="pun">::</SPAN><SPAN class="typ">GetLastError</SPAN><SPAN class="pun">());</SPAN>
<SPAN class="kwd">if</SPAN> <SPAN class="pun">(!</SPAN><SPAN class="pln">ok</SPAN><SPAN class="pun">)</SPAN> <SPAN class="kwd">exit</SPAN><SPAN class="pun">(</SPAN><SPAN class="lit">1</SPAN><SPAN class="pun">);</SPAN><SPAN class="pln"> wprintf </SPAN><SPAN class="pun">(</SPAN><SPAN class="pln">L</SPAN><SPAN class="str">"Read username = '%s', password='%S' (%d bytes)\n"</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln">
pcred</SPAN><SPAN class="pun">-></SPAN><SPAN class="typ">UserName</SPAN><SPAN class="pun">,</SPAN> <SPAN class="pun">(</SPAN><SPAN class="kwd">char</SPAN><SPAN class="pun">*)</SPAN><SPAN class="pln">pcred</SPAN><SPAN class="pun">-></SPAN><SPAN class="typ">CredentialBlob</SPAN><SPAN class="pun">,</SPAN><SPAN class="pln"> pcred</SPAN><SPAN class="pun">-></SPAN><SPAN class="typ">CredentialBlobSize</SPAN><SPAN class="pun">);</SPAN>
<SPAN class="com">// must free memory allocated by CredRead()!</SPAN>
<SPAN class="pun">::</SPAN><SPAN class="typ">CredFree</SPAN> <SPAN class="pun">(</SPAN><SPAN class="pln">pcred</SPAN><SPAN class="pun">);</SPAN>
<SPAN class="pun">}</SPAN>
<SPAN class="pun">}</SPAN>从kkm这里:
https://stackoverflow.com/questions/9221245/how-do-i-store-and-retrieve-credentials-from-the-windows-vault-credential-manage
回复:安全保存密码你已经帮了很多忙了。谢谢。
回复:安全保存密码您可以查看使用 JMP 插件进行加密。 了解运输加密库会产生法律和出口影响。 您最好的选择是编写一个加载项,调用主机操作系统上已有的本机加密库,然后仍然通过您的法律团队运行它。
回复:安全保存密码我喜欢这个。不幸的是我不能强迫客户安装python(有些已经明确禁止他们的用户安装它)。但我已经说服大多数人安装 sqlite odbc 驱动程序,所以也许我可以将其与 MD5 一起使用。
我仍然需要找到某种方法来进行加密。
感谢您的帮助,我确实需要做一些研究。
回复:安全保存密码我拿一个混淆式路线。我将字符转换为数字,然后将这些数字输入数学公式以生成“加密”表示形式。
我更倾向于将该技术用于软件许可证代码而不是用户密码。因此,我将采用产品名称或代码与站点 ID 信息相结合,加上到期日期,构建数字表示形式并通过复杂的数学公式对其进行解析:最终输出可能类似于 1143932720966。
回复:安全保存密码在为自己寻找更好的解决方案时发现了这一点。对于我自己机器上的脚本,我调用 R 并使用 keyring 函数。它在 Mac 上使用 Keychain,在 Windows 上使用 Credential Store,在 Linux 上使用 Secret Service API。显然这会带来开销,如果没有 R 就可以做到这一点会很好。如果有兴趣,我放一个用于创建这些功能的 JMP 愿望清单项目在 JMP 中。
https://github.com/r-lib/keyring
R Init();
R Submit(
"library(keyring)
pw <- keyring::key_get(\!"DomainAccount\!", \!"username\!")"
);
pw = R Get("pw");
R Term();回复:安全保存密码用于创建 sqlite 数据存储的示例 python 脚本,
#! /usr/bin/env/python3
#
# Author: Paul Nelson - JMP Statistical Discovery, From SAS
# Date: 9 Mar 2020
#
# Description: This sample shows the python code using sqlite to create a data data store
# for saving passwords, credentails... While Python has hash functions, the standard library
# does not include ciphers. For purposes of this sample I used lzma compression to 'encode' and
# decompression to 'decrypt' For use from JSL, I would turn this into a python module and then
# import 'my_dataStore_api' to cut down code in the JSL string.
#
# sample python program using sqlite to create a secure store for passwords and
# key, value data storage.
#
# While Python contains hash functions, does not include encryption primitives in the standard library.
# an example using PyCrypto can be found
# https://stackoverflow.com/questions/12524994/encrypt-decrypt-using-pycrypto-aes-265
# however pycrypto has no been updated since 2014... https://github.com/dlitz/pycrypto
#
# pyca/cryptography - https://cryptography.io/ https://github.com/pyca/cryptography
# seems to be currently maintained.
#
# Don't create your own encryption! The above packages or, openssl, or many other providers are
# better than writing your own.
#
# It is an exercise left to the reader to replace the code using lzma compression with real encrypt
# and decrypt code.
#
#
import sqlite3
import hashlib
import os
from pathlib import Path
import lzma
# Salt should be random quantity, get from OS entropy source
salt = os.urandom(16);
mypasswd = b'JMP in a dried up lake'
dk = hashlib.pbkdf2_hmac('sha256', mypasswd, salt, 1000)
# dk.hex() will be the actual hashed password saved to db
# but the binary dk, will be what we use as the encryption key
# dkhex = dk.hex()
# binDk = bytes.fromhex(dkhex)
#
# Path to my credential store , my home directory + AppData
data_path = str(Path.home()) + '/AppData/'
filename = 'dataStore'
# Create directory if it doesn't exist
os.makedirs(data_path, exist_ok=True)
# will create database if it doesn't exist
db = sqlite3.connect(data_path + filename + '.db')
# my username
me = 'jmpuser'
# create our password table storing hashed passwords
db.execute('CREATE TABLE IF NOT EXISTS passwd (uid INTEGER PRIMARY KEY, name TEXT, salt TEXT, key TEXT)')
# should check to see if user is in database and only insert if not found
# exercise left to the reader
db.execute("INSERT INTO passwd (name, salt, key) VALUES( ?,?,? ) ", (me, salt.hex(), dk.hex()) )
db.commit()
print('******* passwd database *******')
for row in db.execute('SELECT * from passwd'):
print(row)
print('*******************************')
# create our credentials table which will store the name of the credential, and its value
db.execute('CREATE TABLE IF NOT EXISTS credentials (id INTEGER PRIMARY KEY, uid INTEGER, key TEXT, value TEXT)')
# first we need to have validated that user gave propper password, and we authenticated against passwd
# table assuming user is authenticated
# should check to see if user is in database and only insert if not found, potentially update if found
# exercise left to the reader.
# my user id in this scheme
id = 0
#The value data I'm going to store into the database
myson1 = """
{
user: paul
magic_key: JMP Rocks!
}"""
myson2 = """
{
user: paul
magic_key: supercalifragilisticexpialidocious
}"""
# 'encrypt' my data
lvalue = lzma.compress( myson2.encode() )
lvalue2 = lzma.compress( myson1.encode() )
# you could encrypt the 'key' as well as the value if you really want security
db.execute("INSERT INTO credentials (uid, key, value) VALUES( ?,?,? ) ", (id, 'JMPCommunity', lvalue.hex()) )
db.execute("INSERT INTO credentials (uid, key, value) VALUES( ?,?,? ) ", (id, 'WDW', lvalue2.hex()) )
db.commit()
print('******* credentials database *******')
for row in db.execute('SELECT * from credentials WHERE uid=?', (id,) ):
print(row)
value = bytes.fromhex(row[3])
print(lzma.decompress(value).decode())
print('************************************')
db.close()
回复:安全保存密码凭证的安全存储是一个难题。 要做到正确确实很难。 至少您可能仍然需要用户在每个会话中输入某种形式的凭据,以防止未经授权使用您试图保护的秘密。 因此,对于每个“用户”,您可能需要为其凭证存储存储一个密码。 然后您需要凭证存储本身。 多安全才足够? 您是否只需要混淆,例如像 rot13 这样的简单替换密码(将字母表中的字母移动 13,所以 m => z、a =>n 或者您是否需要更强大的东西,例如 AES 加密或公钥加密? 您可以使用 JMP 表、文本文件或数据库表创建数据存储,JMP 具有对数据库连接的 ODBC 支持。 更好的校验和和加密支持,可以用 JSL 编写,也可以通过 JMP 的插件功能或通过 Python 桥从共享库加载。
保护密码,
确保密码文件安全的传统方法是使用哈希函数。 一种方法具有 MD5、SHA 系列、SHA1、SHA256 等函数,所有这些函数都会获取数据并创建一个无法反转的哈希值以揭示原始数据。 这个想法是,您获取想要保护的数据并根据该数据创建哈希值。 通常,此类哈希值与 SALT 值混合,SALT 值是与密码数据一起存储的随机值。 盐使得将已知数据的查找表保存为哈希值的成本要高得多。 然后,当用户输入密码时,您对输入的值进行哈希处理,并将哈希值与存储的值进行比较。如果它们匹配==成功并且密码通过验证。 JMP 将 MD5 校验和公开给 JSL。 从脚本索引中,请参阅 Blob MD5()。 请注意,MD5 用于加密目的对于现代加密技术来说并不安全,但对于低级别安全性来说仍然应该没问题。
然后,您可以使用哈希值,甚至可以将哈希值与其他数据结合起来,创建派生哈希值或 HMAC https://en.wikipedia.org/wiki/HMAC充当受保护数据存储的密码密钥。 有些数据库具有数据字段的加密功能,或者您可能需要自己加密数据并存储在表中。
最后,如果您需要更高的安全性,请查看可以调用共享库的 JMP 插件功能,您可以根据需要实现复杂的数据管理方案。 或者查看 JMP 的 Python 界面,调用 Python 包可以让您访问 sqlite,以及更好的校验和和加密方法。
我将如何构建这样一个数据存储? 我会严重依赖 JMP 的 Python 界面。 sqlite 数据库支持内置于 Python 中,并将使用该数据库或 JMP 表作为我的数据存储。 此外,Python 通常是使用 crypt 支持、校验和和加密算法构建的。 我首先创建一个密码表,其中包含密码的哈希值。 然后构建一个数据存储作为另一个具有加密字段的表。 到底有多安全,有多复杂,有多少代码和多少测试的问题......
回复:安全保存密码我想我会尝试解决这个问题,看看是否有人有任何想法。
因为现在我也遇到了其他类型的秘密的问题。用户访问代码等等。
回复:安全保存密码这将使我有权访问所有用户的密码。绝对不可行。告诉用户将密码保存为加密脚本也不是一个可行的选择。我真的想要一个“记住我”选项,我可以存储他们以编程方式输入的任何用户名/密码,但该存储是安全的。
回复:安全保存密码创建一个包含关联数组或列表等中的密码的脚本。然后将该脚本另存为加密脚本。