bashmatlabcross-platformpassword-prompt

MATLAB to read in a password


I'm building a MATLAB application that authenticates a user's credentials. I want to read in his password, and I want to hide his typed credentials somehow.

Some constraints:

Here's what I've tried:

Straight-up GUIDE

Works, but not an option as the user is likely to be running matlab in -nodesktop (or -nodisplay) mode.

MATLAB + Java

console.readPassword. This messes up my terminal horribly.

system() calls

Essentially I call bash or dos scripts based on OS.

I have the following call for linux/mac:

[status cred] = system('stty -echo; read cred; stty echo;echo ""; echo "$cred"');

This is supposed to pick up the user credentials and dump that on to 'cred'. I've checked that it works in the regular terminal, but executing it in MATLAB causes nothing to be output, and a Ctrl-C is required to bring back the >> prompt.

MATLAB Perl

The Windows MATLAB packages Perl, as pointed out in comments. I tried the following snippet:

use Term::ReadKey;
use Term::ReadLine;
ReadMode('noecho');
$yesnoline = Term::ReadLine->new("foo");
$pass = $yesnoline->readline();
printf "$pass";
ReadMode('restore');

And then called it as [result status] = perl('my_perl.pl'). Works great on Linux. On Windows:

res =

GetConsoleMode failed, LastError=|6| at ReadKey.pm line 264.

sta =

 9

My searches so far suggest that it's a problem related to the packaged version of perl for windows.

Any idea what's happening in the above approaches?


Solution

  • I suggest that you detect Windows installation (ispc), and handle them differently than Unix-like systems, by creating a MATLAB GUI or something similar..

    Here is one possible solution for Windows using .NET Windows Forms from inside MATLAB:

    function pass = getPasswordNET()
        %# password return value
        pass = '';
    
        %# hidden figure used to wait for button press
        fig = figure('Visible','off', ...
            'IntegerHandle','off', 'HandleVisibility','off');
    
        %# create and show the Windows Forms GUI
        [handles,lh] = InitializeComponents();
        handles.frm.Show();
    
        %# block execution until figure is closed
        waitfor(fig)
    
        %# remove the listeners
        delete(lh);
    
        return;
    
        %# create GUI
        function [handles,lh] = InitializeComponents()
            %# import assembly
            NET.addAssembly('System.Windows.Forms');
    
            %# form
            frm = System.Windows.Forms.Form();
            frm.SuspendLayout();
    
            %# textbox
            tb = System.Windows.Forms.TextBox();
            tb.Dock = System.Windows.Forms.DockStyle.Fill;
            tb.Text = '';
            tb.PasswordChar = '*';
            tb.MaxLength = 14;
    
            %# button
            bt = System.Windows.Forms.Button();
            bt.Dock = System.Windows.Forms.DockStyle.Bottom;
            bt.Text = 'Submit';
    
            %# setup the form
            frm.Text = 'Password';
            frm.ClientSize = System.Drawing.Size(250, 40);
            frm.Controls.Add(tb);
            frm.Controls.Add(bt);
            frm.ResumeLayout(false);
            frm.PerformLayout();
    
            %# add event listeners
            lh(1) = addlistener(bt, 'Click', @onClick);
            lh(2) = addlistener(frm, 'FormClosing', @onClose);
    
            %# return handles structure
            handles = struct('frm',frm, 'tb',tb, 'bt',bt);
        end
    
        %# event handlers
        function onClick(~,~)
            %# get password from textbox
            pass = char(handles.tb.Text);
    
            %# close form
            handles.frm.Close();
        end
        function onClose(~,~)
            %# delete hidden figure (to unblock and return from function)
            close(fig)
        end
    end
    

    I tested the above on my machine, and it worked even when MATLAB was started in headless mode:

    matlab.exe -nodesktop -noFigureWindows
    

    then called it as:

    >> pass = getPasswordNET()
    pass =
    secret_password
    

    screenshot

    It should be straightforward to do something similar in Java using Swing's JPasswordField