Quick Start Guide |
This quick start guide covers the basic steps to use the ursa library in a .NET project.
.Net Standard 2.0 or .NET Framework 4.6.1
SamoyedSoftware.ursa NuGet package; Or, a copy of the ursa assembly file (SamoyedSoftware.ursa.dll) downloaded from the ursa project homepage.
In your .NET project, install the SamoyedSoftware.ursa NuGet package, or add a reference to a manually downloaded copy of SamoyedSoftware.ursa.dll.
In your code file, add a using statement for the ursa namespace:
using SamoyedSoftware.ursa;
Use SecurIdTokenLoad(String) to load the token from the file.
string strMyTokenFile = "mytokenfile.txt"; SecurIdToken token = SecurIdToken.Load(filename);
Use the SecurIdTokenDecrypt(String, String) to decrypt the token. You'll need to supply the password for the token, and for some tokens a Device ID / Serial number.
string strMyPassword = "this is my token password"; string strMyDeviceId = ""; token.Decrypt(strMyPassword, strMyDeviceId);
Use SecurIdTokenComputeTokencode(DateTime), or if you token requires a PIN use SecurIdTokenComputeTokencode(DateTime, String), retrieve the current tokencode.
string strTokenCode = token.ComputeTokencode(DateTime.Now); // If your token requires a PIN use the following instead //string strPIN = "1234"; //string strTokenCode token.ComputeTokencode(DateTime.Now, strPIN);
The following example is a command-line program that generates a tokencode from a token in stored in a file or from a token string passed as an command-line argument. The complete source for this program is included in the ursa project source code, available from the ursa project homepage.
/* * This file is part of ursa, a tokencode generator compatible with * RSA SecurID® 128-bit (AES) tokens. RSA SecurID® is a registered * trademark held by RSA Security LLC. Neither the ursa project * nor Samoyed Software, LLC are affiliated with or endorsed by * RSA® (RSA Security LLC). * * Copyright 2017 Samoyed Software, LLC <http://www.samoyedsoftware.com> * * Portions of ursa are based on * stoken 0.92, Copyright 2012 Kevin Cernekee <http://stoken.sf.net/> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. If not, see <http://www.gnu.org/licenses/>. */ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Threading; using SamoyedSoftware.ursa; namespace ursaCmd { class Program { static int Main(string[] args) { string filename = ""; string tokenString = ""; string password = ""; string deviceid = ""; string pin = ""; DateTime time = DateTime.MinValue; bool bLoop = false; bool bPrintTime = false; bool bPrintInfo = false; bool bExport = false; char exportVersion = (char) 0; if (args.Length > 0) { string strOpt = ""; string strOptName = ""; string strNextOpt = ""; bool bHasNextOpt = false; for (int i = 0; i < args.Length; i++) { if (args[i].StartsWith("-") || args[i].StartsWith("/")) { strOpt = args[i]; if (strOpt.Length < 2) return UsageBadOption(strOpt); strOptName = strOpt.Substring(1); strNextOpt = (i + 1 < args.Length) ? args[i + 1] : ""; bHasNextOpt = strNextOpt.Length > 0; switch (strOptName) { case "token": if (!bHasNextOpt) return UsageMissingOptionValue(strOpt); tokenString = strNextOpt; i++; break; case "pass": if (!bHasNextOpt) return UsageMissingOptionValue(strOpt); password = strNextOpt; i++; break; case "devid": if (!bHasNextOpt) return UsageMissingOptionValue(strOpt); deviceid = strNextOpt; i++; break; case "pin": if (!bHasNextOpt) return UsageMissingOptionValue(strOpt); pin = strNextOpt; i++; break; case "time": if (!bHasNextOpt) return UsageMissingOptionValue(strOpt); if (!DateTime.TryParse(strNextOpt, out time)) return UsageBadOptionValue(strOpt, args[i + 1], "valid date/time value"); i++; break; case "showtime": bPrintTime = true; break; case "loop": bLoop = true; break; case "info": bPrintInfo = true; break; case "export": if (bHasNextOpt && strNextOpt[0] != '-') { exportVersion = Char.ToLower(strNextOpt[0]); if (exportVersion != '2' && exportVersion != '3' && exportVersion != 's') return UsageBadOptionValue(strOpt, args[i + 1], "valid version number (2, 3, or s)"); } else exportVersion = (char) 0; bExport = true; break; default: return UsageBadOption(strOpt); } } else if (i == 0) { filename = args[i]; } } } if (bLoop && (time > DateTime.MinValue || bExport)) return Usage("Option -loop may not be combined with options -time or -export."); if (bPrintInfo && bExport) return Usage("Option -info may not be combined with option -export."); if (filename.Length == 0 && tokenString.Length == 0) return Usage("Must specify token file path or use -token to specify token string."); try { SecurIdToken token = null; if (tokenString.Length > 0) token = SecurIdToken.Parse(tokenString); else if (filename.Length > 0) token = SecurIdToken.Load(filename); if (token == null) throw new ApplicationException("Could not parse token."); token.Decrypt(password, deviceid); if (bExport) { string strExport = ""; switch (exportVersion) { case '2': SecurIdV2Token t2 = token.AsV2Token; strExport = t2.Export(password, deviceid); break; case '3': SecurIdV3Token t3 = token.AsV3Token; strExport = t3.Export(password, deviceid); break; case 's': SecurIdSdtidToken ts = token.AsSdtidToken; strExport = ts.Export(password, deviceid); break; } Console.WriteLine(strExport); } else { if (bPrintInfo) Console.Write(token.ToString()); do { DateTime dt = (time > DateTime.MinValue) ? time : DateTime.Now; string tokenCode = token.ComputeTokencode(dt, pin); if (bPrintTime) Console.Write("{0}\t", dt); Console.WriteLine(tokenCode); if (bLoop) Thread.Sleep((60 - dt.Second + 1) * 1000); } while (bLoop); } } catch (Exception ex) { return HandleError(ex); } return 0; } #region Console Output static int Usage() { return Usage("", null); } static int Usage(string err) { return Usage(err, null); } static int UsageBadOption(string option) { return Usage("Option \"{0}\" is not valid.", option); } static int UsageMissingOptionValue(string option) { return Usage("Value for option {0} was not specified.", option); } static int UsageBadOptionValue(string option, string optionValue, string expecting) { return Usage("Value \"{0}\" for option {1} is not valid.{2}", optionValue, option, expecting.Length > 0 ? " Expecting " + expecting + "." : ""); } static int Usage(string err, params object[] args) { Console.WriteLine(); if (err.Trim().Length > 0) { Console.ForegroundColor = GetErrorColor(); if (args != null) Console.WriteLine(err, args); else Console.WriteLine(err); Console.ResetColor(); Console.WriteLine(); } Console.WriteLine("Usage: {0} {{ TokenFilePath | -token TokenString }} [ <options> ]", System.Diagnostics.Process.GetCurrentProcess().ProcessName.ToLower()); Console.WriteLine(); Console.WriteLine("Options:"); Console.WriteLine("\t-pass Password"); Console.WriteLine("\t-devid DeviceID"); Console.WriteLine("\t-pin PIN"); Console.WriteLine("\t-time DateTime"); Console.WriteLine("\t-showtime"); Console.WriteLine("\t-loop"); Console.WriteLine("\t-export [VersionCode]"); Console.WriteLine("\t-info"); Console.WriteLine(); return 1; } static void Print(string message, params object[] args) { Console.Write(message, args); } static void Print(string message) { Console.Write(message); } static void PrintLine(string message) { Console.WriteLine(message); } static void PrintLine(string message, params object[] args) { Console.WriteLine(message, args); } static int HandleError(Exception ex) { Console.ForegroundColor = GetErrorColor(); Console.WriteLine(); if (ex is ursaException) Console.WriteLine("Error: {0}", ((ursaException)ex).ErrorCodeAsString); else { Console.WriteLine("Error: {0}", ex.Message); Console.WriteLine("Stack Trace: {0}", ex.StackTrace); } Console.ResetColor(); return 2; } static int HandleError(string message) { Console.ForegroundColor = GetErrorColor(); Console.WriteLine(); Console.WriteLine("Error: {0}", message); Console.ResetColor(); return 2; } static ConsoleColor GetErrorColor() { if (Console.BackgroundColor == ConsoleColor.Red || Console.BackgroundColor == ConsoleColor.Magenta || Console.BackgroundColor == ConsoleColor.DarkRed || Console.BackgroundColor == ConsoleColor.DarkMagenta) return ConsoleColor.Yellow; return ConsoleColor.Red; } #endregion } }