gpt4 book ai didi

java - Lotus Domino C# LtpaToken 类

转载 作者:行者123 更新时间:2023-11-30 06:04:36 26 4
gpt4 key购买 nike

各位开发人员,我正在寻找将以下 java 代码转换为 c# 的方法。我已经做了一些转换,如下所示,但我的 LtpaToken 无效。我需要在 Domino 应用程序和 C# Web API 之间创建单点登录。 Notes 通讯簿中的所有用户都将包含在 SQL Server 数据库中,但有些用户不一定包含在通讯簿中。如果 Notes 地址簿中存在用户,则所有用户都将通过 IdentityServer4 登录,将使用 CN、cookieName、cookieDomain 和 Domino Secret 生成 LTPA token 。生成的cookie将被注入(inject)到用户浏览器中。

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;

import javax.servlet.http.Cookie;

import org.apache.commons.codec.binary.Base64;

/**
* Lightweight Third Party Authentication. Generates and validates ltpa tokens
* used in Domino single sign on environments. Does not work with WebSphere SSO
* tokens. You need a properties file named LtpaToken.properties which holds two
* properties.
*
* <pre>
* ) domino.secret=The base64 encoded secret found in the field LTPA_DominoSecret in the SSO configuration document.
* ) cookie.domain=The domain you want generated cookies to be from. e.g. '.domain.com' (Note the leading dot)
* </pre>
*
* @author $Author: rkelly $
* @version $Revision: 1.1 $
* @created $Date: 2003/04/07 18:22:14 $
*/
public final class LtpaToken {

private byte[] creation;
private Date creationDate;
private byte[] digest;
private byte[] expires;
private Date expiresDate;
private byte[] header;
private String ltpaToken;
private byte[] rawToken;
private byte[] user;
private String dominoSecret;

/**
* Constructor for the LtpaToken object
*
* @param token Description of the Parameter
* @param cookieName
* @param cookieDomain
* @param dominoSecret
*/
public LtpaToken(String token, String cookieName, String cookieDomain, String dominoSecret) {
init();
ltpaToken = token;
this.dominoSecret = dominoSecret;
byte[] byteArray = ltpaToken.getBytes();
rawToken = Base64.decodeBase64(byteArray);

user = new byte[(rawToken.length) - 40];
for (int i = 0; i < 4; i++) {
header[i] = rawToken[i];
}
for (int i = 4; i < 12; i++) {
creation[i - 4] = rawToken[i];
}
for (int i = 12; i < 20; i++) {
expires[i - 12] = rawToken[i];
}
for (int i = 20; i < (rawToken.length - 20); i++) {
user[i - 20] = rawToken[i];
}
for (int i = (rawToken.length - 20); i < rawToken.length; i++) {
digest[i - (rawToken.length - 20)] = rawToken[i];
}

String commonName = new String(user);
System.out.println(commonName);

creationDate = new Date(Long.parseLong(new String(creation), 16) * 1000);
expiresDate = new Date(Long.parseLong(new String(expires), 16) * 1000);

System.out.println(creationDate);
System.out.println(expiresDate);

}

/**
* Constructor for the LtpaToken object
*/
private LtpaToken() {
init();
}

public static Cookie newCookie(String sessionToken, String cookieName, String cookieDomain) {
Cookie cookie = new Cookie(cookieName, sessionToken);

cookie.setDomain(cookieDomain);
cookie.setPath("/");
cookie.setSecure(false);
cookie.setMaxAge(-1);
return cookie;
}

/**
* Gets the creationDate attribute of the LtpaToken object
*
* @return The creationDate value
*/
public Date getCreationDate() {
return creationDate;
}

/**
* Gets the expiresDate attribute of the LtpaToken object
*
* @return The expiresDate value
*/
public Date getExpiresDate() {
return expiresDate;
}

/**
* Gets the user attribute of the LtpaToken object
*
* @return The user value
*/
public String getUser() {
return new String(user);
}

/**
* Validates the SHA-1 digest of the token with the Domino secret key.
*
* @return Returns true if valid.
*/
public boolean isValid() {
boolean validDigest;
boolean validDateRange;
byte[] newDigest;
byte[] bytes = null;
Date now = new Date();

MessageDigest md = getDigest();

bytes = concatenate(bytes, header);

bytes = concatenate(bytes, creation);

bytes = concatenate(bytes, expires);

bytes = concatenate(bytes, user);

bytes = concatenate(bytes, Base64.decodeBase64(dominoSecret));

newDigest = md.digest(bytes);

validDigest = MessageDigest.isEqual(digest, newDigest);

validDateRange = now.after(creationDate) && now.before(expiresDate);

return validDateRange && validDigest;
}


/**
* String representation of LtpaToken object.
*
* @return Returns token String suitable for cookie value.
*/
@Override
public String toString() {
return ltpaToken;
}

/**
* Creates a new SHA-1 <code>MessageDigest</code> instance.
*
* @return The instance.
*/
private MessageDigest getDigest() {
try {
return MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException nsae) {
nsae.printStackTrace();
}
return null;
}

/**
* Description of the Method
*/
private void init() {
creation = new byte[8];
digest = new byte[20];
expires = new byte[8];
header = new byte[4];
}

/**
* Validates the SHA-1 digest of the token with the Domino secret key.
*
* @param ltpaToken Description of the Parameter
* @param cookieName
* @param cookieDomain
* @param serverHostname
* @param dominoSecret
* @return The valid value
*/
public static boolean isValid(String ltpaToken, String cookieName,
String cookieDomain, String serverHostname, String dominoSecret) {
LtpaToken ltpa = new LtpaToken(ltpaToken, cookieName, cookieDomain,
dominoSecret);

return ltpa.isValid();
}

/**
* Generates a new LtpaToken with given parameters.
*
* @param canonicalUser User name in canonical form. e.g. 'CN=Robert
* Kelly/OU=MIS/O=EBIMED'.
* @param tokenCreation Token creation date.
* @param tokenExpires Token expiration date.
* @param cookieName
* @param cookieDomain
* @param dominoSecret
* @return The generated token.
*/
public static LtpaToken generate(String canonicalUser, Date tokenCreation, Date tokenExpires,
String cookieName, String cookieDomain, String dominoSecret) {

LtpaToken ltpa = new LtpaToken();

Calendar calendar = Calendar.getInstance();
MessageDigest md = ltpa.getDigest();
ltpa.header = new byte[]{0, 1, 2, 3};
ltpa.user = canonicalUser.getBytes();
byte[] token = null;

calendar.setTime(tokenCreation);
ltpa.creation = Long.toHexString(calendar.getTimeInMillis() / 1000).toUpperCase().getBytes();
calendar.setTime(tokenExpires);
ltpa.expires = Long.toHexString(calendar.getTimeInMillis() / 1000).toUpperCase().getBytes();
ltpa.user = canonicalUser.getBytes();
token = concatenate(token, ltpa.header);
token = concatenate(token, ltpa.creation);
token = concatenate(token, ltpa.expires);
token = concatenate(token, ltpa.user);
md.update(token);

ltpa.digest = md.digest(Base64.decodeBase64(dominoSecret));
token = concatenate(token, ltpa.digest);

String base64encodedToken = Base64.encodeBase64String(token);

return new LtpaToken(base64encodedToken, cookieName,
cookieDomain, dominoSecret);
}

/**
* Helper method to concatenate a byte array.
*
* @param a Byte array a.
* @param b Byte array b.
* @return a + b.
*/
private static byte[] concatenate(byte[] a, byte[] b) {
if (a == null) {
return b;
} else {
byte[] bytes = new byte[a.length + b.length];

System.arraycopy(a, 0, bytes, 0, a.length);
System.arraycopy(b, 0, bytes, a.length, b.length);
return bytes;
}
}

public String getLtpaToken() {
if (ltpaToken != null) {
return ltpaToken.trim();
} else {
return null;
}
}

public void setLtpaToken(String ltpaToken) {
this.ltpaToken = ltpaToken;
}

}

我已经完成了转换,但在涉及 MessageDigest java 类 c# 等效步骤时,我似乎没有得到正确的结果。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net.Http;
using System.Text;
using System.Security.Cryptography;

namespace Authentication.Services
{
public class LtpaToken
{
private byte[] creation;
private DateTime creationDate;
private byte[] digest;
private byte[] expires;
private DateTime expiresDate;
private byte[] header;
private string ltpaToken;
private byte[] rawToken;
private byte[] user;
private string dominoSecret;

/* complex code */
private byte[] oneByte;
private int blockSize;
private int digestLength;
byte[] buffer;
private int bufOfs;
long bytesProcessed;

private int[] W;
private int[] state;

public LtpaToken(string token, string cookieName, string cookieDomain, string dominoSecret)
{

init();

ltpaToken = token;
this.dominoSecret = dominoSecret;
byte[] DS = Convert.FromBase64String(dominoSecret);
rawToken = Convert.FromBase64String(ltpaToken); //Encoding.UTF8.GetString();
user = new byte[(rawToken.Length) - 40];

for (int i = 0; i < 4; i++)
{
header[i] = rawToken[i];
}
for (int i = 4; i < 12; i++)
{
creation[i - 4] = rawToken[i];
}
for (int i = 12; i < 20; i++)
{
expires[i - 12] = rawToken[i];
}
for (int i = 20; i < (rawToken.Length - 20); i++)
{
user[i - 20] = rawToken[i];
}
for (int i = (rawToken.Length - 20); i < rawToken.Length; i++)
{
digest[i - (rawToken.Length - 20)] = rawToken[i];
}

string sheader = System.Text.Encoding.UTF8.GetString(header);
string suser = System.Text.Encoding.UTF8.GetString(user);
string sdigest = System.Text.Encoding.UTF8.GetString(digest);
string screation = System.Text.Encoding.UTF8.GetString(creation);
string sexpires = System.Text.Encoding.UTF8.GetString(expires);

//var epoch = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
//

Console.WriteLine(screation);
long hexcreationdate = long.Parse(screation, System.Globalization.NumberStyles.HexNumber);
long hexexpirationdate = long.Parse(sexpires, System.Globalization.NumberStyles.HexNumber);
Console.WriteLine(sexpires);
//
creationDate = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(Convert.ToDouble(hexcreationdate * 1000)).AddHours(2);

expiresDate = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(Convert.ToDouble(hexexpirationdate * 1000)).AddHours(2);

}

private LtpaToken()
{
init();
}


private void init()
{
creation = new byte[8];
digest = new byte[20];
expires = new byte[8];
header = new byte[4];
}

public bool isValid(string token, string cookieName, string cookieDomain, string serverHostname, string dominoSecret)
{
LtpaToken ltpaToken = new LtpaToken(token, cookieName, cookieDomain, dominoSecret);
return ltpaToken.isValid();
}

public bool isValid()
{
bool validDigest = false;
bool validDateRange = false;
byte[] newDigest;
byte[] bytes = null;
DateTime now = DateTime.Now;

bytes = concatenate(bytes, header);
bytes = concatenate(bytes, creation);
bytes = concatenate(bytes, expires);
bytes = concatenate(bytes, user);
bytes = concatenate(bytes, Convert.FromBase64String(dominoSecret));
newDigest = getSHA1(bytes);
validDigest = digestIsEqual(newDigest);
validDateRange = dateIsInRage();
string result = System.Text.Encoding.UTF8.GetString(user);

return validDigest & validDateRange;
}

private bool digestIsEqual(byte[] newDigest)
{
bool v = newDigest.SequenceEqual(digest);

switch (v)
{
case true:
return true;

default:
return false;


}
}
public static LtpaToken generate(String canonicalUser, DateTime tokenCreation, DateTime tokenExpires,
String cookieName, String cookieDomain, String dominoSecret)
{

LtpaToken ltpa = new LtpaToken();

SHA1 md = SHA1.Create();
ltpa.header = new byte[] { 0, 1, 2, 3 };
byte[] token = null;

string strCreation = tokenCreation.ToString("yyyyMMddhhmmss");
long decValue = Convert.ToInt64(strCreation);
//Convert to HEX 1245D8F5F7C8
string screation = decValue.ToString("X");

string strExpires = tokenCreation.ToString("yyyyMMddhhmmss");
long expDecValue = Convert.ToInt64(strExpires);
//Convert to HEX 1245D8F5F7C8
string sexpires = expDecValue.ToString("X");


//string screation = tokenCreation.Ticks.ToString("X4");
//string sexpires = tokenExpires.Ticks.ToString("X4");

Console.WriteLine(screation);

ltpa.creation = Encoding.ASCII.GetBytes(screation);
ltpa.expires = Encoding.ASCII.GetBytes(sexpires);
ltpa.user = Encoding.ASCII.GetBytes(canonicalUser);

token = concatenate(token, ltpa.header);
token = concatenate(token, ltpa.creation);
token = concatenate(token, ltpa.expires);
token = concatenate(token, ltpa.user);

//Console.WriteLine(Convert.ToBase64String(token));
token = getSHA1(token);
Console.WriteLine(Convert.ToBase64String(token));
//md.ComputeHash(token);

byte[] dominoBytes = Convert.FromBase64String(dominoSecret);

ltpa.digest = md.TransformFinalBlock(Convert.FromBase64String(dominoSecret), 0, dominoBytes.Length);

token = concatenate(token, ltpa.digest);

String base64encodedToken = Convert.ToBase64String(token, 0, token.Length);

Console.WriteLine(base64encodedToken);

return ltpa;
}

public static String byte2hex(byte[] b)
{
String hs = "";
String stmp = "";
for (int n = 0; n < b.Length; n++)
{
stmp = (b[n]).ToString("X4");
if (stmp.Length == 1) hs = hs + "0" + stmp;
else
{
hs = hs + stmp;
}
}
return hs.ToUpper();
}


private bool dateIsInRage()
{
if (DateTime.Now > creationDate && DateTime.Now < expiresDate)
{
return true;
}
else
{
return false;
}
}

private static byte[] getSHA1(byte[] digest)
{
SHA1CryptoServiceProvider SHAObj = new SHA1CryptoServiceProvider();
//SHAObj.ComputeHash(ASCIIEncoding.ASCII.GetBytes(digesttext));
SHAObj.ComputeHash(digest);
byte[] newSHAObj = SHAObj.Hash;
StringBuilder sb = new StringBuilder();
foreach (byte b in newSHAObj)
{
sb.Append(b.ToString("x2"));
}
return newSHAObj;

}

private static byte[] concatenate(byte[] a, byte[] b)
{
if (a == null)
{
return b;
}
else
{
byte[] bytes = new byte[a.Length + b.Length];

Array.Copy(a, 0, bytes, 0, a.Length);
Array.Copy(b, 0, bytes, a.Length, b.Length);
return bytes;
}
}
}
}

最佳答案

按照 URL http://www-12.lotus.com/ldd/doc/tools/c/7.0/api70ug.nsf/85255d56004d2bfd85255b1800631684/ceda2cb8df47607f85256c3d005f816d?OpenDocument 中的以下信息成功解决了问题

生成 Domino 样式单点登录 token

  1. 从 Web SSO 配置的 LTPA_DominoSecret 字段读取 BASE-64 编码的 secret 数据。

  2. 从 Web SSO 配置的 LTPA_TokenExpiration 字段中读取过期间隔。

  3. 以 4 个字节的版本控制 header 信息开始。Ø 版本0为[0x00][0x01][0x02][0x03]

  4. 附加创建时间。Ø 创建时间表示为距 1970 年 1 月 1 日 12:00 GMT 的偏移量(以秒为单位)。

    • 它被编码为 8 个字符的十六进制字符串。使用带有 %08x 修饰符的 printf()。
  5. 附加到期时间。Ø 过期时间也表示为距 1970 年 1 月 1 日 12:00 GMT 的偏移量(以秒为单位)。

    • 它被编码为 8 个字符的十六进制字符串。使用带有 %08x 修饰符的 printf()。
  6. 附加用户名。Ø Username的格式没有限制,但建议使用LMBCS完全标记的规范名称,最大长度为MAXUSERNAME。

  7. 根据已连接的数据加上 20 字节共享 key 生成 SHA-1 哈希(20 字节)。

  8. 在用户名后附加 SHA-1 哈希值。

  9. BASE-64 对最终标记进行编码。

关于java - Lotus Domino C# LtpaToken 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51607812/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com