记:.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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构