V0.37.0.250711_alpha:新增一个数字签名项目
This commit is contained in:
parent
729d4dcaa9
commit
b1f1c4970f
@ -1,141 +1,173 @@
|
||||
<mxfile host="Electron" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/25.0.2 Chrome/128.0.6613.186 Electron/32.2.5 Safari/537.36" version="25.0.2">
|
||||
<mxfile host="Electron" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/26.2.2 Chrome/134.0.6998.178 Electron/35.1.2 Safari/537.36" version="26.2.2">
|
||||
<diagram name="第 1 页" id="n4mM9-rLUw7j7IC2DLn1">
|
||||
<mxGraphModel dx="676" dy="395" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
||||
<mxGraphModel dx="1680" dy="991" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-109" value="" style="group" vertex="1" connectable="0" parent="1">
|
||||
<mxGeometry x="40" y="240" width="460" height="650" as="geometry" />
|
||||
<mxCell id="nnVTWkkhsZWMSzmyXnU6-1" value="" style="group" vertex="1" connectable="0" parent="1">
|
||||
<mxGeometry x="40" y="40" width="340" height="140" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-42" value="<font>仿真调度引擎退出</font>" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.terminator;whiteSpace=wrap;fontSize=16;labelBackgroundColor=none;fillColor=#E6FFCC;" vertex="1" parent="DPG0hEwUPDznWshsaorW-109">
|
||||
<mxGeometry x="190" y="610" width="140" height="40" as="geometry" />
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-37" value="仿真调度引擎" style="rounded=0;whiteSpace=wrap;html=1;fontSize=16;fillColor=#FFFFCC;fontStyle=1;verticalAlign=top;" parent="nnVTWkkhsZWMSzmyXnU6-1" vertex="1">
|
||||
<mxGeometry width="340" height="140" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-43" value="<span style="font-size: 16px;">仿真调度引擎启动</span>" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.start_1;whiteSpace=wrap;labelBackgroundColor=none;fillColor=#E6FFCC;" vertex="1" parent="DPG0hEwUPDznWshsaorW-109">
|
||||
<mxGeometry x="180" width="160" height="40" as="geometry" />
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-36" value="仿真运行控制" style="rounded=0;whiteSpace=wrap;html=1;fontSize=16;fillColor=#FFFF99;" parent="nnVTWkkhsZWMSzmyXnU6-1" vertex="1">
|
||||
<mxGeometry x="10" y="90" width="150" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-44" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;labelBackgroundColor=none;entryX=1;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="DPG0hEwUPDznWshsaorW-109" source="DPG0hEwUPDznWshsaorW-79" target="DPG0hEwUPDznWshsaorW-42">
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-38" value="仿真运行状态发布" style="rounded=0;whiteSpace=wrap;html=1;fontSize=16;fillColor=#FFFF99;" parent="nnVTWkkhsZWMSzmyXnU6-1" vertex="1">
|
||||
<mxGeometry x="180" y="90" width="150" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-107" value="构型验证" style="rounded=0;whiteSpace=wrap;html=1;fontSize=16;fillColor=#FFFF99;" parent="nnVTWkkhsZWMSzmyXnU6-1" vertex="1">
|
||||
<mxGeometry x="180" y="40" width="150" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-108" value="命令参数解析" style="rounded=0;whiteSpace=wrap;html=1;fontSize=16;fillColor=#FFFF99;" parent="nnVTWkkhsZWMSzmyXnU6-1" vertex="1">
|
||||
<mxGeometry x="10" y="40" width="150" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="nnVTWkkhsZWMSzmyXnU6-14" value="" style="group" vertex="1" connectable="0" parent="1">
|
||||
<mxGeometry x="30" y="240" width="490" height="860" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-42" value="<font>结束</font>" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.terminator;whiteSpace=wrap;fontSize=16;labelBackgroundColor=none;fillColor=#FFFFCC;" parent="nnVTWkkhsZWMSzmyXnU6-14" vertex="1">
|
||||
<mxGeometry x="280" y="820" width="140" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-43" value="<span style="font-size: 16px;">开始</span>" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.start_1;whiteSpace=wrap;labelBackgroundColor=none;fillColor=#FFFFCC;" parent="nnVTWkkhsZWMSzmyXnU6-14" vertex="1">
|
||||
<mxGeometry x="190" width="160" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-44" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;labelBackgroundColor=none;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" parent="nnVTWkkhsZWMSzmyXnU6-14" source="DPG0hEwUPDznWshsaorW-79" target="DPG0hEwUPDznWshsaorW-42" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="480" y="430" as="targetPoint" />
|
||||
<mxPoint x="490" y="570" as="targetPoint" />
|
||||
<Array as="points">
|
||||
<mxPoint x="430" y="800" />
|
||||
<mxPoint x="350" y="800" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-80" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="DPG0hEwUPDznWshsaorW-109" source="DPG0hEwUPDznWshsaorW-45" target="DPG0hEwUPDznWshsaorW-79">
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-76" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;fontSize=14;" parent="nnVTWkkhsZWMSzmyXnU6-14" source="DPG0hEwUPDznWshsaorW-48" target="DPG0hEwUPDznWshsaorW-63" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-45" value="预加载仿真内核" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;fontSize=16;labelBackgroundColor=none;fillColor=#E6FFCC;" vertex="1" parent="DPG0hEwUPDznWshsaorW-109">
|
||||
<mxGeometry x="340" y="210" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-76" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;fontSize=14;" edge="1" parent="DPG0hEwUPDznWshsaorW-109" source="DPG0hEwUPDznWshsaorW-48" target="DPG0hEwUPDznWshsaorW-51">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-77" value="<font style="font-size: 14px;">N</font>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="DPG0hEwUPDznWshsaorW-76">
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-77" value="<font style="font-size: 14px;">N</font>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=none;" parent="DPG0hEwUPDznWshsaorW-76" vertex="1" connectable="0">
|
||||
<mxGeometry x="0.2286" relative="1" as="geometry">
|
||||
<mxPoint x="-10" y="-8" as="offset" />
|
||||
<mxPoint x="-10" y="-1" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-48" value="<span style="font-size: 16px;">预加载模式?</span>" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;labelBackgroundColor=none;fillColor=#E6FFCC;" vertex="1" parent="DPG0hEwUPDznWshsaorW-109">
|
||||
<mxGeometry x="190" y="120" width="140" height="60" as="geometry" />
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-48" value="<span style="font-size: 16px;">测试模式?</span>" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;labelBackgroundColor=none;fillColor=#FFFFCC;" parent="nnVTWkkhsZWMSzmyXnU6-14" vertex="1">
|
||||
<mxGeometry x="200" y="380" width="140" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-81" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="DPG0hEwUPDznWshsaorW-109" source="DPG0hEwUPDznWshsaorW-51" target="DPG0hEwUPDznWshsaorW-59">
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-81" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="nnVTWkkhsZWMSzmyXnU6-14" source="DPG0hEwUPDznWshsaorW-51" target="DPG0hEwUPDznWshsaorW-59" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-51" value="加载仿真内核" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;fontSize=16;labelBackgroundColor=none;fillColor=#E6FFCC;" vertex="1" parent="DPG0hEwUPDznWshsaorW-109">
|
||||
<mxGeometry x="210" y="210" width="100" height="40" as="geometry" />
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-51" value="加载仿真内核" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;fontSize=16;labelBackgroundColor=none;fillColor=#FFFFCC;" parent="nnVTWkkhsZWMSzmyXnU6-14" vertex="1">
|
||||
<mxGeometry x="210" y="120" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-58" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;labelBackgroundColor=none;" edge="1" parent="DPG0hEwUPDznWshsaorW-109" source="DPG0hEwUPDznWshsaorW-59" target="DPG0hEwUPDznWshsaorW-63">
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-58" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;labelBackgroundColor=none;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="nnVTWkkhsZWMSzmyXnU6-14" source="DPG0hEwUPDznWshsaorW-59" target="nnVTWkkhsZWMSzmyXnU6-2" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="260" y="329.9999999999999" as="targetPoint" />
|
||||
<mxPoint x="270" y="389.9999999999999" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-59" value="初始化仿真内核" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;fontSize=16;labelBackgroundColor=none;fillColor=#E6FFCC;" vertex="1" parent="DPG0hEwUPDznWshsaorW-109">
|
||||
<mxGeometry x="200" y="270" width="120" height="40" as="geometry" />
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-59" value="初始化仿真内核" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;fontSize=16;labelBackgroundColor=none;fillColor=#FFFFCC;" parent="nnVTWkkhsZWMSzmyXnU6-14" vertex="1">
|
||||
<mxGeometry x="210" y="180" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-62" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;labelBackgroundColor=none;" edge="1" parent="DPG0hEwUPDznWshsaorW-109" source="DPG0hEwUPDznWshsaorW-63" target="DPG0hEwUPDznWshsaorW-98">
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-62" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;labelBackgroundColor=none;" parent="nnVTWkkhsZWMSzmyXnU6-14" source="DPG0hEwUPDznWshsaorW-63" target="DPG0hEwUPDznWshsaorW-98" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="260" y="390" as="targetPoint" />
|
||||
<mxPoint x="270" y="530" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-63" value="启动仿真内核" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;fontSize=16;labelBackgroundColor=none;fillColor=#E6FFCC;" vertex="1" parent="DPG0hEwUPDznWshsaorW-109">
|
||||
<mxGeometry x="200" y="330" width="120" height="40" as="geometry" />
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-63" value="启动仿真" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;fontSize=16;labelBackgroundColor=none;fillColor=#FFFFCC;" parent="nnVTWkkhsZWMSzmyXnU6-14" vertex="1">
|
||||
<mxGeometry x="210" y="470" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-65" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;labelBackgroundColor=none;" edge="1" parent="DPG0hEwUPDznWshsaorW-109" source="DPG0hEwUPDznWshsaorW-82" target="DPG0hEwUPDznWshsaorW-42">
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-65" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;labelBackgroundColor=none;" parent="nnVTWkkhsZWMSzmyXnU6-14" source="DPG0hEwUPDznWshsaorW-82" target="DPG0hEwUPDznWshsaorW-42" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-67" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;labelBackgroundColor=none;" edge="1" parent="DPG0hEwUPDznWshsaorW-109" source="DPG0hEwUPDznWshsaorW-43" target="DPG0hEwUPDznWshsaorW-74">
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-67" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;labelBackgroundColor=none;" parent="nnVTWkkhsZWMSzmyXnU6-14" source="DPG0hEwUPDznWshsaorW-43" target="DPG0hEwUPDznWshsaorW-74" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="316" y="60" as="targetPoint" />
|
||||
<mxPoint x="326" y="60" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-70" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;fontSize=14;exitX=1;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;labelBackgroundColor=none;" edge="1" parent="DPG0hEwUPDznWshsaorW-109" source="DPG0hEwUPDznWshsaorW-48" target="DPG0hEwUPDznWshsaorW-45">
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-70" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.25;entryY=0;entryDx=0;entryDy=0;fontSize=14;exitX=1;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;labelBackgroundColor=none;" parent="nnVTWkkhsZWMSzmyXnU6-14" source="DPG0hEwUPDznWshsaorW-48" target="DPG0hEwUPDznWshsaorW-79" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="398.5" y="90" as="sourcePoint" />
|
||||
<mxPoint x="376" y="470" as="targetPoint" />
|
||||
<mxPoint x="408.5" y="230" as="sourcePoint" />
|
||||
<mxPoint x="410" y="350" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-71" value="Y" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=14;labelBackgroundColor=none;" vertex="1" connectable="0" parent="DPG0hEwUPDznWshsaorW-70">
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-71" value="Y" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=14;labelBackgroundColor=none;" parent="DPG0hEwUPDznWshsaorW-70" vertex="1" connectable="0">
|
||||
<mxGeometry x="0.0439" relative="1" as="geometry">
|
||||
<mxPoint x="-69" y="-10" as="offset" />
|
||||
<mxPoint x="-50" y="-10" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-74" value="命令参数解析" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;fontSize=16;labelBackgroundColor=none;fillColor=#E6FFCC;" vertex="1" parent="DPG0hEwUPDznWshsaorW-109">
|
||||
<mxGeometry x="200" y="60" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-75" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="DPG0hEwUPDznWshsaorW-109" source="DPG0hEwUPDznWshsaorW-74" target="DPG0hEwUPDznWshsaorW-48">
|
||||
<mxCell id="nnVTWkkhsZWMSzmyXnU6-3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="nnVTWkkhsZWMSzmyXnU6-14" source="DPG0hEwUPDznWshsaorW-74" target="DPG0hEwUPDznWshsaorW-51">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-79" value="输出校验信息" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;fontSize=16;labelBackgroundColor=none;fillColor=#E6FFCC;" vertex="1" parent="DPG0hEwUPDznWshsaorW-109">
|
||||
<mxGeometry x="340" y="270" width="120" height="40" as="geometry" />
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-74" value="命令参数解析" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;fontSize=16;labelBackgroundColor=none;fillColor=#FFFFCC;" parent="nnVTWkkhsZWMSzmyXnU6-14" vertex="1">
|
||||
<mxGeometry x="210" y="60" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-82" value="卸载仿真内核" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;fontSize=16;labelBackgroundColor=none;fillColor=#E6FFCC;" vertex="1" parent="DPG0hEwUPDznWshsaorW-109">
|
||||
<mxGeometry x="200" y="550" width="120" height="40" as="geometry" />
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-75" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" parent="nnVTWkkhsZWMSzmyXnU6-14" source="nnVTWkkhsZWMSzmyXnU6-2" target="nnVTWkkhsZWMSzmyXnU6-9" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="280" y="160" as="sourcePoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-87" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="DPG0hEwUPDznWshsaorW-109" source="DPG0hEwUPDznWshsaorW-86" target="DPG0hEwUPDznWshsaorW-82">
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-79" value="输出验证结果" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;fontSize=16;labelBackgroundColor=none;fillColor=#FFFFCC;" parent="nnVTWkkhsZWMSzmyXnU6-14" vertex="1">
|
||||
<mxGeometry x="370" y="470" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-82" value="卸载仿真内核" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;fontSize=16;labelBackgroundColor=none;fillColor=#FFFFCC;" parent="nnVTWkkhsZWMSzmyXnU6-14" vertex="1">
|
||||
<mxGeometry x="210" y="740" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-87" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="nnVTWkkhsZWMSzmyXnU6-14" source="DPG0hEwUPDznWshsaorW-86" target="DPG0hEwUPDznWshsaorW-82" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-102" value="如果是终止指令" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="DPG0hEwUPDznWshsaorW-87">
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-102" value="终止指令" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=none;" parent="DPG0hEwUPDznWshsaorW-87" vertex="1" connectable="0">
|
||||
<mxGeometry x="-0.1111" y="-1" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
<mxPoint x="31" y="-3" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-104" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="DPG0hEwUPDznWshsaorW-109" source="DPG0hEwUPDznWshsaorW-86" target="DPG0hEwUPDznWshsaorW-103">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-104" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="nnVTWkkhsZWMSzmyXnU6-14" source="DPG0hEwUPDznWshsaorW-86" target="DPG0hEwUPDznWshsaorW-103" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="120" y="680" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-106" value="暂停/继续指令" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="DPG0hEwUPDznWshsaorW-104">
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-106" value="暂停/继续指令" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=none;" parent="DPG0hEwUPDznWshsaorW-104" vertex="1" connectable="0">
|
||||
<mxGeometry x="-0.2444" y="1" relative="1" as="geometry">
|
||||
<mxPoint x="-4" y="9" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-86" value="<span style="font-size: 16px;">收到控制指令?</span>" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;labelBackgroundColor=none;fillColor=#E6FFCC;" vertex="1" parent="DPG0hEwUPDznWshsaorW-109">
|
||||
<mxGeometry x="190" y="450" width="140" height="60" as="geometry" />
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-86" value="<span style="font-size: 16px;">收到控制指令?</span>" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;labelBackgroundColor=none;fillColor=#FFFFCC;" parent="nnVTWkkhsZWMSzmyXnU6-14" vertex="1">
|
||||
<mxGeometry x="200" y="650" width="140" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-98" value="控制指令监听" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;fontSize=16;labelBackgroundColor=none;fillColor=#E6FFCC;" vertex="1" parent="DPG0hEwUPDznWshsaorW-109">
|
||||
<mxGeometry x="200" y="390" width="120" height="40" as="geometry" />
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-98" value="控制指令监听" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;fontSize=16;labelBackgroundColor=none;fillColor=#FFFFCC;" parent="nnVTWkkhsZWMSzmyXnU6-14" vertex="1">
|
||||
<mxGeometry x="210" y="530" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-99" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="DPG0hEwUPDznWshsaorW-109" source="DPG0hEwUPDznWshsaorW-98" target="DPG0hEwUPDznWshsaorW-86">
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-99" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="nnVTWkkhsZWMSzmyXnU6-14" source="DPG0hEwUPDznWshsaorW-98" target="nnVTWkkhsZWMSzmyXnU6-4" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-105" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="DPG0hEwUPDznWshsaorW-109" source="DPG0hEwUPDznWshsaorW-103" target="DPG0hEwUPDznWshsaorW-98">
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-105" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="nnVTWkkhsZWMSzmyXnU6-14" source="DPG0hEwUPDznWshsaorW-103" target="nnVTWkkhsZWMSzmyXnU6-4" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="60" y="660" as="sourcePoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-103" value="控制仿真内核" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;fontSize=16;labelBackgroundColor=none;fillColor=#FFFFCC;" parent="nnVTWkkhsZWMSzmyXnU6-14" vertex="1">
|
||||
<mxGeometry y="660" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="nnVTWkkhsZWMSzmyXnU6-2" value="构型验证" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;fontSize=16;labelBackgroundColor=none;fillColor=#FFFFCC;" vertex="1" parent="nnVTWkkhsZWMSzmyXnU6-14">
|
||||
<mxGeometry x="210" y="240" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="nnVTWkkhsZWMSzmyXnU6-4" value="仿真运行状态<div>发布</div>" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;fontSize=16;labelBackgroundColor=none;fillColor=#FFFFCC;" vertex="1" parent="nnVTWkkhsZWMSzmyXnU6-14">
|
||||
<mxGeometry x="210" y="590" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="nnVTWkkhsZWMSzmyXnU6-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="nnVTWkkhsZWMSzmyXnU6-14" source="nnVTWkkhsZWMSzmyXnU6-4" target="DPG0hEwUPDznWshsaorW-86">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-103" value="控制仿真内核" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;fontSize=16;labelBackgroundColor=none;fillColor=#E6FFCC;" vertex="1" parent="DPG0hEwUPDznWshsaorW-109">
|
||||
<mxGeometry y="460" width="120" height="40" as="geometry" />
|
||||
<mxCell id="nnVTWkkhsZWMSzmyXnU6-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.75;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="nnVTWkkhsZWMSzmyXnU6-14" source="nnVTWkkhsZWMSzmyXnU6-9" target="DPG0hEwUPDznWshsaorW-79">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-110" value="" style="group" vertex="1" connectable="0" parent="1">
|
||||
<mxGeometry x="40" y="40" width="340" height="140" as="geometry" />
|
||||
<mxCell id="nnVTWkkhsZWMSzmyXnU6-13" value="N" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="nnVTWkkhsZWMSzmyXnU6-11">
|
||||
<mxGeometry x="-0.7077" y="1" relative="1" as="geometry">
|
||||
<mxPoint x="-28" y="-9" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-37" value="仿真调度引擎" style="rounded=0;whiteSpace=wrap;html=1;fontSize=16;fillColor=#E6FFCC;fontStyle=1;verticalAlign=top;" vertex="1" parent="DPG0hEwUPDznWshsaorW-110">
|
||||
<mxGeometry width="340" height="140" as="geometry" />
|
||||
<mxCell id="nnVTWkkhsZWMSzmyXnU6-9" value="<span style="font-size: 16px;">验证通过?</span>" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;labelBackgroundColor=none;fillColor=#FFFFCC;" vertex="1" parent="nnVTWkkhsZWMSzmyXnU6-14">
|
||||
<mxGeometry x="200" y="300" width="140" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-36" value="仿真内核加载及调用" style="rounded=0;whiteSpace=wrap;html=1;fontSize=16;fillColor=#CCFF99;" vertex="1" parent="DPG0hEwUPDznWshsaorW-110">
|
||||
<mxGeometry x="10" y="90" width="150" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-38" value="控制指令监听及仿真运行控制" style="rounded=0;whiteSpace=wrap;html=1;fontSize=16;fillColor=#CCFF99;" vertex="1" parent="DPG0hEwUPDznWshsaorW-110">
|
||||
<mxGeometry x="180" y="90" width="150" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-107" value="仿真内核预加载" style="rounded=0;whiteSpace=wrap;html=1;fontSize=16;fillColor=#CCFF99;" vertex="1" parent="DPG0hEwUPDznWshsaorW-110">
|
||||
<mxGeometry x="180" y="40" width="150" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DPG0hEwUPDznWshsaorW-108" value="命令参数解析" style="rounded=0;whiteSpace=wrap;html=1;fontSize=16;fillColor=#CCFF99;" vertex="1" parent="DPG0hEwUPDznWshsaorW-110">
|
||||
<mxGeometry x="10" y="40" width="150" height="40" as="geometry" />
|
||||
<mxCell id="nnVTWkkhsZWMSzmyXnU6-10" value="Y" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="nnVTWkkhsZWMSzmyXnU6-14" source="nnVTWkkhsZWMSzmyXnU6-9" target="DPG0hEwUPDznWshsaorW-48">
|
||||
<mxGeometry y="-10" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -256,8 +256,6 @@ public:
|
||||
using ThisType = cls; \
|
||||
using SuperType = sup;
|
||||
|
||||
#define XN_UNUSED(x) (void)x
|
||||
|
||||
namespace XNSim
|
||||
{
|
||||
template <typename T>
|
||||
|
@ -28,7 +28,7 @@ public:
|
||||
/**
|
||||
* @brief 日志等级
|
||||
*/
|
||||
enum LogLevel { Debug, Info, Warning, Error, Time };
|
||||
enum LogLevel { Debug, Info, Warning, Error };
|
||||
|
||||
/**
|
||||
* @brief 获取日志类实例
|
||||
@ -128,7 +128,7 @@ private:
|
||||
/**
|
||||
* @brief 调试颜色常量
|
||||
*/
|
||||
const std::string COLOR_DEBUG = "\033[34m"; // 蓝色
|
||||
const std::string COLOR_DEBUG = "\033[36m"; // 青色
|
||||
|
||||
/**
|
||||
* @brief 信息颜色常量
|
||||
@ -217,18 +217,20 @@ private:
|
||||
"A01021002: 单条日志参数数量超过限制,详见XNLogger.cpp:line 216");
|
||||
|
||||
std::string result = message;
|
||||
// 使用初始化列表展开参数包
|
||||
|
||||
// 使用折叠表达式展开参数包
|
||||
int index = 1;
|
||||
// 使用lambda和std::initializer_list展开参数包
|
||||
(void)std::initializer_list<int>{(
|
||||
[&result, &index](const auto &value) {
|
||||
std::string placeholder = "%" + std::to_string(index++);
|
||||
size_t pos = result.find(placeholder);
|
||||
if (pos != std::string::npos) {
|
||||
result.replace(pos, placeholder.length(), convertToString(value));
|
||||
}
|
||||
}(args),
|
||||
0)...};
|
||||
// 定义替换单个参数的lambda函数
|
||||
auto replacePlaceholder = [&result, &index](const auto &value) {
|
||||
std::string placeholder = "%" + std::to_string(index++);
|
||||
size_t pos = result.find(placeholder);
|
||||
if (pos != std::string::npos) {
|
||||
result.replace(pos, placeholder.length(), convertToString(value));
|
||||
}
|
||||
};
|
||||
|
||||
// 使用折叠表达式对每个参数调用替换函数
|
||||
(replacePlaceholder(args), ...);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
@ -236,19 +238,35 @@ private:
|
||||
/**
|
||||
* @brief 宏定义,用于输出调试日志
|
||||
*/
|
||||
#define LOG_DEBUG(message, ...) XNLoggerHelper::log(XNLogger::Debug, message, ##__VA_ARGS__)
|
||||
template <typename... Args>
|
||||
inline void LOG_DEBUG(const std::string &message, Args &&...args)
|
||||
{
|
||||
XNLoggerHelper::log(XNLogger::Debug, message, args...);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于输出信息日志
|
||||
* @brief 模板函数,用于输出信息日志
|
||||
*/
|
||||
#define LOG_INFO(message, ...) XNLoggerHelper::log(XNLogger::Info, message, ##__VA_ARGS__)
|
||||
template <typename... Args>
|
||||
inline void LOG_INFO(const std::string &message, Args &&...args)
|
||||
{
|
||||
XNLoggerHelper::log(XNLogger::Info, message, args...);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于输出警告日志
|
||||
* @brief 模板函数,用于输出警告日志
|
||||
*/
|
||||
#define LOG_WARNING(message, ...) XNLoggerHelper::log(XNLogger::Warning, message, ##__VA_ARGS__)
|
||||
template <typename... Args>
|
||||
inline void LOG_WARNING(const std::string &message, Args &&...args)
|
||||
{
|
||||
XNLoggerHelper::log(XNLogger::Warning, message, args...);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于输出错误日志
|
||||
* @brief 模板函数,用于输出错误日志
|
||||
*/
|
||||
#define LOG_ERROR(message, ...) XNLoggerHelper::log(XNLogger::Error, message, ##__VA_ARGS__)
|
||||
template <typename... Args>
|
||||
inline void LOG_ERROR(const std::string &message, Args &&...args)
|
||||
{
|
||||
XNLoggerHelper::log(XNLogger::Error, message, args...);
|
||||
}
|
||||
|
@ -4,8 +4,6 @@
|
||||
#include "TypeDefine.h"
|
||||
#include "TopicManager.h"
|
||||
|
||||
#define THISUNUSED(x) (void)(x)
|
||||
|
||||
class XNFramework;
|
||||
using XNFrameworkPtr = std::shared_ptr<XNFramework>;
|
||||
|
||||
@ -40,11 +38,10 @@ public:
|
||||
_isInitialized = false;
|
||||
};
|
||||
|
||||
virtual void Initialize(XNFrameworkPtr framework, uint32_t modelId, uint32_t DDS_type) override
|
||||
virtual void Initialize(XNFrameworkPtr framework [[maybe_unused]],
|
||||
uint32_t modelId [[maybe_unused]],
|
||||
uint32_t DDS_type [[maybe_unused]]) override
|
||||
{
|
||||
THISUNUSED(framework);
|
||||
THISUNUSED(modelId);
|
||||
THISUNUSED(DDS_type);
|
||||
XNDDSErrorCode ret =
|
||||
TopicManager::Instance()->registerSubscriber<typename T::DDSPubSubType>(
|
||||
T::topic_name,
|
||||
|
9
Release/public_key.pem
Normal file
9
Release/public_key.pem
Normal file
@ -0,0 +1,9 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxdmYwjqt2Jd7+PW4N/qi
|
||||
KQALeEd4j6RqIiXMm8zYYYQSe3SSrEuOZYhUKqFcYX9KwEo05SeiJm6oiHJw/ADw
|
||||
H6Tcn3XoNICrfeMdkpCV1OpAHq9WjaueYtwy3EZgBh7iFx0jOY8a4fpQUL+KeID9
|
||||
qeAYU+BXbPDIOkGVIu2saDfdwfMW2shR6kaNAto66MhfZMSqcGQfN9NkhmsdXahC
|
||||
WuulopiM0k95LMr15TM3fqAvOOIvT+Us8l8OnnGYDYWPx6Gva3DILLa6ZvUXsLUE
|
||||
519inlKdIILYszHCLnfs8hQPPrPk8Fa85v0PVVdSbBORCsQ0r9dN0dBFGJ/yGC8j
|
||||
FQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
@ -256,8 +256,6 @@ public:
|
||||
using ThisType = cls; \
|
||||
using SuperType = sup;
|
||||
|
||||
#define XN_UNUSED(x) (void)x
|
||||
|
||||
namespace XNSim
|
||||
{
|
||||
template <typename T>
|
||||
|
@ -69,23 +69,16 @@ void XNLogger::log(LogLevel level, const std::string &message)
|
||||
break;
|
||||
}
|
||||
|
||||
coloredMessage += "\n";
|
||||
|
||||
// 控制台输出
|
||||
if (consoleOutputEnabled[level]) {
|
||||
if (level == Time) {
|
||||
// 如果是时间日志,则不换行,回退到该行开始
|
||||
std::cout << coloredMessage << "\r" << std::flush;
|
||||
} else {
|
||||
std::cout << coloredMessage << std::endl;
|
||||
}
|
||||
std::cout << coloredMessage;
|
||||
}
|
||||
|
||||
// 文件输出
|
||||
if (fileOutputEnabled[level] && logFile.is_open()) {
|
||||
if (level == Time) {
|
||||
logFile << logMessage << "\r" << std::flush;
|
||||
} else {
|
||||
logFile << logMessage << std::endl;
|
||||
}
|
||||
logFile << logMessage;
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,8 +103,6 @@ std::string XNLogger::logLevelToString(LogLevel level) const
|
||||
return "WARNING";
|
||||
case Error:
|
||||
return "ERROR";
|
||||
case Time:
|
||||
return "TIME";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ public:
|
||||
/**
|
||||
* @brief 日志等级
|
||||
*/
|
||||
enum LogLevel { Debug, Info, Warning, Error, Time };
|
||||
enum LogLevel { Debug, Info, Warning, Error };
|
||||
|
||||
/**
|
||||
* @brief 获取日志类实例
|
||||
@ -128,7 +128,7 @@ private:
|
||||
/**
|
||||
* @brief 调试颜色常量
|
||||
*/
|
||||
const std::string COLOR_DEBUG = "\033[34m"; // 蓝色
|
||||
const std::string COLOR_DEBUG = "\033[36m"; // 青色
|
||||
|
||||
/**
|
||||
* @brief 信息颜色常量
|
||||
@ -217,18 +217,20 @@ private:
|
||||
"A01021002: 单条日志参数数量超过限制,详见XNLogger.cpp:line 216");
|
||||
|
||||
std::string result = message;
|
||||
// 使用初始化列表展开参数包
|
||||
|
||||
// 使用折叠表达式展开参数包
|
||||
int index = 1;
|
||||
// 使用lambda和std::initializer_list展开参数包
|
||||
(void)std::initializer_list<int>{(
|
||||
[&result, &index](const auto &value) {
|
||||
std::string placeholder = "%" + std::to_string(index++);
|
||||
size_t pos = result.find(placeholder);
|
||||
if (pos != std::string::npos) {
|
||||
result.replace(pos, placeholder.length(), convertToString(value));
|
||||
}
|
||||
}(args),
|
||||
0)...};
|
||||
// 定义替换单个参数的lambda函数
|
||||
auto replacePlaceholder = [&result, &index](const auto &value) {
|
||||
std::string placeholder = "%" + std::to_string(index++);
|
||||
size_t pos = result.find(placeholder);
|
||||
if (pos != std::string::npos) {
|
||||
result.replace(pos, placeholder.length(), convertToString(value));
|
||||
}
|
||||
};
|
||||
|
||||
// 使用折叠表达式对每个参数调用替换函数
|
||||
(replacePlaceholder(args), ...);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
@ -236,19 +238,35 @@ private:
|
||||
/**
|
||||
* @brief 宏定义,用于输出调试日志
|
||||
*/
|
||||
#define LOG_DEBUG(message, ...) XNLoggerHelper::log(XNLogger::Debug, message, ##__VA_ARGS__)
|
||||
template <typename... Args>
|
||||
inline void LOG_DEBUG(const std::string &message, Args &&...args)
|
||||
{
|
||||
XNLoggerHelper::log(XNLogger::Debug, message, args...);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于输出信息日志
|
||||
* @brief 模板函数,用于输出信息日志
|
||||
*/
|
||||
#define LOG_INFO(message, ...) XNLoggerHelper::log(XNLogger::Info, message, ##__VA_ARGS__)
|
||||
template <typename... Args>
|
||||
inline void LOG_INFO(const std::string &message, Args &&...args)
|
||||
{
|
||||
XNLoggerHelper::log(XNLogger::Info, message, args...);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于输出警告日志
|
||||
* @brief 模板函数,用于输出警告日志
|
||||
*/
|
||||
#define LOG_WARNING(message, ...) XNLoggerHelper::log(XNLogger::Warning, message, ##__VA_ARGS__)
|
||||
template <typename... Args>
|
||||
inline void LOG_WARNING(const std::string &message, Args &&...args)
|
||||
{
|
||||
XNLoggerHelper::log(XNLogger::Warning, message, args...);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于输出错误日志
|
||||
* @brief 模板函数,用于输出错误日志
|
||||
*/
|
||||
#define LOG_ERROR(message, ...) XNLoggerHelper::log(XNLogger::Error, message, ##__VA_ARGS__)
|
||||
template <typename... Args>
|
||||
inline void LOG_ERROR(const std::string &message, Args &&...args)
|
||||
{
|
||||
XNLoggerHelper::log(XNLogger::Error, message, args...);
|
||||
}
|
||||
|
@ -4,8 +4,6 @@
|
||||
#include "TypeDefine.h"
|
||||
#include "TopicManager.h"
|
||||
|
||||
#define THISUNUSED(x) (void)(x)
|
||||
|
||||
class XNFramework;
|
||||
using XNFrameworkPtr = std::shared_ptr<XNFramework>;
|
||||
|
||||
@ -40,11 +38,10 @@ public:
|
||||
_isInitialized = false;
|
||||
};
|
||||
|
||||
virtual void Initialize(XNFrameworkPtr framework, uint32_t modelId, uint32_t DDS_type) override
|
||||
virtual void Initialize(XNFrameworkPtr framework [[maybe_unused]],
|
||||
uint32_t modelId [[maybe_unused]],
|
||||
uint32_t DDS_type [[maybe_unused]]) override
|
||||
{
|
||||
THISUNUSED(framework);
|
||||
THISUNUSED(modelId);
|
||||
THISUNUSED(DDS_type);
|
||||
XNDDSErrorCode ret =
|
||||
TopicManager::Instance()->registerSubscriber<typename T::DDSPubSubType>(
|
||||
T::topic_name,
|
||||
|
56
XNSignature/CMakeLists.txt
Normal file
56
XNSignature/CMakeLists.txt
Normal file
@ -0,0 +1,56 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(XNSignature LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# 获取环境变量
|
||||
if(DEFINED ENV{XNCore})
|
||||
set(XNCore_PATH $ENV{XNCore})
|
||||
else()
|
||||
message(FATAL_ERROR "Environment variable XNCore is not set.")
|
||||
endif()
|
||||
|
||||
# 查找依赖包
|
||||
find_package(OpenSSL REQUIRED)
|
||||
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX "${XNCore_PATH}" CACHE PATH "Install path prefix" FORCE)
|
||||
endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# 生成密钥对的可执行程序
|
||||
add_executable(XNSignatureKeygen keygen.cpp)
|
||||
target_link_libraries(XNSignatureKeygen PRIVATE OpenSSL::SSL OpenSSL::Crypto)
|
||||
|
||||
# 签名的可执行程序
|
||||
add_executable(XNSignatureSign sign.cpp)
|
||||
target_link_libraries(XNSignatureSign PRIVATE OpenSSL::SSL OpenSSL::Crypto)
|
||||
|
||||
# 验证签名的动态库
|
||||
add_library(XNSignatureVerify SHARED
|
||||
XNSignature_global.h
|
||||
XNSignatureVerify.h
|
||||
verify.cpp
|
||||
)
|
||||
|
||||
target_include_directories(XNSignatureVerify PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(XNSignatureVerify PRIVATE OpenSSL::SSL OpenSSL::Crypto)
|
||||
target_compile_definitions(XNSignatureVerify PRIVATE XNSIGNATURE_LIBRARY XNSIGNATURE_EXPORTS)
|
||||
|
||||
# 验证库测试程序
|
||||
add_executable(test_verify test_verify.cpp)
|
||||
target_link_libraries(test_verify PRIVATE XNSignatureVerify)
|
||||
target_compile_definitions(test_verify PRIVATE XNSIGNATURE_EXPORTS)
|
||||
|
||||
# 完整性检测测试程序
|
||||
add_executable(test_integrity test_integrity.cpp)
|
||||
target_link_libraries(test_integrity PRIVATE XNSignatureVerify)
|
||||
target_compile_definitions(test_integrity PRIVATE XNSIGNATURE_EXPORTS)
|
||||
|
||||
# 安装配置 - 只安装动态库
|
||||
install(TARGETS XNSignatureVerify
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
164
XNSignature/README.md
Normal file
164
XNSignature/README.md
Normal file
@ -0,0 +1,164 @@
|
||||
# XNSignature 数字签名工具集
|
||||
|
||||
这是一个基于 OpenSSL 的数字签名工具集,包含三个主要组件:
|
||||
|
||||
## 项目结构
|
||||
|
||||
- **XNSignatureKeygen**: 密钥生成工具(可执行程序)
|
||||
- **XNSignatureSign**: 文件签名工具(可执行程序)
|
||||
- **XNSignatureVerify**: 签名验证库(动态库)
|
||||
|
||||
## 编译和安装
|
||||
|
||||
### 依赖要求
|
||||
|
||||
- CMake 3.16+
|
||||
- OpenSSL 开发库
|
||||
- C++17 编译器
|
||||
|
||||
### 编译步骤
|
||||
|
||||
```bash
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
```
|
||||
|
||||
### 安装
|
||||
|
||||
```bash
|
||||
make install
|
||||
```
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 1. 生成密钥对
|
||||
|
||||
运行密钥生成工具,会在当前目录生成密钥文件:
|
||||
|
||||
```bash
|
||||
./XNSignatureKeygen
|
||||
```
|
||||
|
||||
这将生成:
|
||||
|
||||
- `private_key.pem` - 私钥文件
|
||||
- `public_key.pem` - 公钥文件
|
||||
|
||||
### 2. 为文件创建数字签名
|
||||
|
||||
有两种使用方式:
|
||||
|
||||
#### 方式一:签名所有文件
|
||||
|
||||
```bash
|
||||
./XNSignatureSign
|
||||
```
|
||||
|
||||
这将自动签名当前目录下的所有文件(除了密钥文件和已有的签名文件),每个文件会生成对应的 `.sig` 签名文件。
|
||||
|
||||
#### 方式二:签名指定文件
|
||||
|
||||
```bash
|
||||
./XNSignatureSign <文件路径>
|
||||
```
|
||||
|
||||
示例:
|
||||
|
||||
```bash
|
||||
./XNSignatureSign document.txt
|
||||
./XNSignatureSign important_file.pdf
|
||||
```
|
||||
|
||||
签名工具会使用当前目录下的 `private_key.pem` 私钥文件。
|
||||
|
||||
### 3. 验证数字签名
|
||||
|
||||
使用验证库验证文件签名:
|
||||
|
||||
#### C++ 程序中使用
|
||||
|
||||
```cpp
|
||||
#include "XNSignatureVerify.h"
|
||||
|
||||
// 验证签名
|
||||
int result = verifySignature("document.txt", "public_key.pem", "document.sig");
|
||||
if (result == 0) {
|
||||
std::cout << "签名验证成功!" << std::endl;
|
||||
} else if (result == -1) {
|
||||
std::cout << "签名验证失败!" << std::endl;
|
||||
} else {
|
||||
std::cout << "验证过程中发生错误!" << std::endl;
|
||||
}
|
||||
```
|
||||
|
||||
#### 测试验证库
|
||||
|
||||
```bash
|
||||
./test_verify
|
||||
```
|
||||
|
||||
## API 函数说明
|
||||
|
||||
### 验证库函数
|
||||
|
||||
#### `verifySignature`
|
||||
|
||||
```cpp
|
||||
int verifySignature(const char* filePath, const char* publicKeyPath, const char* signaturePath);
|
||||
```
|
||||
|
||||
- **功能**: 验证文件数字签名
|
||||
- **返回值**: 0=成功, -1=验证失败, -2=其他错误
|
||||
|
||||
## 技术特点
|
||||
|
||||
- 使用 RSA-2048 算法进行数字签名
|
||||
- 采用 SHA256 哈希算法
|
||||
- 支持 PEM 格式的密钥文件
|
||||
- 提供 C 语言接口,便于集成
|
||||
- 完整的错误处理和资源管理
|
||||
|
||||
## 安全说明
|
||||
|
||||
- 私钥文件应妥善保管,不要泄露给他人
|
||||
- 公钥文件可以公开分发
|
||||
- 签名文件用于验证文件完整性,防止篡改
|
||||
- 建议定期更换密钥对
|
||||
|
||||
## 示例工作流程
|
||||
|
||||
1. 生成密钥对:
|
||||
|
||||
```bash
|
||||
./xn_keygen
|
||||
```
|
||||
|
||||
2. 签名重要文件:
|
||||
|
||||
方式一:签名所有文件
|
||||
|
||||
```bash
|
||||
./XNSignatureSign
|
||||
```
|
||||
|
||||
方式二:签名指定文件
|
||||
|
||||
```bash
|
||||
./XNSignatureSign important_document.pdf
|
||||
```
|
||||
|
||||
3. 分发文件时包含:
|
||||
|
||||
- `important_document.pdf` (原始文件)
|
||||
- `important_document.sig` (签名文件)
|
||||
- `public_key.pem` (公钥文件)
|
||||
|
||||
4. 接收方验证文件完整性:
|
||||
```cpp
|
||||
int result = verifySignature("important_document.pdf", "public_key.pem", "important_document.sig");
|
||||
if (result == 0) {
|
||||
// 文件未被篡改,可以安全使用
|
||||
}
|
||||
```
|
25
XNSignature/XNSignatureVerify.h
Normal file
25
XNSignature/XNSignatureVerify.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef XNSIGNATUREVERIFY_H
|
||||
#define XNSIGNATUREVERIFY_H
|
||||
|
||||
#include "XNSignature_global.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief 验证文件数字签名
|
||||
* @param filePath 原始文件路径
|
||||
* @param publicKeyPath 公钥文件路径
|
||||
* @param signaturePath 签名文件路径
|
||||
* @return 0表示验证成功,-1表示验证失败,-2表示其他错误
|
||||
*/
|
||||
XNSIGNATURE_API int verifySignature(const char *filePath, const char *publicKeyPath,
|
||||
const char *signaturePath);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // XNSIGNATUREVERIFY_H
|
10
XNSignature/XNSignature_global.h
Normal file
10
XNSignature/XNSignature_global.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef XNSIGNATURE_GLOBAL_H
|
||||
#define XNSIGNATURE_GLOBAL_H
|
||||
|
||||
#ifdef XNSIGNATURE_EXPORTS
|
||||
# define XNSIGNATURE_API __attribute__((visibility("default")))
|
||||
#else
|
||||
# define XNSIGNATURE_API __attribute__((visibility("hidden")))
|
||||
#endif
|
||||
|
||||
#endif // XNSIGNATURE_GLOBAL_H
|
133
XNSignature/keygen.cpp
Normal file
133
XNSignature/keygen.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* @brief 生成RSA密钥对
|
||||
* @param privateKeyPath 私钥保存路径
|
||||
* @param publicKeyPath 公钥保存路径
|
||||
* @param keySize 密钥长度(默认2048位)
|
||||
* @return 0表示成功,-1表示失败
|
||||
*/
|
||||
int generateRSAKeyPair(const char *privateKeyPath, const char *publicKeyPath, int keySize = 2048)
|
||||
{
|
||||
if (!privateKeyPath || !publicKeyPath) {
|
||||
std::cerr << "错误:密钥路径不能为空" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 生成RSA密钥对
|
||||
EVP_PKEY *pkey = EVP_PKEY_new();
|
||||
if (!pkey) {
|
||||
std::cerr << "错误:无法创建密钥对象" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 创建RSA密钥生成上下文
|
||||
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr);
|
||||
if (!ctx) {
|
||||
std::cerr << "错误:无法创建密钥生成上下文" << std::endl;
|
||||
EVP_PKEY_free(pkey);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 初始化密钥生成
|
||||
if (EVP_PKEY_keygen_init(ctx) <= 0) {
|
||||
std::cerr << "错误:无法初始化密钥生成" << std::endl;
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
EVP_PKEY_free(pkey);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 设置密钥长度
|
||||
if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, keySize) <= 0) {
|
||||
std::cerr << "错误:无法设置密钥长度" << std::endl;
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
EVP_PKEY_free(pkey);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 生成密钥对
|
||||
if (EVP_PKEY_keygen(ctx, &pkey) <= 0) {
|
||||
std::cerr << "错误:密钥生成失败" << std::endl;
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
EVP_PKEY_free(pkey);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 保存私钥到文件
|
||||
FILE *privateKeyFile = fopen(privateKeyPath, "w");
|
||||
if (!privateKeyFile) {
|
||||
std::cerr << "错误:无法创建私钥文件" << std::endl;
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
EVP_PKEY_free(pkey);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (PEM_write_PrivateKey(privateKeyFile, pkey, nullptr, nullptr, 0, nullptr, nullptr) != 1) {
|
||||
std::cerr << "错误:无法写入私钥" << std::endl;
|
||||
fclose(privateKeyFile);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
EVP_PKEY_free(pkey);
|
||||
return -1;
|
||||
}
|
||||
fclose(privateKeyFile);
|
||||
|
||||
// 保存公钥到文件
|
||||
FILE *publicKeyFile = fopen(publicKeyPath, "w");
|
||||
if (!publicKeyFile) {
|
||||
std::cerr << "错误:无法创建公钥文件" << std::endl;
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
EVP_PKEY_free(pkey);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (PEM_write_PUBKEY(publicKeyFile, pkey) != 1) {
|
||||
std::cerr << "错误:无法写入公钥" << std::endl;
|
||||
fclose(publicKeyFile);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
EVP_PKEY_free(pkey);
|
||||
return -1;
|
||||
}
|
||||
fclose(publicKeyFile);
|
||||
|
||||
// 清理资源
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
EVP_PKEY_free(pkey);
|
||||
|
||||
std::cout << "RSA密钥对生成成功!" << std::endl;
|
||||
std::cout << "私钥保存到: " << privateKeyPath << std::endl;
|
||||
std::cout << "公钥保存到: " << publicKeyPath << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 主函数
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// 固定文件名,生成在程序所在目录
|
||||
const char *privateKeyPath = "private_key.pem";
|
||||
const char *publicKeyPath = "public_key.pem";
|
||||
int keySize = 2048; // 默认密钥长度
|
||||
|
||||
std::cout << "=== XNSignature 密钥生成工具 ===" << std::endl;
|
||||
std::cout << "私钥文件: " << privateKeyPath << std::endl;
|
||||
std::cout << "公钥文件: " << publicKeyPath << std::endl;
|
||||
std::cout << "密钥长度: " << keySize << " 位" << std::endl;
|
||||
std::cout << "正在生成密钥对..." << std::endl;
|
||||
|
||||
int result = generateRSAKeyPair(privateKeyPath, publicKeyPath, keySize);
|
||||
|
||||
if (result == 0) {
|
||||
std::cout << "密钥生成完成!" << std::endl;
|
||||
return 0;
|
||||
} else {
|
||||
std::cerr << "密钥生成失败!" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
253
XNSignature/sign.cpp
Normal file
253
XNSignature/sign.cpp
Normal file
@ -0,0 +1,253 @@
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* @brief 计算文件的SHA256哈希值
|
||||
* @param filePath 文件路径
|
||||
* @param hash 输出哈希值(32字节)
|
||||
* @return 0表示成功,-1表示失败
|
||||
*/
|
||||
int calculateFileHash(const char *filePath, unsigned char *hash)
|
||||
{
|
||||
if (!filePath || !hash) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::ifstream file(filePath, std::ios::binary);
|
||||
if (!file.is_open()) {
|
||||
std::cerr << "错误:无法打开文件 " << filePath << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
SHA256_CTX sha256;
|
||||
SHA256_Init(&sha256);
|
||||
|
||||
char buffer[4096];
|
||||
while (file) {
|
||||
file.read(buffer, sizeof(buffer));
|
||||
std::streamsize bytesRead = file.gcount();
|
||||
if (bytesRead > 0) {
|
||||
SHA256_Update(&sha256, buffer, bytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
SHA256_Final(hash, &sha256);
|
||||
file.close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 为指定文件创建数字签名
|
||||
* @param filePath 要签名的文件路径
|
||||
* @param privateKeyPath 私钥文件路径
|
||||
* @param signaturePath 签名文件保存路径
|
||||
* @return 0表示成功,-1表示失败
|
||||
*/
|
||||
int signFile(const char *filePath, const char *privateKeyPath, const char *signaturePath)
|
||||
{
|
||||
if (!filePath || !privateKeyPath || !signaturePath) {
|
||||
std::cerr << "错误:参数不能为空" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 加载私钥
|
||||
FILE *privateKeyFile = fopen(privateKeyPath, "r");
|
||||
if (!privateKeyFile) {
|
||||
std::cerr << "错误:无法打开私钥文件" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
EVP_PKEY *privateKey = PEM_read_PrivateKey(privateKeyFile, nullptr, nullptr, nullptr);
|
||||
fclose(privateKeyFile);
|
||||
|
||||
if (!privateKey) {
|
||||
std::cerr << "错误:无法读取私钥" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 计算文件哈希
|
||||
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||||
if (calculateFileHash(filePath, hash) != 0) {
|
||||
EVP_PKEY_free(privateKey);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 创建签名上下文
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
|
||||
if (!ctx) {
|
||||
std::cerr << "错误:无法创建签名上下文" << std::endl;
|
||||
EVP_PKEY_free(privateKey);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 初始化签名
|
||||
if (EVP_DigestSignInit(ctx, nullptr, EVP_sha256(), nullptr, privateKey) <= 0) {
|
||||
std::cerr << "错误:无法初始化签名" << std::endl;
|
||||
EVP_MD_CTX_free(ctx);
|
||||
EVP_PKEY_free(privateKey);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 计算签名长度
|
||||
size_t signatureLen;
|
||||
if (EVP_DigestSign(ctx, nullptr, &signatureLen, hash, SHA256_DIGEST_LENGTH) <= 0) {
|
||||
std::cerr << "错误:无法计算签名长度" << std::endl;
|
||||
EVP_MD_CTX_free(ctx);
|
||||
EVP_PKEY_free(privateKey);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 分配签名缓冲区
|
||||
std::vector<unsigned char> signature(signatureLen);
|
||||
|
||||
// 执行签名
|
||||
if (EVP_DigestSign(ctx, signature.data(), &signatureLen, hash, SHA256_DIGEST_LENGTH) <= 0) {
|
||||
std::cerr << "错误:签名失败" << std::endl;
|
||||
EVP_MD_CTX_free(ctx);
|
||||
EVP_PKEY_free(privateKey);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 保存签名到文件
|
||||
std::ofstream signatureFile(signaturePath, std::ios::binary);
|
||||
if (!signatureFile.is_open()) {
|
||||
std::cerr << "错误:无法创建签名文件" << std::endl;
|
||||
EVP_MD_CTX_free(ctx);
|
||||
EVP_PKEY_free(privateKey);
|
||||
return -1;
|
||||
}
|
||||
|
||||
signatureFile.write(reinterpret_cast<const char *>(signature.data()), signatureLen);
|
||||
signatureFile.close();
|
||||
|
||||
// 清理资源
|
||||
EVP_MD_CTX_free(ctx);
|
||||
EVP_PKEY_free(privateKey);
|
||||
|
||||
std::cout << "文件签名成功!" << std::endl;
|
||||
std::cout << "签名文件保存到: " << signaturePath << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* @brief 获取目录下所有文件
|
||||
* @param directory 目录路径
|
||||
* @return 文件路径列表
|
||||
*/
|
||||
std::vector<std::string> getFilesInDirectory(const std::string &directory)
|
||||
{
|
||||
std::vector<std::string> files;
|
||||
|
||||
try {
|
||||
for (const auto &entry : std::filesystem::directory_iterator(directory)) {
|
||||
if (entry.is_regular_file()) {
|
||||
// 跳过密钥文件和签名文件
|
||||
std::string filename = entry.path().filename().string();
|
||||
if (filename != "private_key.pem" && filename != "public_key.pem"
|
||||
&& filename.find(".sig") == std::string::npos) {
|
||||
files.push_back(entry.path().string());
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const std::filesystem::filesystem_error &e) {
|
||||
std::cerr << "错误:无法读取目录 " << directory << ": " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 显示使用说明
|
||||
*/
|
||||
void showUsage(const char *programName)
|
||||
{
|
||||
std::cout << "用法: " << programName << " [文件路径]" << std::endl;
|
||||
std::cout << "参数说明:" << std::endl;
|
||||
std::cout << " 文件路径: 要签名的文件路径(可选)" << std::endl;
|
||||
std::cout << " 如果不提供参数,将签名当前目录下的所有文件" << std::endl;
|
||||
std::cout << "示例:" << std::endl;
|
||||
std::cout << " " << programName << " # 签名所有文件" << std::endl;
|
||||
std::cout << " " << programName << " document.txt # 签名指定文件" << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 主函数
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const char *privateKeyPath = "private_key.pem";
|
||||
std::vector<std::string> filesToSign;
|
||||
|
||||
std::cout << "=== XNSignature 文件签名工具 ===" << std::endl;
|
||||
|
||||
if (argc == 1) {
|
||||
// 没有参数,签名目录下所有文件
|
||||
std::cout << "未指定文件,将签名当前目录下的所有文件..." << std::endl;
|
||||
filesToSign = getFilesInDirectory(".");
|
||||
|
||||
if (filesToSign.empty()) {
|
||||
std::cout << "当前目录下没有找到可签名的文件" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::cout << "找到 " << filesToSign.size() << " 个文件:" << std::endl;
|
||||
for (const auto &file : filesToSign) {
|
||||
std::cout << " - " << file << std::endl;
|
||||
}
|
||||
} else if (argc == 2) {
|
||||
// 指定了单个文件
|
||||
filesToSign.push_back(argv[1]);
|
||||
std::cout << "将签名指定文件: " << argv[1] << std::endl;
|
||||
} else {
|
||||
std::cerr << "错误:参数数量不正确" << std::endl;
|
||||
showUsage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::cout << "私钥文件: " << privateKeyPath << std::endl;
|
||||
std::cout << "正在签名文件..." << std::endl;
|
||||
|
||||
int successCount = 0;
|
||||
int totalCount = filesToSign.size();
|
||||
|
||||
for (const auto &filePath : filesToSign) {
|
||||
// 生成签名文件路径
|
||||
std::string signaturePath = filePath + ".sig";
|
||||
|
||||
std::cout << "\n正在签名: " << filePath << std::endl;
|
||||
std::cout << "签名文件: " << signaturePath << std::endl;
|
||||
|
||||
int result = signFile(filePath.c_str(), privateKeyPath, signaturePath.c_str());
|
||||
|
||||
if (result == 0) {
|
||||
std::cout << "✓ 签名成功" << std::endl;
|
||||
successCount++;
|
||||
} else {
|
||||
std::cout << "✗ 签名失败" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "\n=== 签名完成 ===" << std::endl;
|
||||
std::cout << "成功签名: " << successCount << "/" << totalCount << " 个文件" << std::endl;
|
||||
|
||||
if (successCount == totalCount) {
|
||||
std::cout << "所有文件签名完成!" << std::endl;
|
||||
return 0;
|
||||
} else {
|
||||
std::cerr << "部分文件签名失败!" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
179
XNSignature/test_integrity.cpp
Normal file
179
XNSignature/test_integrity.cpp
Normal file
@ -0,0 +1,179 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include "XNSignatureVerify.h"
|
||||
|
||||
/**
|
||||
* @brief 测试文件完整性检测
|
||||
* 验证签名是否能检测到文件的任何微小变化
|
||||
*/
|
||||
int main()
|
||||
{
|
||||
std::cout << "=== 文件完整性检测测试 ===" << std::endl;
|
||||
|
||||
// 创建测试文件
|
||||
std::string testFile = "test_integrity.txt";
|
||||
std::ofstream file(testFile);
|
||||
if (!file.is_open()) {
|
||||
std::cerr << "错误:无法创建测试文件" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
file << "这是一个测试文件,用于验证数字签名的完整性检测功能。" << std::endl;
|
||||
file << "任何微小的修改都应该被检测到。" << std::endl;
|
||||
file.close();
|
||||
|
||||
std::cout << "1. 创建测试文件: " << testFile << std::endl;
|
||||
|
||||
// 生成密钥对
|
||||
std::cout << "2. 生成密钥对..." << std::endl;
|
||||
system("./XNSignatureKeygen");
|
||||
|
||||
// 对文件进行签名
|
||||
std::cout << "3. 对文件进行签名..." << std::endl;
|
||||
system(("./XNSignatureSign " + testFile).c_str());
|
||||
|
||||
// 验证原始签名
|
||||
std::cout << "4. 验证原始签名..." << std::endl;
|
||||
int result1 = verifySignature(testFile.c_str(), "public_key.pem", (testFile + ".sig").c_str());
|
||||
|
||||
if (result1 == 0) {
|
||||
std::cout << "✓ 原始文件签名验证成功" << std::endl;
|
||||
} else {
|
||||
std::cout << "✗ 原始文件签名验证失败" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 测试1:修改文件内容(添加一个字符)
|
||||
std::cout << "\n5. 测试1:修改文件内容(添加字符)..." << std::endl;
|
||||
std::ofstream modFile1(testFile, std::ios::app);
|
||||
modFile1 << "X"; // 添加一个字符
|
||||
modFile1.close();
|
||||
|
||||
int result2 = verifySignature(testFile.c_str(), "public_key.pem", (testFile + ".sig").c_str());
|
||||
|
||||
if (result2 != 0) {
|
||||
std::cout << "✓ 检测到文件内容修改" << std::endl;
|
||||
} else {
|
||||
std::cout << "✗ 未能检测到文件内容修改" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 恢复文件内容
|
||||
std::ofstream restoreFile1(testFile);
|
||||
restoreFile1 << "这是一个测试文件,用于验证数字签名的完整性检测功能。" << std::endl;
|
||||
restoreFile1 << "任何微小的修改都应该被检测到。" << std::endl;
|
||||
restoreFile1.close();
|
||||
|
||||
// 重新签名
|
||||
system(("./XNSignatureSign " + testFile).c_str());
|
||||
|
||||
// 测试2:修改文件内容(删除一个字符)
|
||||
std::cout << "\n6. 测试2:修改文件内容(删除字符)..." << std::endl;
|
||||
std::string content;
|
||||
std::ifstream readFile(testFile);
|
||||
std::getline(readFile, content);
|
||||
readFile.close();
|
||||
|
||||
if (content.length() > 0) {
|
||||
content = content.substr(0, content.length() - 1); // 删除最后一个字符
|
||||
std::ofstream modFile2(testFile);
|
||||
modFile2 << content << std::endl;
|
||||
modFile2.close();
|
||||
|
||||
int result3 =
|
||||
verifySignature(testFile.c_str(), "public_key.pem", (testFile + ".sig").c_str());
|
||||
|
||||
if (result3 != 0) {
|
||||
std::cout << "✓ 检测到文件内容修改" << std::endl;
|
||||
} else {
|
||||
std::cout << "✗ 未能检测到文件内容修改" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// 测试3:修改文件内容(替换一个字符)
|
||||
std::cout << "\n7. 测试3:修改文件内容(替换字符)..." << std::endl;
|
||||
std::ifstream readFile2(testFile);
|
||||
std::getline(readFile2, content);
|
||||
readFile2.close();
|
||||
|
||||
if (content.length() > 5) {
|
||||
content[5] = 'X'; // 替换第6个字符
|
||||
std::ofstream modFile3(testFile);
|
||||
modFile3 << content << std::endl;
|
||||
modFile3.close();
|
||||
|
||||
int result4 =
|
||||
verifySignature(testFile.c_str(), "public_key.pem", (testFile + ".sig").c_str());
|
||||
|
||||
if (result4 != 0) {
|
||||
std::cout << "✓ 检测到文件内容修改" << std::endl;
|
||||
} else {
|
||||
std::cout << "✗ 未能检测到文件内容修改" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// 测试4:修改文件内容(添加空格)
|
||||
std::cout << "\n8. 测试4:修改文件内容(添加空格)..." << std::endl;
|
||||
std::ifstream readFile3(testFile);
|
||||
std::getline(readFile3, content);
|
||||
readFile3.close();
|
||||
|
||||
content.insert(10, " "); // 在第10个位置插入空格
|
||||
std::ofstream modFile4(testFile);
|
||||
modFile4 << content << std::endl;
|
||||
modFile4.close();
|
||||
|
||||
int result5 = verifySignature(testFile.c_str(), "public_key.pem", (testFile + ".sig").c_str());
|
||||
|
||||
if (result5 != 0) {
|
||||
std::cout << "✓ 检测到文件内容修改" << std::endl;
|
||||
} else {
|
||||
std::cout << "✗ 未能检测到文件内容修改" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 测试5:修改文件内容(改变换行符)
|
||||
std::cout << "\n9. 测试5:修改文件内容(改变换行符)..." << std::endl;
|
||||
std::ofstream modFile5(testFile);
|
||||
modFile5 << "这是一个测试文件,用于验证数字签名的完整性检测功能。\r\n"; // 使用Windows换行符
|
||||
modFile5 << "任何微小的修改都应该被检测到。\r\n";
|
||||
modFile5.close();
|
||||
|
||||
int result6 = verifySignature(testFile.c_str(), "public_key.pem", (testFile + ".sig").c_str());
|
||||
|
||||
if (result6 != 0) {
|
||||
std::cout << "✓ 检测到文件内容修改" << std::endl;
|
||||
} else {
|
||||
std::cout << "✗ 未能检测到文件内容修改" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 测试6:修改文件内容(添加不可见字符)
|
||||
std::cout << "\n10. 测试6:修改文件内容(添加不可见字符)..." << std::endl;
|
||||
std::ofstream modFile6(testFile);
|
||||
modFile6 << "这是一个测试文件,用于验证数字签名的完整性检测功能。" << std::endl;
|
||||
modFile6 << "任何微小的修改都应该被检测到。" << (char)0x00 << std::endl; // 添加null字符
|
||||
modFile6.close();
|
||||
|
||||
int result7 = verifySignature(testFile.c_str(), "public_key.pem", (testFile + ".sig").c_str());
|
||||
|
||||
if (result7 != 0) {
|
||||
std::cout << "✓ 检测到文件内容修改" << std::endl;
|
||||
} else {
|
||||
std::cout << "✗ 未能检测到文件内容修改" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::cout << "\n=== 测试完成 ===" << std::endl;
|
||||
std::cout << "✓ 所有完整性检测测试通过!" << std::endl;
|
||||
std::cout << "✓ 数字签名能够检测到文件的任何微小变化" << std::endl;
|
||||
|
||||
// 清理测试文件
|
||||
system(("rm -f " + testFile + " " + testFile + ".sig").c_str());
|
||||
|
||||
return 0;
|
||||
}
|
51
XNSignature/test_verify.cpp
Normal file
51
XNSignature/test_verify.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
#include "XNSignatureVerify.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
/**
|
||||
* @brief 创建测试文件
|
||||
* @param filename 文件名
|
||||
* @param content 文件内容
|
||||
*/
|
||||
void createTestFile(const char *filename, const char *content)
|
||||
{
|
||||
std::ofstream file(filename);
|
||||
if (file.is_open()) {
|
||||
file << content;
|
||||
file.close();
|
||||
std::cout << "测试文件创建成功: " << filename << std::endl;
|
||||
} else {
|
||||
std::cerr << "无法创建测试文件: " << filename << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 主测试函数
|
||||
*/
|
||||
int main()
|
||||
{
|
||||
std::cout << "=== XNSignature 验证库测试程序 ===" << std::endl;
|
||||
|
||||
// 测试文件路径
|
||||
const char *testFile = "test_document.txt";
|
||||
const char *publicKeyFile = "public_key.pem";
|
||||
const char *signatureFile = "test_document.txt.sig";
|
||||
|
||||
// 创建测试文件
|
||||
//createTestFile(testFile, "这是一个测试文档,用于验证数字签名功能。\n包含一些重要信息。");
|
||||
|
||||
std::cout << "\n1. 验证数字签名..." << std::endl;
|
||||
int verifyResult = verifySignature(testFile, publicKeyFile, signatureFile);
|
||||
if (verifyResult == 0) {
|
||||
std::cout << "签名验证成功!" << std::endl;
|
||||
} else if (verifyResult == -1) {
|
||||
std::cout << "签名验证失败!" << std::endl;
|
||||
} else {
|
||||
std::cout << "验证过程中发生错误!" << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "\n2. 验证完成" << std::endl;
|
||||
|
||||
std::cout << "\n=== 测试完成 ===" << std::endl;
|
||||
return 0;
|
||||
}
|
303
XNSignature/verify.cpp
Normal file
303
XNSignature/verify.cpp
Normal file
@ -0,0 +1,303 @@
|
||||
#include "XNSignature_global.h"
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief 计算文件的SHA256哈希值
|
||||
* @param filePath 文件路径
|
||||
* @param hash 输出哈希值(32字节)
|
||||
* @return 0表示成功,-1表示失败
|
||||
*/
|
||||
int calculateFileHash(const char *filePath, unsigned char *hash)
|
||||
{
|
||||
if (!filePath || !hash) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::ifstream file(filePath, std::ios::binary);
|
||||
if (!file.is_open()) {
|
||||
std::cerr << "错误:无法打开文件 " << filePath << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
SHA256_CTX sha256;
|
||||
SHA256_Init(&sha256);
|
||||
|
||||
char buffer[4096];
|
||||
while (file) {
|
||||
file.read(buffer, sizeof(buffer));
|
||||
std::streamsize bytesRead = file.gcount();
|
||||
if (bytesRead > 0) {
|
||||
SHA256_Update(&sha256, buffer, bytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
SHA256_Final(hash, &sha256);
|
||||
file.close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 验证文件数字签名
|
||||
* @param filePath 原始文件路径
|
||||
* @param publicKeyPath 公钥文件路径
|
||||
* @param signaturePath 签名文件路径
|
||||
* @return 0表示验证成功,-1表示验证失败,-2表示其他错误
|
||||
*/
|
||||
XNSIGNATURE_API int verifySignature(const char *filePath, const char *publicKeyPath,
|
||||
const char *signaturePath)
|
||||
{
|
||||
if (!filePath || !publicKeyPath || !signaturePath) {
|
||||
std::cerr << "错误:参数不能为空" << std::endl;
|
||||
return -2;
|
||||
}
|
||||
|
||||
// 加载公钥
|
||||
FILE *publicKeyFile = fopen(publicKeyPath, "r");
|
||||
if (!publicKeyFile) {
|
||||
std::cerr << "错误:无法打开公钥文件" << std::endl;
|
||||
return -2;
|
||||
}
|
||||
|
||||
EVP_PKEY *publicKey = PEM_read_PUBKEY(publicKeyFile, nullptr, nullptr, nullptr);
|
||||
fclose(publicKeyFile);
|
||||
|
||||
if (!publicKey) {
|
||||
std::cerr << "错误:无法读取公钥" << std::endl;
|
||||
return -2;
|
||||
}
|
||||
|
||||
// 计算文件哈希
|
||||
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||||
if (calculateFileHash(filePath, hash) != 0) {
|
||||
EVP_PKEY_free(publicKey);
|
||||
return -2;
|
||||
}
|
||||
|
||||
// 读取签名文件
|
||||
std::ifstream signatureFile(signaturePath, std::ios::binary);
|
||||
if (!signatureFile.is_open()) {
|
||||
std::cerr << "错误:无法打开签名文件" << std::endl;
|
||||
EVP_PKEY_free(publicKey);
|
||||
return -2;
|
||||
}
|
||||
|
||||
signatureFile.seekg(0, std::ios::end);
|
||||
size_t signatureSize = signatureFile.tellg();
|
||||
signatureFile.seekg(0, std::ios::beg);
|
||||
|
||||
std::vector<unsigned char> signature(signatureSize);
|
||||
signatureFile.read(reinterpret_cast<char *>(signature.data()), signatureSize);
|
||||
signatureFile.close();
|
||||
|
||||
// 创建验证上下文
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
|
||||
if (!ctx) {
|
||||
std::cerr << "错误:无法创建验证上下文" << std::endl;
|
||||
EVP_PKEY_free(publicKey);
|
||||
return -2;
|
||||
}
|
||||
|
||||
// 初始化验证
|
||||
if (EVP_DigestVerifyInit(ctx, nullptr, EVP_sha256(), nullptr, publicKey) <= 0) {
|
||||
std::cerr << "错误:无法初始化验证" << std::endl;
|
||||
EVP_MD_CTX_free(ctx);
|
||||
EVP_PKEY_free(publicKey);
|
||||
return -2;
|
||||
}
|
||||
|
||||
// 执行验证
|
||||
int result =
|
||||
EVP_DigestVerify(ctx, signature.data(), signature.size(), hash, SHA256_DIGEST_LENGTH);
|
||||
|
||||
// 清理资源
|
||||
EVP_MD_CTX_free(ctx);
|
||||
EVP_PKEY_free(publicKey);
|
||||
|
||||
if (result == 1) {
|
||||
std::cout << "签名验证成功!文件完整性确认。" << std::endl;
|
||||
return 0;
|
||||
} else if (result == 0) {
|
||||
std::cout << "签名验证失败!文件可能已被篡改。" << std::endl;
|
||||
return -1;
|
||||
} else {
|
||||
std::cerr << "错误:验证过程中发生错误" << std::endl;
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 显示文件哈希值
|
||||
* @param filePath 文件路径
|
||||
* @return 0表示成功,-1表示失败
|
||||
*/
|
||||
int showFileHash(const char *filePath)
|
||||
{
|
||||
if (!filePath) {
|
||||
std::cerr << "错误:文件路径不能为空" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||||
if (calculateFileHash(filePath, hash) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::cout << "文件 " << filePath << " 的SHA256哈希值:" << std::endl;
|
||||
for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
|
||||
printf("%02x", hash[i]);
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取文件哈希值的十六进制字符串
|
||||
* @param filePath 文件路径
|
||||
* @param hashString 输出哈希字符串缓冲区(至少65字节)
|
||||
* @return 0表示成功,-1表示失败
|
||||
*/
|
||||
int getFileHashString(const char *filePath, char *hashString)
|
||||
{
|
||||
if (!filePath || !hashString) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||||
if (calculateFileHash(filePath, hash) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
|
||||
sprintf(hashString + i * 2, "%02x", hash[i]);
|
||||
}
|
||||
hashString[64] = '\0'; // 确保字符串结束
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 验证签名并返回详细结果
|
||||
* @param filePath 原始文件路径
|
||||
* @param publicKeyPath 公钥文件路径
|
||||
* @param signaturePath 签名文件路径
|
||||
* @param resultMessage 结果消息缓冲区
|
||||
* @param messageSize 缓冲区大小
|
||||
* @return 0表示验证成功,-1表示验证失败,-2表示其他错误
|
||||
*/
|
||||
int verifySignatureWithMessage(const char *filePath, const char *publicKeyPath,
|
||||
const char *signaturePath, char *resultMessage, int messageSize)
|
||||
{
|
||||
if (!filePath || !publicKeyPath || !signaturePath || !resultMessage) {
|
||||
if (resultMessage && messageSize > 0) {
|
||||
snprintf(resultMessage, messageSize, "错误:参数不能为空");
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
// 加载公钥
|
||||
FILE *publicKeyFile = fopen(publicKeyPath, "r");
|
||||
if (!publicKeyFile) {
|
||||
if (messageSize > 0) {
|
||||
snprintf(resultMessage, messageSize, "错误:无法打开公钥文件");
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
EVP_PKEY *publicKey = PEM_read_PUBKEY(publicKeyFile, nullptr, nullptr, nullptr);
|
||||
fclose(publicKeyFile);
|
||||
|
||||
if (!publicKey) {
|
||||
if (messageSize > 0) {
|
||||
snprintf(resultMessage, messageSize, "错误:无法读取公钥");
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
// 计算文件哈希
|
||||
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||||
if (calculateFileHash(filePath, hash) != 0) {
|
||||
EVP_PKEY_free(publicKey);
|
||||
if (messageSize > 0) {
|
||||
snprintf(resultMessage, messageSize, "错误:无法计算文件哈希");
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
// 读取签名文件
|
||||
std::ifstream signatureFile(signaturePath, std::ios::binary);
|
||||
if (!signatureFile.is_open()) {
|
||||
EVP_PKEY_free(publicKey);
|
||||
if (messageSize > 0) {
|
||||
snprintf(resultMessage, messageSize, "错误:无法打开签名文件");
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
signatureFile.seekg(0, std::ios::end);
|
||||
size_t signatureSize = signatureFile.tellg();
|
||||
signatureFile.seekg(0, std::ios::beg);
|
||||
|
||||
std::vector<unsigned char> signature(signatureSize);
|
||||
signatureFile.read(reinterpret_cast<char *>(signature.data()), signatureSize);
|
||||
signatureFile.close();
|
||||
|
||||
// 创建验证上下文
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
|
||||
if (!ctx) {
|
||||
EVP_PKEY_free(publicKey);
|
||||
if (messageSize > 0) {
|
||||
snprintf(resultMessage, messageSize, "错误:无法创建验证上下文");
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
// 初始化验证
|
||||
if (EVP_DigestVerifyInit(ctx, nullptr, EVP_sha256(), nullptr, publicKey) <= 0) {
|
||||
EVP_MD_CTX_free(ctx);
|
||||
EVP_PKEY_free(publicKey);
|
||||
if (messageSize > 0) {
|
||||
snprintf(resultMessage, messageSize, "错误:无法初始化验证");
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
// 执行验证
|
||||
int result =
|
||||
EVP_DigestVerify(ctx, signature.data(), signature.size(), hash, SHA256_DIGEST_LENGTH);
|
||||
|
||||
// 清理资源
|
||||
EVP_MD_CTX_free(ctx);
|
||||
EVP_PKEY_free(publicKey);
|
||||
|
||||
if (result == 1) {
|
||||
if (messageSize > 0) {
|
||||
snprintf(resultMessage, messageSize, "签名验证成功!文件完整性确认。");
|
||||
}
|
||||
return 0;
|
||||
} else if (result == 0) {
|
||||
if (messageSize > 0) {
|
||||
snprintf(resultMessage, messageSize, "签名验证失败!文件可能已被篡改。");
|
||||
}
|
||||
return -1;
|
||||
} else {
|
||||
if (messageSize > 0) {
|
||||
snprintf(resultMessage, messageSize, "错误:验证过程中发生错误");
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
} // extern "C"
|
28
private_key.pem
Normal file
28
private_key.pem
Normal file
@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDF2ZjCOq3Yl3v4
|
||||
9bg3+qIpAAt4R3iPpGoiJcybzNhhhBJ7dJKsS45liFQqoVxhf0rASjTlJ6ImbqiI
|
||||
cnD8APAfpNyfdeg0gKt94x2SkJXU6kAer1aNq55i3DLcRmAGHuIXHSM5jxrh+lBQ
|
||||
v4p4gP2p4BhT4Fds8Mg6QZUi7axoN93B8xbayFHqRo0C2jroyF9kxKpwZB8302SG
|
||||
ax1dqEJa66WimIzST3ksyvXlMzd+oC844i9P5SzyXw6ecZgNhY/Hoa9rcMgstrpm
|
||||
9RewtQTnX2KeUp0ggtizMcIud+zyFA8+s+TwVrzm/Q9VV1JsE5EKxDSv103R0EUY
|
||||
n/IYLyMVAgMBAAECggEBAKl1CgWxxJyygphlvXcU0DdVtn06meRN6il9PpZjCSHc
|
||||
wQfEfKvduwTzk0NAGaPYJuozpMJxA8zvEqJrgqIVG5W+2sgpcM0nN7sG/5k9BVfr
|
||||
myes/fExgOMjvtwz2qLjaLprVnRCQcAzaP8AT1WPBbSuH6gXikngoV5kNZxI/VX0
|
||||
oYniHmGUlfOC2LKYXvSpHEmXhEyuZFDLxNqEpUPG2xHot7HUYklJKR4qxhD44CZJ
|
||||
UvOs5AeXxXlKVUpY0Ue+DGbd8kzNyVD+MChRKCDe+pwdIMP1u5yOwNNLqkveszOh
|
||||
9RH85l07cFrB68+Qycx+HqhzkNgjafqKZt08PAR6PzECgYEA7SzL3pOtfVUMwPNd
|
||||
6o1I8dfsSM7PxSWswUFkGF9ULijX4TbsQ3kli6Y3ZZZ4I1g4rEv3LKF1KB98Pv2T
|
||||
iKID1scEke4cYy8Q69wvXgektPgEf2JDdOOm7mFADAvAh4oIvjHSDXaFeskqnhhZ
|
||||
Vc3K64/7NNfd7NwT+dk69uNgVQMCgYEA1Y2/i5f2Es7xLAK1+NeoSYuDsKhfK3bn
|
||||
sWEKmJflIchvQ/GcUthawKuACv2u59xLtDHI8+Jky3ISobVYKREP+otWv2rndSQk
|
||||
XpfmsBLgIrcmgkBaZF+ebln8qwclqMjMW5hItfRKb/f57RTM+wsoGvNzWAxrtuR1
|
||||
O27PtrOe8AcCgYEA5x/FWBR/d2h/MjS3K9Ac6phpSRZIwK0TKYzItzuGtCjXH0C/
|
||||
go03OlxzFYtJbeAV8klhCNwaaEwubs/7iqWfqhhtaqwoe7ss+Tur6Sz3o+chsuUW
|
||||
KX2Dej/JAzQcnbi1BmtUcAw0zU/mOQQvYn9WJLI9seQ+/wgEa3D2lgtEH/MCgYEA
|
||||
hXPmfprBOTG/fwxWoaJLVWJtMmmVx7ivw6ZsE73gf8Mc3S3QzejMldjW1IeB1P1T
|
||||
BdGSze3tpUGtKQcFh+xUuvJ2jHqHGCo03DQ7Ak9ZZ/hihUUn98/VVwq/HjYCL78E
|
||||
Dj1VOvflyKEDu0ejbUKklmsK6rwgWBPeuvxdq8QGD+MCgYEAjXiRR7Jo+zKPZFmC
|
||||
P7G4YURBxAXNAneHTS6NXrXqf8l6ST1yPMfy+AoBtW6IkwQuob8e0aR7WiAtK427
|
||||
OQicnMap9/oDZ+tm2po7O3FQ7EJKiPYdltuCS/H4rYHm70oMiuMvWb5tzlYSbk4Z
|
||||
2LZ2Omi+NQyZiuHUWhnm8nQaQmc=
|
||||
-----END PRIVATE KEY-----
|
Loading…
x
Reference in New Issue
Block a user