node-keytar icon indicating copy to clipboard operation
node-keytar copied to clipboard

getPassword on windows seems to only return the first letter from the password

Open randohinn opened this issue 5 years ago • 10 comments

Trying to use the latest node-keytar from npm on electron (have used electron-rebuild electron-rebuild -f -w keytar to get it working), this piece of code, will only log the first letter of the password. Implying that's all it gets back.

keytar.getPassword('Kassa','kassa').then((result) => {
           console.log(result)
});

randohinn avatar Aug 04 '19 11:08 randohinn

@randohinn there's more information needed to help me understand the issue:

  • which OS?
  • which version of Electron?

shiftkey avatar Aug 06 '19 12:08 shiftkey

I have same problem when I use keytar in windows 10 professional (version 1903 build 10.0.18362) language traditional chinese. If I directly create new credential ( or modify credential) by windows credential manager interface that problem occur. but If create new credential by keytar.setPassword(service, account, password) method it doesn't occur this problem.

OS: windows 10 professional (version 1903 build 10.0.18362) language traditional chinese Electron: 7.1.0

I found a solution for the problem, the reason course this problem is password be separate with ascii code '0'. so we can use regular expression trim every ascii code 0. therefore the password is correct.

 keytar.getPassword('MyService', 'token').then((result) => {
    console.log(result.replace(/\000+/g, ''))
  });

akiratfli avatar Nov 26 '19 02:11 akiratfli

I found a solution for the problem, the reason course this problem is password be separate with ascii code '0'. so we can use regular expression trim every ascii code 0.

This sounds plausible, because on Windows we know the size of the credentials that were stored, and convert that into a string, so it may contain \0:

https://github.com/atom/node-keytar/blob/1f6e680696fa4416762525e53806595285129211/src/keytar_win.cc#L170-L171

If someone is able to reproduce this using a setPassword and getPassword call that doesn't result in the expected string, I'd love to hear more.

shiftkey avatar Nov 27 '19 13:11 shiftkey

I just ran into this as well. A credential entry created with keytar comes back from keytar as expected. A credential I create by hand in the Credential Manager comes back from keytar with the extra nulls in it. I'm working around it using akirafli's workaround, but if you'd like any more information let me know and I'll be happy to provide.

baldnate avatar Jun 07 '20 21:06 baldnate

@baldnate a runnable test and the specific OS you're running it on would be ideal for me to understand what's happening:

If someone is able to reproduce this using a setPassword and getPassword call that doesn't result in the expected string, I'd love to hear more

shiftkey avatar Jun 08 '20 13:06 shiftkey

@shiftkey I am using Windows 10.0.18363. Using setPassword and getPassword together works fine. It is when I use the Credential Manager directly (through the UI) that getPassword displays the unexpected behavior reported by akirafli.

I can write a runnable test, but there will be a manual step in it to go into the Credential Manager UI and set the password. Either that, or the test will need to re-implement setting a password directly through the Credential Manager's API.

baldnate avatar Jun 08 '20 13:06 baldnate

@baldnate even if manual steps are needed, steps to walk me through how to reproduce it on my end would be great

shiftkey avatar Jun 08 '20 14:06 shiftkey

I am having this same issue. The workaround from @akiratfli works. Windows 10 v. 10.0.18363 English [email protected]

In Windows Credential Manager add a generic credential: Internet or Network Address: 'KeytarTest/manualSet' User name: 'manualSet' Password: 'manuallyCreated'

const keytar = require('keytar');

keytar.getPassword('KeytarTest', 'manualSet')
    .then( (pw) => {
        console.log('manually entered credential = ', pw);
    });

keytar.getPassword('KeytarTest', 'manualSet')
    .then( (pw) => {
        console.log('manually entered credential with replace 0 = ', pw.replace(/\000+/g, ''));
    });

keytar.setPassword('KeytarTest', 'KeytarSet', 'keytarCreated')
    .then(() => {
        keytar.getPassword('KeytarTest', 'KeytarSet')
            .then((pw) => {
                console.log('keytar created credential = ', pw);
            });
    });

Outputs:

manually entered credential with replace 0 =  manuallyCreated
manually entered credential =  m a n u a l l y C r e a t e d
keytar created credential =  keytarCreated

JiCi avatar Jun 09 '20 16:06 JiCi

I can confirm the issue as well. Exact same behavior as described by @baldnate. Only round-trip using keytar itself works fine (writing and reading). If I use the windows user interface for the credential manager or the command line (cmdkey.exe) I get \u0000 after each character when reading with keytar.

I'm running Windows 10.0.19041.630 64-bit Node v10.18.0 Keytar 7.2.0

What else on the environment could be of relevance for reproduction?

mmben avatar Nov 26 '20 07:11 mmben

Could it be that windows stores the passwords in UTF-16 and keytar interprets them as UTF-8? Example: Convert UTF-16 (big endian) into hex: TEST --> 0054 0045 0053 0054 Interpret that hex as UTF-8: 00 54 00 45 00 53 00 54 --> T E S T

Does that make sense?

mmben avatar Nov 26 '20 13:11 mmben