记:.net 海关179自行加签方法

海关加签用的ukey加签方式,拼接报文

public class SignHelper
{
private const int REQUEST_TIME_WAIT = 200;
private const int TIME_OUT = 60000;
private const string URL = "ws://127.0.0.1:61232";
private static int m_lastRequestTime;
private static readonly object m_lockThis = new object();

public static State WebSocketSign(string jsonParamStr)
{
lock (m_lockThis)
{
if (Environment.TickCount - m_lastRequestTime < REQUEST_TIME_WAIT)
Thread.Sleep(REQUEST_TIME_WAIT);

m_lastRequestTime = Environment.TickCount;
}

WebSocket websocket = new WebSocket(URL);
State state = new State()
{
Parameter = jsonParamStr
};

websocket.Error += new EventHandler<SuperSocket.ClientEngine.ErrorEventArgs>((sender, e) =>
{
state.NoWait = true;
state.Code = "404";
state.Message = "Error:" + e.Exception.Message;
state.Data = string.Empty;
});

websocket.MessageReceived += new EventHandler<MessageReceivedEventArgs>((sender, e) =>
{
try
{
state.Message = "Success";
state.Data = e.Message;
Websocket_MessageReceived(websocket, state);
}
catch (Exception ex)
{
websocket.Close();
websocket.Dispose();

state.NoWait = true;
state.Code = "404";
state.Message = "Error:" + ex.Message;
state.Data = string.Empty;
}
});

websocket.Open();

int time = Environment.TickCount;

while (!state.NoWait && Environment.TickCount - time < TIME_OUT)
Thread.Sleep(1);

websocket.Close();
websocket.Dispose();
state.Code = "200";

if (Environment.TickCount - time > TIME_OUT)
state.Message = "request time out.";

return state;
}

private static void Websocket_MessageReceived(WebSocket webSocket, State state)
{
if (state.Data.Contains("握手成功"))
{
StringBuilder postJson = new StringBuilder();

postJson.Append(state.Parameter);

JObject jObject = new JObject
{
["_method"] = "cus-sec_SpcSignDataAsPEM",
["_id"] = 1
};

JObject args = new JObject
{
["inData"] = postJson.ToString(),
["passwd"] = "88888888"
};

jObject["args"] = args;

webSocket.Send(jObject.ToString());
}
else
{
state.Data = JObject.Parse(state.Data)["_args"].ToString();
state.NoWait = true;
}
}

public static string GetSignature(string dataString)
{
string canonicalizeXmlData = Canonicalize(dataString);

SHA1 sha = new SHA1CryptoServiceProvider();
string digest = Convert.ToBase64String(sha.ComputeHash(Encoding.UTF8.GetBytes(canonicalizeXmlData)));

string signedInfoContent = GetSignedInfoContent(digest);
string signedInfoContentPlus = Canonicalize(GetSignedInfoContentPlus(digest));

State state = WebSocketSign(signedInfoContentPlus);
JObject jObject = JObject.Parse(state.Data);
JArray jArray = jObject["Data"].ToObject<JArray>();
string keyName = jArray[1].ToString();
string signatureValue = jArray[0].ToString();
string signatureXml = ComposeW3cEnvelopedSignedInfoXml(signedInfoContent, signatureValue, keyName, Convert.ToBase64String(Encoding.UTF8.GetBytes(canonicalizeXmlData)));

return ComposeW3cEnvelopedXmlEx(signatureXml, canonicalizeXmlData);
}

private static string GetSignedInfoContentPlus(string digest)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append("<ds:SignedInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"").Append(" xmlns:ceb=\"http://www.chinaport.gov.cn/ceb\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"").Append(">");
stringBuilder.Append("<ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\"/>");
stringBuilder.Append("<ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>");
stringBuilder.Append("<ds:Reference URI=\"\">");
stringBuilder.Append("<ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/></ds:Transforms>");
stringBuilder.Append("<ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/>");
stringBuilder.Append("<ds:DigestValue>");
stringBuilder.Append(digest);
stringBuilder.Append("</ds:DigestValue></ds:Reference></ds:SignedInfo>");
return stringBuilder.ToString();
}

private static string GetSignedInfoContent(string digest)
{
StringBuilder stringBuilder = new StringBuilder();

stringBuilder.Append("<ds:SignedInfo>");
stringBuilder.Append("<ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\"/>");
stringBuilder.Append("<ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>");
stringBuilder.Append("<ds:Reference URI=\"\">");
stringBuilder.Append("<ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/></ds:Transforms>");
stringBuilder.Append("<ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/>");
stringBuilder.Append("<ds:DigestValue>");
stringBuilder.Append(digest);
stringBuilder.Append("</ds:DigestValue></ds:Reference></ds:SignedInfo>");
return stringBuilder.ToString();
}

public static string Canonicalize(string xmlData)
{
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.PreserveWhitespace = true;
xmlDocument.LoadXml(xmlData);

using (MemoryStream memoryStream = new MemoryStream())
{
using (XmlWriter xmlWriter = XmlWriter.Create(memoryStream))
{
xmlDocument.WriteTo(xmlWriter);
xmlWriter.Flush();
}

memoryStream.Position = 0L;
XmlDsigC14NTransform xmlDsigC14NTransform = new XmlDsigC14NTransform();
xmlDsigC14NTransform.LoadInput(memoryStream);

using (MemoryStream transformMemoryStream = (MemoryStream)xmlDsigC14NTransform.GetOutput(typeof(Stream)))
{
return Encoding.UTF8.GetString(transformMemoryStream.ToArray());
}
}
}

private static string ComposeW3cEnvelopedSignedInfoXml(string signedInfo, string signatureValue, string keyName, string x509Data)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append("<ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">");
stringBuilder.Append(signedInfo);
stringBuilder.Append("<ds:SignatureValue>");
stringBuilder.Append(signatureValue);
stringBuilder.Append("</ds:SignatureValue>");
stringBuilder.Append("<ds:KeyInfo><ds:KeyName>");
stringBuilder.Append(keyName);
stringBuilder.Append("</ds:KeyName>");
stringBuilder.Append("</ds:KeyInfo>");
stringBuilder.Append("</ds:Signature>");
return stringBuilder.ToString();
}

private static string ComposeW3cEnvelopedXmlEx(string signatureXml, string srcData)
{
int num = srcData.LastIndexOf("</");
return string.Format("<?xml version=\"1.0\" encoding=\"UTF-8\"?>{0}{1}{2}", srcData.Substring(0, num), signatureXml, srcData.Substring(num));
}

private static readonly XmlSerializer m_serializer;
private static readonly XmlSerializer m_serializerSignature;

static SignHelper()
{
m_serializer = new XmlSerializer(typeof(SignedInfoType));
m_serializerSignature = new XmlSerializer(typeof(SignatureType));
}
public static string ADDSignature(string dataString, bool isKeyInfo = false)
{
string canonicalizeXmlData = dataString;

SHA1 sha = new SHA1CryptoServiceProvider();
string digest = Convert.ToBase64String(sha.ComputeHash(Encoding.UTF8.GetBytes(canonicalizeXmlData)));

SignedInfoType signedInfo = GetSignedInfo(digest);

StringBuilder stringBuilder = new StringBuilder();
XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
namespaces.Add("ceb", "http://www.chinaport.gov.cn/ceb");
namespaces.Add("ds", "http://www.w3.org/2000/09/xmldsig#");
namespaces.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
string xmlValue = string.Empty;
using (StringWriter stringWriter = new StringWriter(stringBuilder))
{
m_serializer.Serialize(stringWriter, signedInfo, namespaces);
xmlValue = stringWriter.ToString();
}

State state = WebSocketSign(xmlValue);
JObject jObject = JObject.Parse(state.Data);
JArray jArray = jObject["Data"].ToObject<JArray>();

string keyName = null;

if (isKeyInfo)
keyName = jArray[1].ToString();

string signatureValue = jArray[0].ToString();

SignatureType signature = GetSignature(signedInfo, signatureValue, keyName);

StringBuilder signatureStringBuilder = new StringBuilder();
XmlSerializerNamespaces signatureNamespaces = new XmlSerializerNamespaces();
namespaces.Add("ds", "http://www.w3.org/2000/09/xmldsig#");
string signatureXmlValue = string.Empty;
using (StringWriter stringWriter = new StringWriter(signatureStringBuilder))
{
m_serializerSignature.Serialize(stringWriter, signature, signatureNamespaces);
signatureXmlValue = stringWriter.ToString();
}

return signatureXmlValue;
}

public static SignedInfoType GetSignedInfo(string digest)
{
SignedInfoType signedInfo = new SignedInfoType();
signedInfo.CanonicalizationMethod = new CanonicalizationMethodType();
signedInfo.SignatureMethod = new SignatureMethodType();

ReferenceType reference = new ReferenceType();

TransformType transform = new TransformType();
reference.Transforms = new TransformType[] { transform };
reference.DigestMethod = new DigestMethodType();

reference.DigestValue = Encoding.UTF8.GetBytes(digest);

signedInfo.Reference = new ReferenceType[] { reference };

return signedInfo;
}

private static SignatureType GetSignature(SignedInfoType signedInfo, string signatureValue, string keyName = null)
{
SignatureType signature = new SignatureType();

signature.SignedInfo = signedInfo;

SignatureValueType signatureValueType = new SignatureValueType();

signatureValueType.Value = Encoding.UTF8.GetBytes(signatureValue);

signature.SignatureValue = signatureValueType;

if (!string.IsNullOrWhiteSpace(keyName))
{
KeyInfoType keyInfo = new KeyInfoType();

keyInfo.ItemsElementName = new ItemsChoiceType2[] { ItemsChoiceType2.KeyName };
keyInfo.Items = new object[] { keyName };

signature.KeyInfo = keyInfo;
}

return signature;
}
}

#region Object

public class JsonParam
{
public string JsonParamStr { get; set; }
}

public class State
{
public string Message { get; set; }

public bool NoWait { get; set; }

public string Data { get; set; }

public string Parameter { get; set; }

public string Code { get; set; }
}

#endregion Object

posted @   六月Talk  阅读(295)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示