mirror of
https://github.com/QuasarApp/Heart.git
synced 2025-04-27 02:04:38 +00:00
big changes to cheat card app
This commit is contained in:
parent
7bea1e32c5
commit
332acbdf7b
@ -1,878 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="218.722mm" height="114.653mm"
|
||||
viewBox="0 0 620 325"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" baseProfile="tiny">
|
||||
<title>Qt SVG Document</title>
|
||||
<desc>Generated with Qt</desc>
|
||||
<defs>
|
||||
<linearGradient gradientUnits="objectBoundingBox" x1="0" y1="0" x2="0" y2="1" id="gradient1">
|
||||
<stop offset="0" stop-color="#ebfdff" stop-opacity="1" />
|
||||
<stop offset="1" stop-color="#bfe4e8" stop-opacity="1" />
|
||||
</linearGradient>
|
||||
<linearGradient gradientUnits="objectBoundingBox" x1="0" y1="0" x2="0" y2="1" id="gradient2">
|
||||
<stop offset="0" stop-color="#ebfdff" stop-opacity="1" />
|
||||
<stop offset="1" stop-color="#bfe4e8" stop-opacity="1" />
|
||||
</linearGradient>
|
||||
<linearGradient gradientUnits="objectBoundingBox" x1="0" y1="0" x2="0" y2="1" id="gradient3">
|
||||
<stop offset="0" stop-color="#ebfdff" stop-opacity="1" />
|
||||
<stop offset="1" stop-color="#bfe4e8" stop-opacity="1" />
|
||||
</linearGradient>
|
||||
<linearGradient gradientUnits="objectBoundingBox" x1="0" y1="0" x2="0" y2="1" id="gradient4">
|
||||
<stop offset="0" stop-color="#ebfdff" stop-opacity="1" />
|
||||
<stop offset="1" stop-color="#bfe4e8" stop-opacity="1" />
|
||||
</linearGradient>
|
||||
<linearGradient gradientUnits="objectBoundingBox" x1="0" y1="0" x2="0" y2="1" id="gradient5">
|
||||
<stop offset="0" stop-color="#ebfdff" stop-opacity="1" />
|
||||
<stop offset="1" stop-color="#bfe4e8" stop-opacity="1" />
|
||||
</linearGradient>
|
||||
<linearGradient gradientUnits="objectBoundingBox" x1="0" y1="0" x2="0" y2="1" id="gradient6">
|
||||
<stop offset="0" stop-color="#ebfdff" stop-opacity="1" />
|
||||
<stop offset="1" stop-color="#bfe4e8" stop-opacity="1" />
|
||||
</linearGradient>
|
||||
<linearGradient gradientUnits="objectBoundingBox" x1="0" y1="0" x2="0" y2="1" id="gradient7">
|
||||
<stop offset="0" stop-color="#ffecd4" stop-opacity="1" />
|
||||
<stop offset="1" stop-color="#e8cdaa" stop-opacity="1" />
|
||||
</linearGradient>
|
||||
<linearGradient gradientUnits="objectBoundingBox" x1="0" y1="0" x2="0" y2="1" id="gradient8">
|
||||
<stop offset="0" stop-color="#f9eaff" stop-opacity="1" />
|
||||
<stop offset="1" stop-color="#cec1d3" stop-opacity="1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel" >
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,-53.1538,-112.277)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="#ffffff" fill-opacity="1" stroke="none" transform="matrix(0.969231,0,0,0.969231,-53.1538,-112.277)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<rect x="60" y="121" width="620" height="325"/>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,-53.1538,-112.277)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,513.846,197.877)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,513.846,197.877)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,421.769,100.954)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="url(#gradient1)" stroke="#5d979d" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,421.769,100.954)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<rect x="0" y="0" width="190" height="200"/>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,421.769,100.954)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,421.769,100.954)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,469.027,298.677)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,469.027,298.677)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,469.027,298.677)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="4" y="15" font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>Storage Location</text>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,469.027,298.677)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,469.027,298.677)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,469.027,298.677)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,469.027,298.677)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,460.538,144.569)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,460.538,144.569)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,441.154,115.492)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="url(#gradient2)" stroke="#5d979d" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,441.154,115.492)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M0,0 L24,0 L40,16 L40,60 L0,60 L0,0"/>
|
||||
<polyline fill="none" vector-effect="none" points="24,0 24,16 " />
|
||||
<polyline fill="none" vector-effect="none" points="24,16 40,16 " />
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,441.154,115.492)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,441.154,115.492)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,436.391,177.523)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,436.391,177.523)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,436.391,177.523)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="4" y="15" font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>KeyData</text>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,436.391,177.523)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,436.391,177.523)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,436.391,177.523)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,436.391,177.523)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,562.308,144.569)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,562.308,144.569)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,542.923,115.492)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="url(#gradient3)" stroke="#5d979d" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,542.923,115.492)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M0,0 L24,0 L40,16 L40,60 L0,60 L0,0"/>
|
||||
<polyline fill="none" vector-effect="none" points="24,0 24,16 " />
|
||||
<polyline fill="none" vector-effect="none" points="24,16 40,16 " />
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,542.923,115.492)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,542.923,115.492)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,177.523)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,177.523)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,177.523)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="4" y="15" font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>KeyData2</text>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,177.523)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,177.523)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,177.523)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,177.523)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,460.538,231.8)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,460.538,231.8)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,441.154,202.723)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="url(#gradient4)" stroke="#5d979d" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,441.154,202.723)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M0,0 L24,0 L40,16 L40,60 L0,60 L0,0"/>
|
||||
<polyline fill="none" vector-effect="none" points="24,0 24,16 " />
|
||||
<polyline fill="none" vector-effect="none" points="24,16 40,16 " />
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,441.154,202.723)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,441.154,202.723)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,433.385,264.754)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,433.385,264.754)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,433.385,264.754)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="4" y="15" font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>KeyData3</text>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,433.385,264.754)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,433.385,264.754)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,433.385,264.754)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,433.385,264.754)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,562.308,231.8)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,562.308,231.8)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,542.923,202.723)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="url(#gradient5)" stroke="#5d979d" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,542.923,202.723)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M0,0 L24,0 L40,16 L40,60 L0,60 L0,0"/>
|
||||
<polyline fill="none" vector-effect="none" points="24,0 24,16 " />
|
||||
<polyline fill="none" vector-effect="none" points="24,16 40,16 " />
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,542.923,202.723)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,542.923,202.723)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,264.754)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,264.754)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,264.754)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="4" y="15" font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>KeyData3</text>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,264.754)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,264.754)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,264.754)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,264.754)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,168.8)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,168.8)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,5,42.8)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="url(#gradient6)" stroke="#5d979d" stroke-opacity="1" stroke-width="2" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,5,42.8)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M0,0 L52.5,-39 L402.5,-39 L402.5,221 L350,260 L0,260 L0,0"/>
|
||||
<polyline fill="none" vector-effect="none" points="0,0 350,0 " />
|
||||
<polyline fill="none" vector-effect="none" points="350,0 402.5,-39 " />
|
||||
<polyline fill="none" vector-effect="none" points="350,0 350,260 " />
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,5,42.8)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,5,42.8)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,115.5,46.6769)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,115.5,46.6769)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,115.5,46.6769)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="19.3594" y="15" font-family="Ubuntu" font-size="11" font-weight="700" font-style="normal"
|
||||
>Node (Server or</text>
|
||||
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="43.2656" y="28" font-family="Ubuntu" font-size="11" font-weight="700" font-style="normal"
|
||||
>Client)</text>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,115.5,46.6769)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,115.5,46.6769)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,115.5,46.6769)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,115.5,46.6769)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,178.492)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,178.492)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,178.492)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="url(#gradient7)" stroke="#ac7e42" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,178.492)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<rect x="-155" y="-95" width="310" height="190"/>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,178.492)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,132.938)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#ac7e42" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,132.938)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<polyline fill="none" vector-effect="none" points="-155,4 155,4 " />
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,132.938)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,140.692)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#ac7e42" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,140.692)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<polyline fill="none" vector-effect="none" points="-155,4 155,4 " />
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,140.692)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,168.149,90.2923)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,168.149,90.2923)"
|
||||
font-family="Ubuntu" font-size="9" font-weight="400" font-style="normal"
|
||||
>
|
||||
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="0" y="9" font-family="Ubuntu" font-size="9" font-weight="400" font-style="normal"
|
||||
>QH</text>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,168.149,90.2923)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,142.964,100.954)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,142.964,100.954)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,142.964,100.954)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="4" y="15" font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>KeyStorage</text>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,142.964,100.954)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,142.964,100.954)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,142.964,100.954)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,142.964,100.954)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,132.643,122.277)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,132.643,122.277)"
|
||||
font-family="Ubuntu" font-size="9" font-weight="400" font-style="normal"
|
||||
>
|
||||
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="0" y="9" font-family="Ubuntu" font-size="9" font-weight="400" font-style="normal"
|
||||
>(from AbstractSpace)</text>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,132.643,122.277)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,197.877)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,197.877)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,197.877)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="url(#gradient8)" stroke="#7e6687" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,197.877)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<rect x="-140" y="-50" width="280" height="100"/>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,197.877)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,118.029,153.292)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,118.029,153.292)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,118.029,153.292)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="4" y="15" font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>ReadAllData methods</text>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,118.029,153.292)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,118.029,153.292)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,118.029,153.292)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,118.029,153.292)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,132.643,174.615)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,132.643,174.615)"
|
||||
font-family="Ubuntu" font-size="9" font-weight="400" font-style="normal"
|
||||
>
|
||||
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="0" y="9" font-family="Ubuntu" font-size="9" font-weight="400" font-style="normal"
|
||||
>(from AbstractSpace)</text>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,132.643,174.615)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,310.308,197.877)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,310.308,197.877)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,310.308,197.877)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,310.308,197.877)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,310.308,197.877)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-dasharray="4,4" stroke-dashoffset="0" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,310.308,197.877)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M10.3923,0 L104.608,0"/>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,310.308,197.877)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,421.769,197.877)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,421.769,197.877)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,421.769,197.877)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M-10.3923,-6 L0,0 L-10.3923,6"/>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,421.769,197.877)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(-0.969231,8.70301e-11,-8.70301e-11,-0.969231,310.308,197.877)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(-0.969231,8.70301e-11,-8.70301e-11,-0.969231,310.308,197.877)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(-0.969231,8.70301e-11,-8.70301e-11,-0.969231,310.308,197.877)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<path vector-effect="none" fill-rule="evenodd" d="M-10.3923,-6 L0,0 L-10.3923,6"/>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(-0.969231,8.70301e-11,-8.70301e-11,-0.969231,310.308,197.877)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,42.8,178.492)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,42.8,178.492)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,46.6769,182.369)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,46.6769,182.369)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,46.6769,182.369)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="4" y="15" font-family="Ubuntu" font-size="11" font-weight="700" font-style="normal"
|
||||
>This method read all files from storage</text>
|
||||
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="4" y="28" font-family="Ubuntu" font-size="11" font-weight="700" font-style="normal"
|
||||
>locations. </text>
|
||||
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="4" y="42" font-family="Ubuntu" font-size="11" font-weight="700" font-style="normal"
|
||||
>Where a name of file it is key of DataKey.</text>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,46.6769,182.369)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,46.6769,182.369)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,46.6769,182.369)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,46.6769,182.369)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
|
||||
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
|
||||
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
|
||||
>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 46 KiB |
@ -1,544 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<qmt>
|
||||
<project>
|
||||
<uid>{578fb64c-d647-45d7-9413-1a54b354db2b}</uid>
|
||||
<root-package>
|
||||
<instance>
|
||||
<MPackage>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{3cc6cd6f-0ce7-43b5-8a8c-1962b0207c79}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>KeyStorageImplementation</name>
|
||||
<children>
|
||||
<handles>
|
||||
<handles>
|
||||
<qlist>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{1ee7a90d-8a76-4fbd-9bd2-ef7a78f293e9}</uid>
|
||||
<target>
|
||||
<instance type="MCanvasDiagram">
|
||||
<MCanvasDiagram>
|
||||
<base-MDiagram>
|
||||
<MDiagram>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{1ee7a90d-8a76-4fbd-9bd2-ef7a78f293e9}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>KeyStorageImplementation</name>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
<elements>
|
||||
<qlist>
|
||||
<item>
|
||||
<instance type="DItem">
|
||||
<DItem>
|
||||
<base-DObject>
|
||||
<DObject>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{73bb3bc5-3604-4108-9eb9-6322ee2c03a6}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<object>{5bf04cca-9103-4df5-a5a6-42ca6a7478cd}</object>
|
||||
<name>Storage Location</name>
|
||||
<pos>x:585;y:320</pos>
|
||||
<rect>x:-95;y:-100;w:190;h:200</rect>
|
||||
<auto-sized>false</auto-sized>
|
||||
<visual-role>0</visual-role>
|
||||
</DObject>
|
||||
</base-DObject>
|
||||
<variety>artifact</variety>
|
||||
<shape-editable>false</shape-editable>
|
||||
</DItem>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DItem">
|
||||
<DItem>
|
||||
<base-DObject>
|
||||
<DObject>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{63906c75-b844-49ff-a2d7-003d91396628}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<object>{54a04999-4d1f-474d-b713-b41960caad2f}</object>
|
||||
<name>KeyData</name>
|
||||
<pos>x:530;y:265</pos>
|
||||
<rect>x:-20;y:-30;w:40;h:60</rect>
|
||||
<visual-role>0</visual-role>
|
||||
</DObject>
|
||||
</base-DObject>
|
||||
<variety>document</variety>
|
||||
<shape-editable>false</shape-editable>
|
||||
</DItem>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DItem">
|
||||
<DItem>
|
||||
<base-DObject>
|
||||
<DObject>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{4ba1d96e-4bb2-490f-9a2c-30f37cab8090}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<object>{7bf70bc2-48c6-4a73-8c37-c4d74c2a471c}</object>
|
||||
<name>KeyData2</name>
|
||||
<pos>x:635;y:265</pos>
|
||||
<rect>x:-20;y:-30;w:40;h:60</rect>
|
||||
<visual-role>0</visual-role>
|
||||
</DObject>
|
||||
</base-DObject>
|
||||
<variety>document</variety>
|
||||
<shape-editable>false</shape-editable>
|
||||
</DItem>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DItem">
|
||||
<DItem>
|
||||
<base-DObject>
|
||||
<DObject>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{f3c8b82c-2d10-4aab-bf2d-f0a773b1a214}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<object>{272fa499-b8f6-4b5f-a65d-52e94fd19e75}</object>
|
||||
<name>KeyData3</name>
|
||||
<pos>x:530;y:355</pos>
|
||||
<rect>x:-20;y:-30;w:40;h:60</rect>
|
||||
<visual-role>0</visual-role>
|
||||
</DObject>
|
||||
</base-DObject>
|
||||
<variety>document</variety>
|
||||
<shape-editable>false</shape-editable>
|
||||
</DItem>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DItem">
|
||||
<DItem>
|
||||
<base-DObject>
|
||||
<DObject>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{0a31881d-976f-49b4-84bc-6e829fde7524}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<object>{41a62eef-b99a-4292-9a5e-6877f3822d74}</object>
|
||||
<name>KeyData3</name>
|
||||
<pos>x:635;y:355</pos>
|
||||
<rect>x:-20;y:-30;w:40;h:60</rect>
|
||||
<visual-role>0</visual-role>
|
||||
</DObject>
|
||||
</base-DObject>
|
||||
<variety>document</variety>
|
||||
<shape-editable>false</shape-editable>
|
||||
</DItem>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DItem">
|
||||
<DItem>
|
||||
<base-DObject>
|
||||
<DObject>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{90e23bca-830b-4f04-9b79-d2b76aa7a942}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<object>{2ccda0b5-00de-4d4c-b365-e045dc6f6f31}</object>
|
||||
<name>Node (Server or Client)</name>
|
||||
<pos>x:235;y:290</pos>
|
||||
<rect>x:-175;y:-130;w:350;h:260</rect>
|
||||
<auto-sized>false</auto-sized>
|
||||
<visual-role>0</visual-role>
|
||||
<visual-emphasized>true</visual-emphasized>
|
||||
</DObject>
|
||||
</base-DObject>
|
||||
<variety>node</variety>
|
||||
<shape-editable>false</shape-editable>
|
||||
</DItem>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DClass">
|
||||
<DClass>
|
||||
<base-DObject>
|
||||
<DObject>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{32b0ae69-b40c-426c-aaa8-34d737714611}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<object>{962cbac6-7959-42e9-acd3-f26976cbe484}</object>
|
||||
<context>AbstractSpace</context>
|
||||
<name>KeyStorage</name>
|
||||
<pos>x:235;y:300</pos>
|
||||
<rect>x:-155;y:-95;w:310;h:190</rect>
|
||||
<auto-sized>false</auto-sized>
|
||||
<visual-role>0</visual-role>
|
||||
</DObject>
|
||||
</base-DObject>
|
||||
<namespace>QH</namespace>
|
||||
</DClass>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DDependency">
|
||||
<DDependency>
|
||||
<base-DRelation>
|
||||
<DRelation>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{18d07b5f-7a24-4007-811a-800f28514869}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<object>{58bd3970-0d20-48e4-ad00-e9b89ee16e8e}</object>
|
||||
<a>{b11fad66-7c15-4a0c-90d7-fdb7c7b09d54}</a>
|
||||
<b>{73bb3bc5-3604-4108-9eb9-6322ee2c03a6}</b>
|
||||
</DRelation>
|
||||
</base-DRelation>
|
||||
<direction>2</direction>
|
||||
</DDependency>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DItem">
|
||||
<DItem>
|
||||
<base-DObject>
|
||||
<DObject>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{b11fad66-7c15-4a0c-90d7-fdb7c7b09d54}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<object>{7c08d894-d147-4b48-8829-6f3a50c45cd0}</object>
|
||||
<context>AbstractSpace</context>
|
||||
<name>ReadAllData methods</name>
|
||||
<pos>x:235;y:320</pos>
|
||||
<rect>x:-140;y:-50;w:280;h:100</rect>
|
||||
<auto-sized>false</auto-sized>
|
||||
<visual-role>0</visual-role>
|
||||
</DObject>
|
||||
</base-DObject>
|
||||
<shape-editable>false</shape-editable>
|
||||
</DItem>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DAnnotation">
|
||||
<DAnnotation>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{ac8b121e-fdfc-41ae-bc0b-296e2658c1dc}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<text>This method read all files from storage locations.
|
||||
Where a name of file it is key of DataKey.</text>
|
||||
<pos>x:99;y:300</pos>
|
||||
<rect>x:0;y:0;w:270.125;h:57</rect>
|
||||
<auto-sized>false</auto-sized>
|
||||
<visual-role>3</visual-role>
|
||||
</DAnnotation>
|
||||
</instance>
|
||||
</item>
|
||||
</qlist>
|
||||
</elements>
|
||||
<last-modified>1600928388806</last-modified>
|
||||
<toolbarid>General</toolbarid>
|
||||
</MDiagram>
|
||||
</base-MDiagram>
|
||||
</MCanvasDiagram>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{5bf04cca-9103-4df5-a5a6-42ca6a7478cd}</uid>
|
||||
<target>
|
||||
<instance type="MItem">
|
||||
<MItem>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{5bf04cca-9103-4df5-a5a6-42ca6a7478cd}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>Storage Location</name>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
<variety-editable>false</variety-editable>
|
||||
<variety>artifact</variety>
|
||||
</MItem>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{b4753b9b-bb59-4797-8201-0e7f6cc3a09f}</uid>
|
||||
<target>
|
||||
<instance type="MItem">
|
||||
<MItem>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{b4753b9b-bb59-4797-8201-0e7f6cc3a09f}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>Новый Document</name>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
<variety-editable>false</variety-editable>
|
||||
<variety>document</variety>
|
||||
</MItem>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{54a04999-4d1f-474d-b713-b41960caad2f}</uid>
|
||||
<target>
|
||||
<instance type="MItem">
|
||||
<MItem>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{54a04999-4d1f-474d-b713-b41960caad2f}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>KeyData</name>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
<variety-editable>false</variety-editable>
|
||||
<variety>document</variety>
|
||||
</MItem>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{7bf70bc2-48c6-4a73-8c37-c4d74c2a471c}</uid>
|
||||
<target>
|
||||
<instance type="MItem">
|
||||
<MItem>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{7bf70bc2-48c6-4a73-8c37-c4d74c2a471c}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>KeyData2</name>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
<variety-editable>false</variety-editable>
|
||||
<variety>document</variety>
|
||||
</MItem>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{272fa499-b8f6-4b5f-a65d-52e94fd19e75}</uid>
|
||||
<target>
|
||||
<instance type="MItem">
|
||||
<MItem>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{272fa499-b8f6-4b5f-a65d-52e94fd19e75}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>KeyData3</name>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
<variety-editable>false</variety-editable>
|
||||
<variety>document</variety>
|
||||
</MItem>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{41a62eef-b99a-4292-9a5e-6877f3822d74}</uid>
|
||||
<target>
|
||||
<instance type="MItem">
|
||||
<MItem>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{41a62eef-b99a-4292-9a5e-6877f3822d74}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>KeyData3</name>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
<variety-editable>false</variety-editable>
|
||||
<variety>document</variety>
|
||||
</MItem>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{2ccda0b5-00de-4d4c-b365-e045dc6f6f31}</uid>
|
||||
<target>
|
||||
<instance type="MItem">
|
||||
<MItem>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{2ccda0b5-00de-4d4c-b365-e045dc6f6f31}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>Node (Server or Client)</name>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
<variety-editable>false</variety-editable>
|
||||
<variety>node</variety>
|
||||
</MItem>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{d472d214-54c2-4045-b825-9a2ab109d69f}</uid>
|
||||
<target>
|
||||
<instance type="MPackage">
|
||||
<MPackage>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{d472d214-54c2-4045-b825-9a2ab109d69f}</uid>
|
||||
<flags>1</flags>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>AbstractSpace</name>
|
||||
<children>
|
||||
<handles>
|
||||
<handles>
|
||||
<qlist>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{962cbac6-7959-42e9-acd3-f26976cbe484}</uid>
|
||||
<target>
|
||||
<instance type="MClass">
|
||||
<MClass>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{962cbac6-7959-42e9-acd3-f26976cbe484}</uid>
|
||||
<flags>1</flags>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>KeyStorage</name>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
<namespace>QH</namespace>
|
||||
</MClass>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{7c08d894-d147-4b48-8829-6f3a50c45cd0}</uid>
|
||||
<target>
|
||||
<instance type="MItem">
|
||||
<MItem>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{7c08d894-d147-4b48-8829-6f3a50c45cd0}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>ReadAllData methods</name>
|
||||
<relations>
|
||||
<handles>
|
||||
<handles>
|
||||
<qlist>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{58bd3970-0d20-48e4-ad00-e9b89ee16e8e}</uid>
|
||||
<target>
|
||||
<instance type="MDependency">
|
||||
<MDependency>
|
||||
<base-MRelation>
|
||||
<MRelation>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{58bd3970-0d20-48e4-ad00-e9b89ee16e8e}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<a>{7c08d894-d147-4b48-8829-6f3a50c45cd0}</a>
|
||||
<b>{5bf04cca-9103-4df5-a5a6-42ca6a7478cd}</b>
|
||||
</MRelation>
|
||||
</base-MRelation>
|
||||
<direction>2</direction>
|
||||
</MDependency>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
</qlist>
|
||||
</handles>
|
||||
</handles>
|
||||
</relations>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
</MItem>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
</qlist>
|
||||
</handles>
|
||||
</handles>
|
||||
</children>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
</MPackage>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
</qlist>
|
||||
</handles>
|
||||
</handles>
|
||||
</children>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
</MPackage>
|
||||
</instance>
|
||||
</root-package>
|
||||
</project>
|
||||
</qmt>
|
@ -27,8 +27,6 @@
|
||||
#include "abstractdata.h"
|
||||
#include "workstate.h"
|
||||
#include "package.h"
|
||||
#include "cryptopairkeys.h"
|
||||
#include "icrypto.h"
|
||||
#include "heart_global.h"
|
||||
#include "packagemanager.h"
|
||||
#include "abstracterrorcodes.h"
|
||||
|
@ -6,85 +6,4 @@
|
||||
*/
|
||||
|
||||
#include "asynckeysauth.h"
|
||||
#include "QCryptographicHash"
|
||||
#include <QString>
|
||||
#include <time.h>
|
||||
|
||||
namespace QH {
|
||||
|
||||
AsyncKeysAuth::AsyncKeysAuth() {
|
||||
|
||||
}
|
||||
|
||||
bool AsyncKeysAuth::auth(int allowedTimeRangeSec, QString* userId) const {
|
||||
|
||||
int diff = time(0) - _unixTime;
|
||||
|
||||
if (diff < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (diff >= allowedTimeRangeSec) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray data = _publicKey;
|
||||
data.insert(0, reinterpret_cast<const char*>(&_unixTime),
|
||||
sizeof(_unixTime));
|
||||
|
||||
bool result = checkSign(data, _signature, _publicKey);
|
||||
|
||||
if (result && userId) {
|
||||
*userId = getUserId();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AsyncKeysAuth::prepare() {
|
||||
_unixTime = time(0);
|
||||
|
||||
QByteArray data = _publicKey;
|
||||
data.insert(0, reinterpret_cast<const char*>(&_unixTime),
|
||||
sizeof(_unixTime));
|
||||
|
||||
setSignature(signMessage(data, getPrivateKey()));
|
||||
|
||||
return isValid();
|
||||
}
|
||||
|
||||
unsigned int AsyncKeysAuth::unixTime() const {
|
||||
return _unixTime;
|
||||
}
|
||||
|
||||
void AsyncKeysAuth::setUnixTime(unsigned int newUnixTime) {
|
||||
_unixTime = newUnixTime;
|
||||
}
|
||||
|
||||
const QByteArray &AsyncKeysAuth::signature() const {
|
||||
return _signature;
|
||||
}
|
||||
|
||||
const QByteArray &AsyncKeysAuth::publicKey() const {
|
||||
return _publicKey;
|
||||
}
|
||||
|
||||
void AsyncKeysAuth::setPublicKey(const QByteArray &newPublicKey) {
|
||||
_publicKey = newPublicKey;
|
||||
}
|
||||
|
||||
bool AsyncKeysAuth::isValid() const {
|
||||
return _publicKey.size() && _signature.size() && _unixTime;
|
||||
}
|
||||
|
||||
QString AsyncKeysAuth::getUserId() const {
|
||||
return QCryptographicHash::hash(_publicKey,
|
||||
QCryptographicHash::Sha256).
|
||||
toBase64(QByteArray::Base64UrlEncoding);
|
||||
}
|
||||
|
||||
void AsyncKeysAuth::setSignature(const QByteArray &newSignature) {
|
||||
_signature = newSignature;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,14 +8,29 @@
|
||||
#ifndef ASYNCKEYSAUTH_H
|
||||
#define ASYNCKEYSAUTH_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QCryptographicHash>
|
||||
#include <time.h>
|
||||
#include <QString>
|
||||
|
||||
#include "heart_global.h"
|
||||
#include "hcrypto/icrypto.h"
|
||||
|
||||
namespace QH {
|
||||
|
||||
/**
|
||||
* @brief The AsyncKeysAuth class is base class for works with authorization of a pair of asynchronous keys
|
||||
* @brief The AsyncKeysAuth class is temaplate class for works with authorization of a pair of asynchronous keys
|
||||
* This class contains base implementation for the authentication using async encription. The base encription alhorithm defined on the template argument **CryptoImplementation**.
|
||||
* You can use any crypto alhorithm.
|
||||
*
|
||||
* ## Exampel of use:
|
||||
*
|
||||
* @code{cpp}
|
||||
* #include <hcrypto.h>
|
||||
*
|
||||
* using ECDSAAuth = AsyncKeysAuth<ECDSA>;
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
*
|
||||
* ### How to it works:
|
||||
*
|
||||
@ -46,45 +61,115 @@ namespace QH {
|
||||
* * After accept server create new user with ID = sha256(PUB) or
|
||||
* if user alredy exits make them as a logined user.
|
||||
*
|
||||
* @tparam CryptoImplementation This is internal implementaion of base encription functions.
|
||||
* @see iCrypto class.
|
||||
*
|
||||
*/
|
||||
class HEARTSHARED_EXPORT AsyncKeysAuth
|
||||
|
||||
template<class CryptoImplementation>
|
||||
class HEARTSHARED_EXPORT AsyncKeysAuth: public CryptoImplementation
|
||||
{
|
||||
public:
|
||||
AsyncKeysAuth();
|
||||
AsyncKeysAuth() {
|
||||
|
||||
}
|
||||
|
||||
~AsyncKeysAuth() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief auth This method make authentication and return true if the authentication finished successful else false.
|
||||
* @brief retLoginedUserId This is logined user id in Base64UrlEncoding
|
||||
* @return true if the authentication finished successful else false.
|
||||
*/
|
||||
bool auth(int allowedTimeRangeSec, QString* retLoginedUserId) const;
|
||||
bool auth(int allowedTimeRangeSec, QString* retLoginedUserId) const {
|
||||
|
||||
int diff = time(0) - _unixTime;
|
||||
|
||||
if (diff < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (diff >= allowedTimeRangeSec) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray data = _publicKey;
|
||||
data.insert(0, reinterpret_cast<const char*>(&_unixTime),
|
||||
sizeof(_unixTime));
|
||||
|
||||
bool result = checkSign(data, _signature, _publicKey);
|
||||
|
||||
if (result && retLoginedUserId) {
|
||||
*retLoginedUserId = getUserId();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief prepare This method will generate signature for autentication of client. Please inboke this method before send request to server.
|
||||
* @return true if signature generated sucessuful.
|
||||
*/
|
||||
bool prepare();
|
||||
bool prepare() {
|
||||
_unixTime = time(0);
|
||||
|
||||
QByteArray data = _publicKey;
|
||||
data.insert(0, reinterpret_cast<const char*>(&_unixTime),
|
||||
sizeof(_unixTime));
|
||||
|
||||
setSignature(signMessage(data, getPrivateKey()));
|
||||
|
||||
return isValid();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief unixTime This method return unix time that client added for authentication.
|
||||
* @return unix time that client added for authentication.
|
||||
* @see AsyncKeysAuth::setUnixTime
|
||||
*/
|
||||
unsigned int unixTime() const;
|
||||
unsigned int unixTime() const {
|
||||
return _unixTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief setUnixTime This method sets new value of the unixTime propertye.
|
||||
* @param newUnixTime This is new unix time value. Unix time sets in secunds from 1970 year
|
||||
*/
|
||||
void setUnixTime(unsigned int newUnixTime);
|
||||
void setUnixTime(unsigned int newUnixTime) {
|
||||
_unixTime = newUnixTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief signature This method return signature array.
|
||||
* @return signature array.
|
||||
* @see AsyncKeysAuth::setSignature
|
||||
*/
|
||||
const QByteArray &signature() const;
|
||||
const QByteArray &signature() const {
|
||||
return _signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief isValid this method check this ibject to valid.
|
||||
* @return return true if object contains valid signature else false.
|
||||
* @note Invoke the AsyncKeysAuth::prepare method before check valid of object. All object that not be preparred is invalid.
|
||||
*/
|
||||
bool isValid() const {
|
||||
return _publicKey.size() && _signature.size() && _unixTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief getUserId This method return user id that generated from the public key.
|
||||
* @note This function works slow, because this object does not contain ID of user. The user ID will be generated every invoke of this function
|
||||
* @return user ID.
|
||||
*/
|
||||
QString getUserId() const {
|
||||
return QCryptographicHash::hash(_publicKey,
|
||||
QCryptographicHash::Sha256).
|
||||
toBase64(QByteArray::Base64UrlEncoding);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief publicKey This method return public key that client added for authentication.
|
||||
@ -92,49 +177,36 @@ public:
|
||||
* @return public key that client added for authentication.
|
||||
* @see AsyncKeysAuth::setPublicKey
|
||||
*/
|
||||
const QByteArray &publicKey() const;
|
||||
const QByteArray &publicKey() const {
|
||||
return _publicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief setPublicKey This method sets new public key for authentication.
|
||||
* @param newPublicKey Thiy is new key.
|
||||
* @see AsyncKeysAuth::publicKey
|
||||
*/
|
||||
void setPublicKey(const QByteArray &newPublicKey);
|
||||
|
||||
/**
|
||||
* @brief isValid this method check this ibject to valid.
|
||||
* @return return true if object contains valid signature else false.
|
||||
* @note Invoke the AsyncKeysAuth::prepare method before check valid of object. All object that not be preparred is invalid.
|
||||
*/
|
||||
bool isValid() const;
|
||||
|
||||
/**
|
||||
* @brief getUserId This method return user id that generated from the public key.
|
||||
* @note This function works slow, because this object does not contain ID of user. The user ID will be generated every invoke of this function
|
||||
* @return user ID.
|
||||
*/
|
||||
QString getUserId() const;
|
||||
void setPublicKey(const QByteArray &newPublicKey) {
|
||||
_publicKey = newPublicKey;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief signMessage This method should be sign the @a message using the @a key.
|
||||
* @param message This is input data that should be signed.
|
||||
* @param key This is a privete key for encription the @a message.
|
||||
* @return signature data array.
|
||||
* @see AsyncKeysAuth::descrupt
|
||||
*/
|
||||
virtual QByteArray signMessage(const QByteArray& message, const QByteArray& key) const = 0;
|
||||
QByteArray decript(const QByteArray &message, const QByteArray &key) override {
|
||||
return CryptoImplementation::decript(message, key);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief checkSign This method should be check signature of the @a message using the @a key.
|
||||
* @param message This is input data that should be decripted.
|
||||
* @param signature This is signature that will be checked for the @a message.
|
||||
* @param key This is a public key for encription the @a inpputData.
|
||||
* @return decripted data array.
|
||||
* @see AsyncKeysAuth::encrypt
|
||||
*/
|
||||
virtual bool checkSign(const QByteArray& message, const QByteArray& signature, const QByteArray& key) const = 0;
|
||||
QByteArray encript(const QByteArray &message, const QByteArray &key) override {
|
||||
return CryptoImplementation::encript(message, key);
|
||||
};
|
||||
|
||||
QByteArray signMessage(const QByteArray &message, const QByteArray &key) const override {
|
||||
return CryptoImplementation::signMessage(message, key);
|
||||
};
|
||||
|
||||
bool checkSign(const QByteArray &message, const QByteArray &signature, const QByteArray &key) const override {
|
||||
return CryptoImplementation::checkSign(message, signature, key);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief getPrivateKey This method should be return private key for the public key that saved in this object.
|
||||
@ -147,7 +219,9 @@ protected:
|
||||
* @param newSignature new signature value.
|
||||
* @note used in the
|
||||
*/
|
||||
void setSignature(const QByteArray &newSignature);
|
||||
void setSignature(const QByteArray &newSignature) {
|
||||
_signature = newSignature;
|
||||
}
|
||||
|
||||
unsigned int _unixTime = 0;
|
||||
QByteArray _signature;
|
||||
|
@ -7,238 +7,3 @@
|
||||
|
||||
|
||||
#include "authecdsa.h"
|
||||
|
||||
#ifdef USE_HEART_SSL
|
||||
|
||||
#include <openssl/ecdsa.h> // for ECDSA_do_sign, ECDSA_do_verify
|
||||
#include <openssl/obj_mac.h> // for NID_secp192k1
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <QCryptographicHash>
|
||||
#include <QIODevice>
|
||||
#include <QVector>
|
||||
#include <quasarapp.h>
|
||||
|
||||
namespace QH {
|
||||
|
||||
AuthECDSA::AuthECDSA() {
|
||||
|
||||
}
|
||||
|
||||
void printlastOpenSSlError() {
|
||||
int error = ERR_get_error();
|
||||
char buffer[256];
|
||||
ERR_error_string(error, buffer);
|
||||
QuasarAppUtils::Params::log(QString("openssl: %0").arg(buffer),
|
||||
QuasarAppUtils::Error);
|
||||
}
|
||||
|
||||
QByteArray bignumToArray(const BIGNUM* num) {
|
||||
int length = BN_bn2mpi(num, nullptr);
|
||||
QVector<unsigned char> data(length);
|
||||
BN_bn2mpi(num, data.data());
|
||||
QByteArray result;
|
||||
result.insert(0, reinterpret_cast<char*>(data.data()), data.length());
|
||||
return result;
|
||||
}
|
||||
|
||||
BIGNUM* bignumFromArray(const QByteArray& array) {
|
||||
auto d = reinterpret_cast<const unsigned char*>(array.data());
|
||||
BIGNUM* result = BN_mpi2bn(d,
|
||||
array.length(), nullptr);
|
||||
if (!result) {
|
||||
printlastOpenSSlError();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QByteArray extractPrivateKey(EC_KEY* ec_key) {
|
||||
const BIGNUM* ec_priv = EC_KEY_get0_private_key(ec_key);
|
||||
return bignumToArray(ec_priv);
|
||||
}
|
||||
|
||||
QByteArray extractPublicKey(EC_KEY* key, EC_GROUP* group) {
|
||||
|
||||
QByteArray data;
|
||||
point_conversion_form_t form = EC_GROUP_get_point_conversion_form(group);
|
||||
|
||||
unsigned char* pub_key_buffer;
|
||||
size_t length = EC_KEY_key2buf(key, form, &pub_key_buffer, nullptr);
|
||||
|
||||
if (length <= 0) {
|
||||
printlastOpenSSlError();
|
||||
return {};
|
||||
}
|
||||
|
||||
data.insert(0, reinterpret_cast<const char*>(pub_key_buffer), length);
|
||||
|
||||
OPENSSL_free(pub_key_buffer);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
bool AuthECDSA::makeKeys(QByteArray &pubKey, QByteArray &privKey) {
|
||||
|
||||
EC_KEY *eckey= nullptr;
|
||||
EC_GROUP *ecgroup = nullptr;
|
||||
|
||||
if (!prepareKeyAdnGroupObjects(&eckey, &ecgroup)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EC_KEY_generate_key(eckey)) {
|
||||
printlastOpenSSlError();
|
||||
EC_GROUP_free(ecgroup);
|
||||
EC_KEY_free(eckey);
|
||||
return false;
|
||||
}
|
||||
|
||||
pubKey = extractPublicKey(eckey, ecgroup);
|
||||
privKey = extractPrivateKey(eckey);
|
||||
|
||||
return pubKey.length() && privKey.length();
|
||||
}
|
||||
|
||||
QByteArray AuthECDSA::signMessage(const QByteArray &inputData,
|
||||
const QByteArray &key) const {
|
||||
|
||||
EC_KEY *eckey= nullptr;
|
||||
EC_GROUP *ecgroup = nullptr;
|
||||
|
||||
if (!prepareKeyAdnGroupObjects(&eckey, &ecgroup)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto hash = QCryptographicHash::hash(inputData,
|
||||
QCryptographicHash::Sha256);
|
||||
|
||||
BIGNUM* priv = bignumFromArray(key);
|
||||
if (!EC_KEY_set_private_key(eckey, priv)) {
|
||||
printlastOpenSSlError();
|
||||
EC_GROUP_free(ecgroup);
|
||||
EC_KEY_free(eckey);
|
||||
return {};
|
||||
};
|
||||
|
||||
ECDSA_SIG *signature = ECDSA_do_sign(reinterpret_cast<const unsigned char*>(hash.data()),
|
||||
hash.length(), eckey);
|
||||
BN_free(priv);
|
||||
EC_KEY_free(eckey);
|
||||
EC_GROUP_free(ecgroup);
|
||||
|
||||
if (!signature) {
|
||||
printlastOpenSSlError();
|
||||
return {};
|
||||
}
|
||||
|
||||
const BIGNUM * R, *S;
|
||||
ECDSA_SIG_get0(signature, &R, &S);
|
||||
|
||||
QByteArray result;
|
||||
QDataStream stream(&result, QIODevice::WriteOnly);
|
||||
|
||||
stream << bignumToArray(R);
|
||||
stream << bignumToArray(S);
|
||||
|
||||
ECDSA_SIG_free(signature);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AuthECDSA::checkSign(const QByteArray &inputData,
|
||||
const QByteArray &signature,
|
||||
const QByteArray &key) const {
|
||||
|
||||
|
||||
// extract signature from raw array
|
||||
|
||||
BIGNUM * R, *S;
|
||||
QDataStream stream(signature);
|
||||
|
||||
QByteArray rR,rS;
|
||||
stream >> rR;
|
||||
stream >> rS;
|
||||
R = bignumFromArray(rR);
|
||||
S = bignumFromArray(rS);
|
||||
|
||||
ECDSA_SIG *sig = ECDSA_SIG_new();
|
||||
ECDSA_SIG_set0(sig, R, S);
|
||||
|
||||
auto hash = QCryptographicHash::hash(inputData,
|
||||
QCryptographicHash::Sha256);
|
||||
|
||||
|
||||
EC_KEY *eckey= nullptr;
|
||||
EC_GROUP *ecgroup = nullptr;
|
||||
|
||||
if (!prepareKeyAdnGroupObjects(&eckey, &ecgroup)) {
|
||||
ECDSA_SIG_free(sig);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
// extract key from raw array;
|
||||
EC_POINT* ec_point = EC_POINT_new(ecgroup);
|
||||
EC_POINT_oct2point(ecgroup, ec_point,
|
||||
reinterpret_cast<const unsigned char*>(key.data()),
|
||||
key.length(), nullptr);
|
||||
|
||||
EC_KEY_set_public_key(eckey, ec_point);
|
||||
|
||||
|
||||
int verify_status = ECDSA_do_verify(reinterpret_cast<const unsigned char*>(hash.data()),
|
||||
hash.length(), sig, eckey);
|
||||
|
||||
ECDSA_SIG_free(sig);
|
||||
EC_POINT_free(ec_point);
|
||||
|
||||
return verify_status == 1;
|
||||
|
||||
}
|
||||
|
||||
bool AuthECDSA::prepareKeyAdnGroupObjects(EC_KEY **eckey, EC_GROUP **ecgroup) {
|
||||
|
||||
// input data should be valid pointers to pointers of key and group objects.
|
||||
if (!(eckey && ecgroup))
|
||||
return false;
|
||||
|
||||
// input pointers should be nullptr;
|
||||
if ((*eckey) || (*ecgroup))
|
||||
return false;
|
||||
|
||||
auto free = [eckey, ecgroup] () {
|
||||
if (*ecgroup)
|
||||
EC_GROUP_free(*ecgroup);
|
||||
|
||||
if (*eckey)
|
||||
EC_KEY_free(*eckey);
|
||||
};
|
||||
|
||||
*eckey = EC_KEY_new();
|
||||
if (!*eckey) {
|
||||
printlastOpenSSlError();
|
||||
free();
|
||||
return false;
|
||||
}
|
||||
|
||||
*ecgroup = EC_GROUP_new_by_curve_name(NID_secp256k1);
|
||||
|
||||
if (!*ecgroup) {
|
||||
printlastOpenSSlError();
|
||||
free();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EC_KEY_set_group(*eckey, *ecgroup)) {
|
||||
printlastOpenSSlError();
|
||||
free();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -14,42 +14,19 @@
|
||||
|
||||
|
||||
#include "abstractdata.h"
|
||||
#include "hcrypto/ecdsa.h"
|
||||
|
||||
#include <asynckeysauth.h>
|
||||
|
||||
#include <openssl/ec.h> // for EC_GROUP_new_by_curve_name, EC_GROUP_free, EC_KEY_new, EC_KEY_set_group, EC_KEY_generate_key,EC_KEY_free
|
||||
|
||||
namespace QH {
|
||||
|
||||
/**
|
||||
* @brief The AuthECDSA class is ecdsa implementation of the Async authentication. This implementation based on Openssl library.
|
||||
*/
|
||||
class HEARTSHARED_EXPORT AuthECDSA: public QH::AsyncKeysAuth
|
||||
{
|
||||
|
||||
public:
|
||||
AuthECDSA();
|
||||
|
||||
/**
|
||||
* @brief makeKeys This static method generate the public and private keys of the ECDSA.
|
||||
* @param pubKey This is result public key.
|
||||
* @param privKey This is result private key.
|
||||
* @return true if keys generated successful.
|
||||
*/
|
||||
static bool makeKeys(QByteArray &pubKey, QByteArray &privKey);
|
||||
|
||||
// AsyncKeysAuth interface
|
||||
protected:
|
||||
QByteArray signMessage(const QByteArray &inputData, const QByteArray &key) const override;
|
||||
bool checkSign(const QByteArray &inputData, const QByteArray &signature, const QByteArray &key) const override;
|
||||
|
||||
private:
|
||||
static bool prepareKeyAdnGroupObjects(EC_KEY **eckey, EC_GROUP **ecgroup);
|
||||
|
||||
};
|
||||
|
||||
typedef AsyncKeysAuth<ECDSA> AuthECDSA;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // AUTHECDSA_H
|
||||
|
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2022 QuasarApp.
|
||||
* Distributed under the lgplv3 software license, see the accompanying
|
||||
* Everyone is permitted to copy and distribute verbatim copies
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
|
||||
|
||||
#include "cryptopairkeys.h"
|
||||
|
||||
#include <QDataStream>
|
||||
namespace QH {
|
||||
CryptoPairKeys::CryptoPairKeys() {
|
||||
|
||||
}
|
||||
|
||||
CryptoPairKeys::CryptoPairKeys(const QByteArray &pubKey, const QByteArray &privKey) {
|
||||
setPrivKey(privKey);
|
||||
setPublicKey(pubKey);
|
||||
setBits(privKey.size() * 8);
|
||||
}
|
||||
|
||||
bool CryptoPairKeys::isValid() const {
|
||||
return _privKey.size() && _publicKey.size() && !(_bits % 8) && _bits > 1;
|
||||
}
|
||||
|
||||
QByteArray CryptoPairKeys::privKey() const {
|
||||
return _privKey;
|
||||
}
|
||||
|
||||
void CryptoPairKeys::setPrivKey(const QByteArray &privKey) {
|
||||
_privKey = privKey;
|
||||
}
|
||||
|
||||
QByteArray CryptoPairKeys::publicKey() const {
|
||||
return _publicKey;
|
||||
}
|
||||
|
||||
void CryptoPairKeys::setPublicKey(const QByteArray &publicKey) {
|
||||
_publicKey = publicKey;
|
||||
}
|
||||
|
||||
int CryptoPairKeys::bits() const {
|
||||
return _bits;
|
||||
}
|
||||
|
||||
void CryptoPairKeys::setBits(int bits) {
|
||||
_bits = bits;
|
||||
}
|
||||
|
||||
QDataStream &CryptoPairKeys::fromStream(QDataStream &stream) {
|
||||
|
||||
stream >> _publicKey;
|
||||
stream >> _privKey;
|
||||
stream >> _bits;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream &CryptoPairKeys::toStream(QDataStream &stream) const {
|
||||
stream << _publicKey;
|
||||
stream << _privKey;
|
||||
stream << _bits;
|
||||
|
||||
return stream;
|
||||
|
||||
}
|
||||
|
||||
bool operator ==(const CryptoPairKeys &left, const CryptoPairKeys &right) {
|
||||
return !(left != right);
|
||||
}
|
||||
|
||||
bool operator !=(const CryptoPairKeys &left, const CryptoPairKeys &right) {
|
||||
return left._privKey != right._privKey || left._publicKey != right._publicKey;
|
||||
}
|
||||
|
||||
uint qHash(const CryptoPairKeys &value) {
|
||||
return qHash(value.privKey());
|
||||
}
|
||||
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2022 QuasarApp.
|
||||
* Distributed under the lgplv3 software license, see the accompanying
|
||||
* Everyone is permitted to copy and distribute verbatim copies
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CRYPTOPAIRKEYS_H
|
||||
#define CRYPTOPAIRKEYS_H
|
||||
|
||||
#include "streambase.h"
|
||||
|
||||
|
||||
namespace QH {
|
||||
|
||||
/**
|
||||
* @brief The CryptoPairKeys class contains pair keys. This is wraper for cripto graphick keys.
|
||||
*/
|
||||
class HEARTSHARED_EXPORT CryptoPairKeys: public StreamBase
|
||||
{
|
||||
public:
|
||||
CryptoPairKeys();
|
||||
CryptoPairKeys(const QByteArray& pubKey, const QByteArray& privKey);
|
||||
|
||||
/**
|
||||
* @brief isValid - This Method check an internal keys.
|
||||
* @return true if this objeсt contains a valid pair keys.
|
||||
*/
|
||||
bool isValid() const;
|
||||
|
||||
/**
|
||||
* @brief privKey This method return private key of current keys pair.
|
||||
* @return return byteArray of private key.
|
||||
*/
|
||||
QByteArray privKey() const;
|
||||
|
||||
/**
|
||||
* @brief setPrivKey This method set a private key for keys pair.
|
||||
* @param privKey new byte array of private pair keys.
|
||||
*/
|
||||
void setPrivKey(const QByteArray &privKey);
|
||||
|
||||
/**
|
||||
* @brief publicKey This method return public key of array.
|
||||
* @return publicKey of current key pair.
|
||||
*/
|
||||
QByteArray publicKey() const;
|
||||
|
||||
/**
|
||||
* @brief setPublicKey This method set new value of publickKey.
|
||||
* @param publicKey new value of publicKey.
|
||||
*/
|
||||
void setPublicKey(const QByteArray &publicKey);
|
||||
|
||||
/**
|
||||
* @brief bits This method return size pair of crypto keys in bits.
|
||||
* @return bits size of keys pair.
|
||||
*/
|
||||
int bits() const;
|
||||
|
||||
/**
|
||||
* @brief setBits This method sets new value of keys pair.
|
||||
* @param bits This is new value of size keys.
|
||||
*/
|
||||
void setBits(int bits);
|
||||
|
||||
friend bool operator != (const CryptoPairKeys& left, const CryptoPairKeys& right);
|
||||
friend bool operator == (const CryptoPairKeys& left, const CryptoPairKeys& right);
|
||||
|
||||
// StreamBase interface
|
||||
protected:
|
||||
QDataStream &fromStream(QDataStream &stream);
|
||||
QDataStream &toStream(QDataStream &stream) const;
|
||||
|
||||
private:
|
||||
QByteArray _privKey;
|
||||
QByteArray _publicKey;
|
||||
|
||||
int _bits;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief qHash This functions calc crc32 hash code of CryptoPairKeys object.
|
||||
* @param value -
|
||||
* @return crc32 hash code.
|
||||
*/
|
||||
uint qHash(const CryptoPairKeys& value);
|
||||
}
|
||||
#endif // CRYPTOPAIRKEYS_H
|
254
Heart/AbstractSpace/hcrypto/ecdsa.cpp
Normal file
254
Heart/AbstractSpace/hcrypto/ecdsa.cpp
Normal file
@ -0,0 +1,254 @@
|
||||
//#
|
||||
//# Copyright (C) 2021-2022 QuasarApp.
|
||||
//# Distributed under the GPLv3 software license, see the accompanying
|
||||
//# Everyone is permitted to copy and distribute verbatim copies
|
||||
//# of this license document, but changing it is not allowed.
|
||||
//#
|
||||
|
||||
|
||||
#include "ecdsa.h"
|
||||
|
||||
#ifdef USE_HEART_SSL
|
||||
|
||||
#include <openssl/ecdsa.h> // for ECDSA_do_sign, ECDSA_do_verify
|
||||
#include <openssl/obj_mac.h> // for NID_secp192k1
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <QCryptographicHash>
|
||||
#include <QIODevice>
|
||||
#include <QVector>
|
||||
#include <quasarapp.h>
|
||||
|
||||
namespace QH {
|
||||
|
||||
ECDSA::ECDSA() {
|
||||
|
||||
}
|
||||
|
||||
void printlastOpenSSlError() {
|
||||
int error = ERR_get_error();
|
||||
char buffer[256];
|
||||
ERR_error_string(error, buffer);
|
||||
QuasarAppUtils::Params::log(QString("openssl: %0").arg(buffer),
|
||||
QuasarAppUtils::Error);
|
||||
}
|
||||
|
||||
QByteArray bignumToArray(const BIGNUM* num) {
|
||||
int length = BN_bn2mpi(num, nullptr);
|
||||
QVector<unsigned char> data(length);
|
||||
BN_bn2mpi(num, data.data());
|
||||
QByteArray result;
|
||||
result.insert(0, reinterpret_cast<char*>(data.data()), data.length());
|
||||
return result;
|
||||
}
|
||||
|
||||
BIGNUM* bignumFromArray(const QByteArray& array) {
|
||||
auto d = reinterpret_cast<const unsigned char*>(array.data());
|
||||
BIGNUM* result = BN_mpi2bn(d,
|
||||
array.length(), nullptr);
|
||||
if (!result) {
|
||||
printlastOpenSSlError();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QByteArray extractPrivateKey(EC_KEY* ec_key) {
|
||||
const BIGNUM* ec_priv = EC_KEY_get0_private_key(ec_key);
|
||||
return bignumToArray(ec_priv);
|
||||
}
|
||||
|
||||
QByteArray extractPublicKey(EC_KEY* key, EC_GROUP* group) {
|
||||
|
||||
QByteArray data;
|
||||
point_conversion_form_t form = EC_GROUP_get_point_conversion_form(group);
|
||||
|
||||
unsigned char* pub_key_buffer;
|
||||
size_t length = EC_KEY_key2buf(key, form, &pub_key_buffer, nullptr);
|
||||
|
||||
if (length <= 0) {
|
||||
printlastOpenSSlError();
|
||||
return {};
|
||||
}
|
||||
|
||||
data.insert(0, reinterpret_cast<const char*>(pub_key_buffer), length);
|
||||
|
||||
OPENSSL_free(pub_key_buffer);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
bool ECDSA::makeKeys(QByteArray &pubKey, QByteArray &privKey) {
|
||||
|
||||
EC_KEY *eckey= nullptr;
|
||||
EC_GROUP *ecgroup = nullptr;
|
||||
|
||||
if (!prepareKeyAdnGroupObjects(&eckey, &ecgroup)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EC_KEY_generate_key(eckey)) {
|
||||
printlastOpenSSlError();
|
||||
EC_GROUP_free(ecgroup);
|
||||
EC_KEY_free(eckey);
|
||||
return false;
|
||||
}
|
||||
|
||||
pubKey = extractPublicKey(eckey, ecgroup);
|
||||
privKey = extractPrivateKey(eckey);
|
||||
|
||||
return pubKey.length() && privKey.length();
|
||||
}
|
||||
|
||||
QByteArray ECDSA::signMessage(const QByteArray &inputData,
|
||||
const QByteArray &key) const {
|
||||
|
||||
EC_KEY *eckey= nullptr;
|
||||
EC_GROUP *ecgroup = nullptr;
|
||||
|
||||
if (!prepareKeyAdnGroupObjects(&eckey, &ecgroup)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto hash = QCryptographicHash::hash(inputData,
|
||||
QCryptographicHash::Sha256);
|
||||
|
||||
BIGNUM* priv = bignumFromArray(key);
|
||||
if (!EC_KEY_set_private_key(eckey, priv)) {
|
||||
printlastOpenSSlError();
|
||||
EC_GROUP_free(ecgroup);
|
||||
EC_KEY_free(eckey);
|
||||
return {};
|
||||
};
|
||||
|
||||
ECDSA_SIG *signature = ECDSA_do_sign(reinterpret_cast<const unsigned char*>(hash.data()),
|
||||
hash.length(), eckey);
|
||||
BN_free(priv);
|
||||
EC_KEY_free(eckey);
|
||||
EC_GROUP_free(ecgroup);
|
||||
|
||||
if (!signature) {
|
||||
printlastOpenSSlError();
|
||||
return {};
|
||||
}
|
||||
|
||||
const BIGNUM * R, *S;
|
||||
ECDSA_SIG_get0(signature, &R, &S);
|
||||
|
||||
QByteArray result;
|
||||
QDataStream stream(&result, QIODevice::WriteOnly);
|
||||
|
||||
stream << bignumToArray(R);
|
||||
stream << bignumToArray(S);
|
||||
|
||||
ECDSA_SIG_free(signature);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ECDSA::checkSign(const QByteArray &inputData,
|
||||
const QByteArray &signature,
|
||||
const QByteArray &key) const {
|
||||
|
||||
|
||||
// extract signature from raw array
|
||||
|
||||
BIGNUM * R, *S;
|
||||
QDataStream stream(signature);
|
||||
|
||||
QByteArray rR,rS;
|
||||
stream >> rR;
|
||||
stream >> rS;
|
||||
R = bignumFromArray(rR);
|
||||
S = bignumFromArray(rS);
|
||||
|
||||
ECDSA_SIG *sig = ECDSA_SIG_new();
|
||||
ECDSA_SIG_set0(sig, R, S);
|
||||
|
||||
auto hash = QCryptographicHash::hash(inputData,
|
||||
QCryptographicHash::Sha256);
|
||||
|
||||
|
||||
EC_KEY *eckey= nullptr;
|
||||
EC_GROUP *ecgroup = nullptr;
|
||||
|
||||
if (!prepareKeyAdnGroupObjects(&eckey, &ecgroup)) {
|
||||
ECDSA_SIG_free(sig);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
// extract key from raw array;
|
||||
EC_POINT* ec_point = EC_POINT_new(ecgroup);
|
||||
EC_POINT_oct2point(ecgroup, ec_point,
|
||||
reinterpret_cast<const unsigned char*>(key.data()),
|
||||
key.length(), nullptr);
|
||||
|
||||
EC_KEY_set_public_key(eckey, ec_point);
|
||||
|
||||
|
||||
int verify_status = ECDSA_do_verify(reinterpret_cast<const unsigned char*>(hash.data()),
|
||||
hash.length(), sig, eckey);
|
||||
|
||||
ECDSA_SIG_free(sig);
|
||||
EC_POINT_free(ec_point);
|
||||
|
||||
return verify_status == 1;
|
||||
|
||||
}
|
||||
|
||||
QByteArray ECDSA::decript(const QByteArray &message, const QByteArray &key) {
|
||||
QuasarAppUtils::Params::log("");
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
QByteArray ECDSA::encript(const QByteArray &message, const QByteArray &key) {
|
||||
return {};
|
||||
}
|
||||
|
||||
bool ECDSA::prepareKeyAdnGroupObjects(EC_KEY **eckey, EC_GROUP **ecgroup) {
|
||||
|
||||
// input data should be valid pointers to pointers of key and group objects.
|
||||
if (!(eckey && ecgroup))
|
||||
return false;
|
||||
|
||||
// input pointers should be nullptr;
|
||||
if ((*eckey) || (*ecgroup))
|
||||
return false;
|
||||
|
||||
auto free = [eckey, ecgroup] () {
|
||||
if (*ecgroup)
|
||||
EC_GROUP_free(*ecgroup);
|
||||
|
||||
if (*eckey)
|
||||
EC_KEY_free(*eckey);
|
||||
};
|
||||
|
||||
*eckey = EC_KEY_new();
|
||||
if (!*eckey) {
|
||||
printlastOpenSSlError();
|
||||
free();
|
||||
return false;
|
||||
}
|
||||
|
||||
*ecgroup = EC_GROUP_new_by_curve_name(NID_secp256k1);
|
||||
|
||||
if (!*ecgroup) {
|
||||
printlastOpenSSlError();
|
||||
free();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EC_KEY_set_group(*eckey, *ecgroup)) {
|
||||
printlastOpenSSlError();
|
||||
free();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
65
Heart/AbstractSpace/hcrypto/ecdsa.h
Normal file
65
Heart/AbstractSpace/hcrypto/ecdsa.h
Normal file
@ -0,0 +1,65 @@
|
||||
//#
|
||||
//# Copyright (C) 2021-2022 QuasarApp.
|
||||
//# Distributed under the GPLv3 software license, see the accompanying
|
||||
//# Everyone is permitted to copy and distribute verbatim copies
|
||||
//# of this license document, but changing it is not allowed.
|
||||
//#
|
||||
|
||||
|
||||
#ifndef QH_ECDSA_H
|
||||
#define QH_ECDSA_H
|
||||
#include "heart_global.h"
|
||||
|
||||
#ifdef USE_HEART_SSL
|
||||
|
||||
|
||||
#include "abstractdata.h"
|
||||
#include "icrypto.h"
|
||||
|
||||
#include <openssl/ec.h> // for EC_GROUP_new_by_curve_name, EC_GROUP_free, EC_KEY_new, EC_KEY_set_group, EC_KEY_generate_key,EC_KEY_free
|
||||
|
||||
namespace QH {
|
||||
|
||||
/**
|
||||
* @brief The ECDSA class is ecdsa implementation of the Async authentication. This implementation based on Openssl library.
|
||||
*/
|
||||
class HEARTSHARED_EXPORT ECDSA: public QH::ICrypto
|
||||
{
|
||||
|
||||
public:
|
||||
ECDSA();
|
||||
|
||||
/**
|
||||
* @brief makeKeys This static method generate the public and private keys of the ECDSA.
|
||||
* @param pubKey This is result public key.
|
||||
* @param privKey This is result private key.
|
||||
* @return true if keys generated successful.
|
||||
*/
|
||||
static bool makeKeys(QByteArray &pubKey, QByteArray &privKey);
|
||||
|
||||
protected:
|
||||
QByteArray signMessage(const QByteArray &inputData, const QByteArray &key) const override;
|
||||
bool checkSign(const QByteArray &inputData, const QByteArray &signature, const QByteArray &key) const override;
|
||||
|
||||
/**
|
||||
* @brief decript This method has empty implementation.
|
||||
* @return empty array.
|
||||
*/
|
||||
QByteArray decript(const QByteArray &message, const QByteArray &key) override;
|
||||
|
||||
/**
|
||||
* @brief encript This method has empty implementation.
|
||||
* @return empty array.
|
||||
*/
|
||||
QByteArray encript(const QByteArray &message, const QByteArray &key) override;
|
||||
|
||||
private:
|
||||
static bool prepareKeyAdnGroupObjects(EC_KEY **eckey, EC_GROUP **ecgroup);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // QH_ECDSA_H
|
@ -11,8 +11,4 @@
|
||||
|
||||
namespace QH {
|
||||
|
||||
ICrypto::ICrypto() = default;
|
||||
|
||||
ICrypto::~ICrypto() = default;
|
||||
|
||||
}
|
65
Heart/AbstractSpace/hcrypto/icrypto.h
Normal file
65
Heart/AbstractSpace/hcrypto/icrypto.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2022 QuasarApp.
|
||||
* Distributed under the lgplv3 software license, see the accompanying
|
||||
* Everyone is permitted to copy and distribute verbatim copies
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef I_CRYPTO_H
|
||||
#define I_CRYPTO_H
|
||||
|
||||
#include "heart_global.h"
|
||||
#include <QByteArray>
|
||||
|
||||
namespace QH {
|
||||
|
||||
/**
|
||||
* @brief The ICrypto class This is base interface that provide encription functionality.
|
||||
*/
|
||||
class HEARTSHARED_EXPORT ICrypto
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief decript This method decript @a message using @a key.
|
||||
* @param message This is encripted message that should be decripted.
|
||||
* @param key This is key that will be used for decription for the @a message.
|
||||
* @return decripted message or empty string if method not supported or decripted failed.
|
||||
* @see IAsyncEncription::encript
|
||||
*/
|
||||
virtual QByteArray decript(const QByteArray& message, const QByteArray& key) = 0;
|
||||
/**
|
||||
* @brief decript This method encript @a message using @a key.
|
||||
* @param message This is a message that should be decripted.
|
||||
* @param key This is key that will be used for encription for the @a message.
|
||||
* @return decripted message or empty string if method not supported or decripted failed.
|
||||
* @see IAsyncEncription::encript
|
||||
*/
|
||||
virtual QByteArray encript(const QByteArray& message, const QByteArray& key) = 0;
|
||||
|
||||
/**
|
||||
* @brief signMessage This method should be sign the @a message using the @a key.
|
||||
* @param message This is input data that should be signed.
|
||||
* @param key This is a privete key for encription the @a message.
|
||||
* @return signature data array.
|
||||
* @see AsyncKeysAuth::descrupt
|
||||
*/
|
||||
virtual QByteArray signMessage(const QByteArray& message, const QByteArray& key) const = 0;
|
||||
|
||||
/**
|
||||
* @brief checkSign This method should be check signature of the @a message using the @a key.
|
||||
* @param message This is input data that should be decripted.
|
||||
* @param signature This is signature that will be checked for the @a message.
|
||||
* @param key This is a public key for encription the @a inpputData.
|
||||
* @return decripted data array.
|
||||
* @see AsyncKeysAuth::encrypt
|
||||
*/
|
||||
virtual bool checkSign(const QByteArray& message,
|
||||
const QByteArray& signature,
|
||||
const QByteArray& key) const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
#endif // I_CRYPTO_H
|
@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2022 QuasarApp.
|
||||
* Distributed under the lgplv3 software license, see the accompanying
|
||||
* Everyone is permitted to copy and distribute verbatim copies
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ICRYPTO_H
|
||||
#define ICRYPTO_H
|
||||
|
||||
#include <QList>
|
||||
#include <QThread>
|
||||
#include "heart_global.h"
|
||||
#include <QByteArray>
|
||||
#include <QHash>
|
||||
#include <QSet>
|
||||
#define RAND_KEY ""
|
||||
|
||||
class QMutex;
|
||||
|
||||
namespace QH {
|
||||
|
||||
class CryptoPairKeys;
|
||||
|
||||
/**
|
||||
* @brief The ICrypto class provide cryptographic functionality.
|
||||
* This is interface for decoration of KeyStorage classes.
|
||||
*/
|
||||
class HEARTSHARED_EXPORT ICrypto
|
||||
{
|
||||
|
||||
public:
|
||||
ICrypto();
|
||||
virtual ~ICrypto();
|
||||
|
||||
/**
|
||||
* @brief isValid check crypto object is valid.
|
||||
* @return true if the crypto object is valid.
|
||||
*/
|
||||
virtual bool isValid() const = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @brief crypt This method crypt input data using public key.
|
||||
* @param data This is pointer to data array for crypting.
|
||||
* @note data as ben changed after call this method.
|
||||
* @param publicKey This is key for crypting data.
|
||||
* @return true if function finished successful.
|
||||
*/
|
||||
virtual bool crypt(QByteArray *data, const QByteArray& publicKey) = 0;
|
||||
|
||||
/**
|
||||
* @brief decrypt This method decrypt input data.
|
||||
* @param cryptedData This is pointer to data array for decrypting.
|
||||
* @note cryptedData has been changed after call this method.
|
||||
* @param privateKey This is key for decrypting data message
|
||||
* @return true if function finished successful.
|
||||
*/
|
||||
virtual bool decrypt(QByteArray *cryptedData, const QByteArray& privateKey) = 0;
|
||||
|
||||
/**
|
||||
* @brief sign This method sign a input message using privateKey.
|
||||
* @param data This is pointer to data array for signed.
|
||||
* @note data has been changed after call this method.
|
||||
* @param privateKey This is key for sign a message.
|
||||
* @return true if function finished successful.
|
||||
*/
|
||||
virtual bool sign(QByteArray* data, const QByteArray& privateKey) = 0;
|
||||
|
||||
/**
|
||||
* @brief extractSign This method extract sign from signed byteArray.
|
||||
* @param data - signed message.
|
||||
* @return return array of sign.
|
||||
*/
|
||||
virtual QByteArray extractSign(const QByteArray& data) = 0;
|
||||
|
||||
/**
|
||||
* @brief concatSign This method make a concatenation between a message data and a sign of message.
|
||||
* @param data This is message data.
|
||||
* @param sign This is sign of message.
|
||||
* @return signed message.
|
||||
*/
|
||||
virtual QByteArray concatSign(const QByteArray& data, const QByteArray& sign) = 0;
|
||||
|
||||
/**
|
||||
* @brief check This method validation signed message
|
||||
* @param signedData This is array of signed data.
|
||||
* @param publicKey This is public key for validation of message.
|
||||
* @return true if function finished successful and signedData is valid.
|
||||
*/
|
||||
virtual bool check(const QByteArray& signedData, const QByteArray& publicKey) = 0;
|
||||
|
||||
/**
|
||||
* @brief generate This method is generate a new key pair. Default implementation do nothing.
|
||||
* @note Override this method for create of new class with new keys type.
|
||||
* @param genesis This is genesis bytes Array. if is possible add support generate keys pair from genesis data.
|
||||
* @return crypto pair keys.
|
||||
*/
|
||||
virtual CryptoPairKeys generate(const QByteArray& genesis = {}) const = 0;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
#endif // CRYPTO_H
|
@ -1,391 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2022 QuasarApp.
|
||||
* Distributed under the lgplv3 software license, see the accompanying
|
||||
* Everyone is permitted to copy and distribute verbatim copies
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
|
||||
|
||||
#include "cryptopairkeys.h"
|
||||
#include "icrypto.h"
|
||||
#include "keystorage.h"
|
||||
#include <quasarapp.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDataStream>
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QMutex>
|
||||
#include <QStandardPaths>
|
||||
#include "config.h"
|
||||
|
||||
namespace QH {
|
||||
|
||||
#define THE_CLASS(x) QString::fromLatin1(typeid(*x).name())
|
||||
#define VERSION_FILE "version"
|
||||
|
||||
KeyStorage::KeyStorage(ICrypto * cryptoMethod) {
|
||||
_keyPoolSizeMutex = new QMutex();
|
||||
_keysMutex = new QMutex();
|
||||
_taskMutex = new QMutex();
|
||||
|
||||
_cryptoMethod = cryptoMethod;
|
||||
|
||||
assert(_cryptoMethod);
|
||||
}
|
||||
|
||||
KeyStorage::~KeyStorage() {
|
||||
|
||||
stop();
|
||||
waitForThreadFinished(WAIT_TIME);
|
||||
|
||||
if (!saveStorage()) {
|
||||
QuasarAppUtils::Params::log("save keys to storae is failed!",
|
||||
QuasarAppUtils::Error);
|
||||
}
|
||||
|
||||
delete _keyPoolSizeMutex;
|
||||
delete _keysMutex;
|
||||
delete _taskMutex;
|
||||
delete _cryptoMethod;
|
||||
}
|
||||
|
||||
CryptoPairKeys KeyStorage::getNextPair(const QString &accsessKey,
|
||||
const QByteArray& genesis,
|
||||
int timeout) {
|
||||
|
||||
if (!isInited() && genesis == RAND_KEY) {
|
||||
QuasarAppUtils::Params::log("You want get the random crypto keys pair in a not initialized crypto object.",
|
||||
QuasarAppUtils::Error);
|
||||
return CryptoPairKeys{};
|
||||
}
|
||||
|
||||
if (_keyPoolSize <= 0) {
|
||||
return CryptoPairKeys{};
|
||||
}
|
||||
|
||||
if (!genKey(accsessKey, genesis)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
start();
|
||||
|
||||
if (!waitForGeneratekey(accsessKey, timeout)) {
|
||||
return CryptoPairKeys{};
|
||||
}
|
||||
|
||||
QMutexLocker locker(_keysMutex);
|
||||
|
||||
return _keys.value(accsessKey, {});
|
||||
}
|
||||
|
||||
int KeyStorage::getKeyPoolSize() const {
|
||||
return _keyPoolSize;
|
||||
}
|
||||
|
||||
void KeyStorage::setKeyPoolSize(int keyPoolSize) {
|
||||
_keyPoolSizeMutex->lock();
|
||||
_keyPoolSize = keyPoolSize;
|
||||
_keyPoolSizeMutex->unlock();
|
||||
|
||||
start();
|
||||
}
|
||||
|
||||
bool KeyStorage::isValid() const {
|
||||
return isInited();
|
||||
}
|
||||
|
||||
bool KeyStorage::isInited() const {
|
||||
return _inited;
|
||||
}
|
||||
|
||||
bool KeyStorage::crypt(QByteArray *data, const QByteArray &publicKey) {
|
||||
return _cryptoMethod->crypt(data, publicKey);
|
||||
}
|
||||
|
||||
bool KeyStorage::decrypt(QByteArray *cryptedData, const QByteArray &privateKey) {
|
||||
return _cryptoMethod->decrypt(cryptedData, privateKey);
|
||||
}
|
||||
|
||||
bool KeyStorage::sign(QByteArray *data, const QByteArray &privateKey) {
|
||||
return _cryptoMethod->sign(data, privateKey);
|
||||
}
|
||||
|
||||
QByteArray KeyStorage::extractSign(const QByteArray &data) {
|
||||
return _cryptoMethod->extractSign(data);
|
||||
}
|
||||
|
||||
QByteArray KeyStorage::concatSign(const QByteArray &data, const QByteArray &sign) {
|
||||
return _cryptoMethod->concatSign(data, sign);
|
||||
}
|
||||
|
||||
bool KeyStorage::check(const QByteArray &signedData, const QByteArray &publicKey) {
|
||||
return _cryptoMethod->check(signedData, publicKey);
|
||||
}
|
||||
|
||||
void KeyStorage::setGenesisList(const QList<QByteArray>& list) {
|
||||
_keysMutex->lock();
|
||||
for (const auto& i : list) {
|
||||
_keys.insert(i, {});
|
||||
}
|
||||
_keysMutex->unlock();
|
||||
|
||||
start();
|
||||
}
|
||||
|
||||
bool KeyStorage::toStorage(const QString &key) const {
|
||||
|
||||
if (!isValid())
|
||||
return false;
|
||||
|
||||
_keysMutex->lock();
|
||||
CryptoPairKeys value = _keys.value(key);
|
||||
_keysMutex->unlock();
|
||||
|
||||
auto filePath = storageLocation() + "/" + key;
|
||||
|
||||
QFile file(filePath);
|
||||
|
||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
file.setPermissions(QFile::Permission::ReadOwner | QFile::Permission::WriteOwner);
|
||||
|
||||
QDataStream stream(&file);
|
||||
|
||||
stream << value;
|
||||
|
||||
file.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KeyStorage::fromStorage(const QByteArray &key) {
|
||||
auto filePath = storageLocation() + "/" + key;
|
||||
|
||||
QFile file(filePath);
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QDataStream stream(&file);
|
||||
|
||||
CryptoPairKeys value;
|
||||
stream >> value;
|
||||
|
||||
file.close();
|
||||
|
||||
_keys.insert(key, value);
|
||||
|
||||
return value.isValid();
|
||||
}
|
||||
|
||||
void KeyStorage::generateKeysByTasks() {
|
||||
_taskMutex->lock();
|
||||
auto tasks = _generateTasks;
|
||||
_taskMutex->unlock();
|
||||
|
||||
for (auto it = tasks.begin(); it != tasks.end(); ++it) {
|
||||
|
||||
if (_stopGenerator) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& value = _keys.value(it.key());
|
||||
if (!value.isValid()) {
|
||||
|
||||
_keysMutex->lock();
|
||||
|
||||
if (it.value() == RAND_KEY && _randomKeysPool.size()) {
|
||||
_keys[it.key()] = *_randomKeysPool.begin();
|
||||
_randomKeysPool.erase(_randomKeysPool.begin());
|
||||
} else {
|
||||
_keys[it.key()] = _cryptoMethod->generate(it.value());
|
||||
}
|
||||
|
||||
_keysMutex->unlock();
|
||||
|
||||
}
|
||||
|
||||
_taskMutex->lock();
|
||||
_generateTasks.remove(it.key());
|
||||
_taskMutex->unlock();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void KeyStorage::generateRandomKeys() {
|
||||
_keyPoolSizeMutex->lock();
|
||||
int size = _keyPoolSize;
|
||||
_keyPoolSizeMutex->unlock();
|
||||
|
||||
while (size > _randomKeysPool.size()) {
|
||||
|
||||
if ((_stopGenerator))
|
||||
return;
|
||||
|
||||
auto &&keys = _cryptoMethod->generate();
|
||||
|
||||
_keysMutex->lock();
|
||||
_randomKeysPool.insert(keys);
|
||||
_keysMutex->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void KeyStorage::run() {
|
||||
|
||||
if (_stopGenerator) {
|
||||
return;
|
||||
}
|
||||
|
||||
_keyPoolSizeMutex->lock();
|
||||
int keyPoolSize = _keyPoolSize;
|
||||
_keyPoolSizeMutex->unlock();
|
||||
|
||||
while ((_generateTasks.size() || keyPoolSize > _randomKeysPool.size())
|
||||
&& !_stopGenerator) {
|
||||
|
||||
generateKeysByTasks();
|
||||
generateRandomKeys();
|
||||
|
||||
_keyPoolSizeMutex->lock();
|
||||
keyPoolSize = _keyPoolSize;
|
||||
_keyPoolSizeMutex->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void KeyStorage::stop() {
|
||||
_stopGenerator = true;
|
||||
}
|
||||
|
||||
bool KeyStorage::waitForGeneratekey(const QString& key, int timeout) const {
|
||||
return waitFor([this, &key](){return _keys.contains(key);}, timeout);
|
||||
}
|
||||
|
||||
bool KeyStorage::waitForThreadFinished(int timeout) const {
|
||||
return waitFor([this](){return !isRunning();}, timeout);
|
||||
}
|
||||
|
||||
bool KeyStorage::waitFor(const std::function<bool()> &checkFunc, int timeout) const {
|
||||
auto waitFor = timeout + QDateTime::currentMSecsSinceEpoch();
|
||||
while (!checkFunc() && waitFor > QDateTime::currentMSecsSinceEpoch()) {
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
|
||||
return checkFunc();
|
||||
}
|
||||
|
||||
void KeyStorage::loadAllKeysFromStorage() {
|
||||
auto list = QDir(storageLocation()).entryInfoList(QDir::Files | QDir::NoDotAndDotDot);
|
||||
|
||||
for (const auto& file: list ) {
|
||||
if (file.fileName() != VERSION_FILE) {
|
||||
fromStorage(file.fileName().toLatin1());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool KeyStorage::saveStorage() const {
|
||||
|
||||
bool result = true;
|
||||
for (auto it = _keys.begin(); it != _keys.end(); ++it) {
|
||||
result = result && toStorage(it.key());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool KeyStorage::genKey(const QString &accessKey, const QByteArray &genesis) {
|
||||
|
||||
if (accessKey.isEmpty())
|
||||
return false;
|
||||
|
||||
QMutexLocker locker(_taskMutex);
|
||||
_generateTasks.insert(accessKey, genesis);
|
||||
return true;
|
||||
}
|
||||
|
||||
QString KeyStorage::storageLocation() const {
|
||||
return _storageLocation;
|
||||
}
|
||||
|
||||
bool KeyStorage::initStorageLocation(const QString &value) {
|
||||
QFile version(value + "/" + VERSION_FILE);
|
||||
|
||||
if (!QFile::exists(value)) {
|
||||
|
||||
if (!QDir().mkpath(value)) {
|
||||
QuasarAppUtils::Params::log(" fail to create a key storagge. Into "
|
||||
+ value, QuasarAppUtils::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
QFile::setPermissions(value,
|
||||
QFile::Permission::ExeOwner |
|
||||
QFile::Permission::ReadOwner |
|
||||
QFile::Permission::WriteOwner);
|
||||
|
||||
QFile version(value + "/" + VERSION_FILE);
|
||||
|
||||
if (!version.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QDataStream stream(&version);
|
||||
stream << THE_CLASS(_cryptoMethod);
|
||||
version.close();
|
||||
|
||||
} else {
|
||||
|
||||
if (!version.open(QIODevice::ReadOnly)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QDataStream stream(&version);
|
||||
QString versionName;
|
||||
stream >> versionName;
|
||||
version.close();
|
||||
|
||||
if (THE_CLASS(_cryptoMethod) != versionName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_storageLocation = value;
|
||||
|
||||
return _storageLocation.size();
|
||||
|
||||
}
|
||||
|
||||
bool KeyStorage::initDefaultStorageLocation(const QString &dirName) {
|
||||
auto storageLoation =
|
||||
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) +
|
||||
"/" + dirName;
|
||||
|
||||
if (dirName.isEmpty()) {
|
||||
storageLoation += THE_CLASS(_cryptoMethod);
|
||||
}
|
||||
|
||||
storageLoation += "/crypto/";
|
||||
|
||||
if (!initStorageLocation(storageLoation)) {
|
||||
QuasarAppUtils::Params::log("CryptoStorage not inited",
|
||||
QuasarAppUtils::Error);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
loadAllKeysFromStorage();
|
||||
|
||||
return _inited = true;
|
||||
}
|
||||
|
||||
void KeyStorage::clearStorage() const {
|
||||
QDir::root().remove(storageLocation());
|
||||
}
|
||||
|
||||
}
|
@ -1,266 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2022 QuasarApp.
|
||||
* Distributed under the lgplv3 software license, see the accompanying
|
||||
* Everyone is permitted to copy and distribute verbatim copies
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef KEYSTORAGE_H
|
||||
#define KEYSTORAGE_H
|
||||
|
||||
#include <QList>
|
||||
#include <QThread>
|
||||
#include "heart_global.h"
|
||||
#include <QByteArray>
|
||||
#include <QHash>
|
||||
#include <QSet>
|
||||
#include "config.h"
|
||||
|
||||
#define RAND_KEY ""
|
||||
|
||||
class QMutex;
|
||||
|
||||
|
||||
namespace QH {
|
||||
|
||||
class CryptoPairKeys;
|
||||
class ICrypto;
|
||||
/**
|
||||
* @brief The KeyStorage class provide the functionality of control crypto keys (generate, save and write).
|
||||
* The current implementation of the key storage is collected cryptokeys like files in a key storage location.
|
||||
*
|
||||
* Work scheme:
|
||||
*\image html KeyStorage.svg width=800px
|
||||
*/
|
||||
class HEARTSHARED_EXPORT KeyStorage: public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief KeyStorage
|
||||
* @param cryptoMethod This is pointer to any class inherited from ICrypto
|
||||
*/
|
||||
KeyStorage(ICrypto* cryptoMethod);
|
||||
~KeyStorage();
|
||||
|
||||
/**
|
||||
* @brief getNextPair This method take a one pair key from the keys pool or generate a new keys pair if the keys pool is empty.
|
||||
* @warning If key pool is empty then this method frease a current thread for awaiting f neg generated pair key.
|
||||
* @note if the key is not generated within the specified period of time, an invalid copy of the key pair will be returned.
|
||||
* @param accsessKey The byte array for get a accesses to key from storage.
|
||||
* @param genesis Set this params to empty for get random key pair or set the byte array for get a key pair for genesis array.
|
||||
* @param timeout_msec This is timeout in milisecunds. default is WAIT_TIME (30000)
|
||||
* @return pair of keys.
|
||||
*/
|
||||
CryptoPairKeys getNextPair(const QString &accsessKey,
|
||||
const QByteArray &genesis = RAND_KEY,
|
||||
int timeout_msec = WAIT_TIME);
|
||||
|
||||
/**
|
||||
* @brief getKeyPoolSize - This method return size of keyPool.
|
||||
* By default it is 1.
|
||||
* @return value of keys pool size.
|
||||
*/
|
||||
int getKeyPoolSize() const;
|
||||
|
||||
/**
|
||||
* @brief setKeyPoolSize This method return the size of keys pool.
|
||||
* and start new work for generation a new keys.
|
||||
* @param keyPoolSize This is a new size of pool.
|
||||
*/
|
||||
void setKeyPoolSize(int keyPoolSize);
|
||||
|
||||
/**
|
||||
* @brief isValid This method check keysStorage to valid.
|
||||
* @return true if the crypto object is valid.
|
||||
*/
|
||||
virtual bool isValid() const;
|
||||
|
||||
/**
|
||||
* @brief isInited This method returns true if the crypto object was initialized correctly.
|
||||
* @return true if the crypto object was initialized correctly.
|
||||
*/
|
||||
virtual bool isInited() const;
|
||||
|
||||
/**
|
||||
* @brief crypt This method crypted a data message using a publicKey.
|
||||
* @param data This is pointer to data array for crypting.
|
||||
* @note data has ben changed after call this method.
|
||||
* @param publicKey This is key for crypting data.
|
||||
* @return true if function finished successful.
|
||||
*/
|
||||
bool crypt(QByteArray *data, const QByteArray& publicKey);
|
||||
|
||||
/**
|
||||
* @brief decrypt This method decrypt a data message using a privateKey.
|
||||
* @param cryptedData - Pointer to data array for decrypting.
|
||||
* @note cryptedData Has been changed after call this method.
|
||||
* @param privateKey This is private key for decrypting data.
|
||||
* @return true if function finished successful.
|
||||
*/
|
||||
bool decrypt(QByteArray *cryptedData, const QByteArray& privateKey);
|
||||
|
||||
/**
|
||||
* @brief sign This method sign a message using a privateKey.
|
||||
* @param data This is pointer to data array for signed.
|
||||
* @note data has been changed after call this method.
|
||||
* @param privateKey This is key for signing a data message.
|
||||
* @return true if function finished successful.
|
||||
*/
|
||||
bool sign(QByteArray* data, const QByteArray& privateKey);
|
||||
|
||||
/**
|
||||
* @brief extractSign This method extract sign from signed byteArray.
|
||||
* @param data This is a signed message.
|
||||
* @return return array of sign.
|
||||
*/
|
||||
QByteArray extractSign(const QByteArray& data);
|
||||
|
||||
/**
|
||||
* @brief concatSign This method concat a data of message and signs of a message.
|
||||
* @param data This is message data.
|
||||
* @param sign This is a sign of message.
|
||||
* @return signed message.
|
||||
*/
|
||||
QByteArray concatSign(const QByteArray& data, const QByteArray& sign);
|
||||
|
||||
/**
|
||||
* @brief check This method fore validation signed message.
|
||||
* @param signedData This is signed message for checking.
|
||||
* @param publicKey This is public key for validation of message.
|
||||
* @return true if function finished successful and signedData is valid.
|
||||
*/
|
||||
bool check(const QByteArray& signedData, const QByteArray& publicKey);
|
||||
|
||||
/**
|
||||
* @brief setGenesisList - set genesis list for generation key pairs.
|
||||
* After invoke this method for each all items will be generated a keys pair.
|
||||
*/
|
||||
void setGenesisList(const QList<QByteArray> &list);
|
||||
|
||||
/**
|
||||
* @brief storageLocation This method return a path of the storage location.
|
||||
* By default storageLocation is QStandardPaths::DataLocation/KeysStorage
|
||||
* @return path to storage location of crypto keys.
|
||||
*/
|
||||
QString storageLocation() const;
|
||||
|
||||
/**
|
||||
* @brief initStorageLocation This method set a new path for storage location of keys.
|
||||
* @param value This is a new path to storage location.
|
||||
*/
|
||||
bool initStorageLocation(const QString &value);
|
||||
|
||||
/**
|
||||
* @brief initDefaultStorageLocation These is some as initStorageLocation,
|
||||
* but set default path.
|
||||
* @param dirName This is name of storage location. If This parametr weel be empty then
|
||||
* storage location set default direction name. By default is name of crypto class.
|
||||
* By default path of storage is:
|
||||
* \code
|
||||
* QStandardPaths::AppDataLocation/crypto/dirName;
|
||||
* \endcode
|
||||
* @return true if the storage inited successful.
|
||||
*/
|
||||
bool initDefaultStorageLocation(const QString& dirName = "");
|
||||
|
||||
/**
|
||||
* @brief clearStorage - This method clear all storage.
|
||||
*/
|
||||
void clearStorage() const;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief toStorage This method save key into local storage.
|
||||
* @param key This is key data value of keys pair.
|
||||
* @note override this method if you want to change storage location or method of save of keys.
|
||||
* @return true if key saved successful.
|
||||
*/
|
||||
virtual bool toStorage(const QString &key) const;
|
||||
|
||||
/**
|
||||
* @brief fromStorage This method load keys from local storage.
|
||||
* @param key This is key data value of keys pair.
|
||||
* @return true if key pair saved successful.
|
||||
*/
|
||||
virtual bool fromStorage(const QByteArray& key);
|
||||
|
||||
/**
|
||||
* @brief run This method start the key generator on own thread.
|
||||
*/
|
||||
void run() override;
|
||||
|
||||
/**
|
||||
* @brief stop This method stop generate keys.
|
||||
*/
|
||||
void stop();
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief waitForGeneratekey.
|
||||
* @param timeout - maximum time for generation new key. by default = WAIT_TIME (30000)
|
||||
* @return true if key generated successful.
|
||||
*/
|
||||
bool waitForGeneratekey(const QString &key, int timeout = WAIT_TIME) const;
|
||||
|
||||
/**
|
||||
* @brief waitForThreadFinished
|
||||
* @param timeout
|
||||
* @return
|
||||
*/
|
||||
bool waitForThreadFinished(int timeout = WAIT_TIME) const;
|
||||
|
||||
/**
|
||||
* @brief waitFor - Base wait function.
|
||||
* @param checkFunc - This is lambda of check event.
|
||||
* @param timeout - Maximum time line of waiting of event.
|
||||
* @return true if event is checkFunc return true.
|
||||
*/
|
||||
bool waitFor(const std::function<bool()>& checkFunc, int timeout) const;
|
||||
|
||||
/**
|
||||
* @brief loadAllKeysFromStorage
|
||||
*/
|
||||
void loadAllKeysFromStorage();
|
||||
|
||||
/**
|
||||
* @brief saveStorage This method for saved keys in storage.
|
||||
* @return true if all keys has been saved in a storage.
|
||||
*/
|
||||
bool saveStorage() const;
|
||||
|
||||
/**
|
||||
* @brief genKey - this method add a new task for generate keys pair
|
||||
* @param accessKey - the byte array for get access of the keys pair.
|
||||
* @param genesis - The byte array for generate new key.
|
||||
* @note If access key well be empty then this method return false.
|
||||
* @note For generate random key use a RAND_KEY genesis or empty value.
|
||||
* @return true if task of generation a new pair keys added successful else false.
|
||||
*/
|
||||
bool genKey(const QString &accessKey, const QByteArray& genesis = RAND_KEY);
|
||||
|
||||
QHash<QString, CryptoPairKeys> _keys;
|
||||
QSet<CryptoPairKeys> _randomKeysPool;
|
||||
|
||||
QHash<QString, QByteArray> _generateTasks;
|
||||
|
||||
int _keyPoolSize = 1;
|
||||
|
||||
QMutex *_keyPoolSizeMutex = nullptr;
|
||||
QMutex *_keysMutex = nullptr;
|
||||
QMutex *_taskMutex = nullptr;
|
||||
|
||||
QString _storageLocation;
|
||||
|
||||
bool _inited = false;
|
||||
bool _stopGenerator = false;
|
||||
|
||||
ICrypto *_cryptoMethod = nullptr;
|
||||
|
||||
void generateKeysByTasks();
|
||||
void generateRandomKeys();
|
||||
};
|
||||
}
|
||||
#endif // KEYSTORAGE_H
|
@ -36,6 +36,7 @@ if (${HEART_BUILD_LVL} GREATER_EQUAL 0)
|
||||
"AbstractSpace/*.cpp" "AbstractSpace/*.h" "AbstractSpace/*.qrc"
|
||||
"AbstractSpace/packages/*.cpp" "AbstractSpace/packages/*.h" "AbstractSpace/packages/*.qrc"
|
||||
"AbstractSpace/Private/*.cpp" "AbstractSpace/Private/*.h" "AbstractSpace/Private/*.qrc"
|
||||
"AbstractSpace/hcrypto/*.cpp" "AbstractSpace/hcrypto/*.h" "AbstractSpace/hcrypto/*.qrc"
|
||||
|
||||
)
|
||||
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include <websocketcontroller.h>
|
||||
#include <QCoreApplication>
|
||||
#include <ping.h>
|
||||
#include <keystorage.h>
|
||||
#include <basenodeinfo.h>
|
||||
#include <abstractnetworkmember.h>
|
||||
#include <memberpermisionobject.h>
|
||||
|
@ -16,7 +16,7 @@
|
||||
namespace QH {
|
||||
namespace PKG {
|
||||
|
||||
AbstractNetworkMember::AbstractNetworkMember():DBObject("NetworkMembers") {
|
||||
AbstractNetworkMember::AbstractNetworkMember(): {
|
||||
|
||||
}
|
||||
|
||||
@ -32,6 +32,7 @@ AbstractNetworkMember::AbstractNetworkMember(const QString& id):
|
||||
|
||||
bool AbstractNetworkMember::fromSqlRecord(const QSqlRecord &q) {
|
||||
|
||||
setId(q.value("id").toString());
|
||||
setAuthenticationData(q.value("authenticationData").toByteArray());
|
||||
setTrust(q.value("trust").toInt());
|
||||
|
||||
@ -88,6 +89,10 @@ void AbstractNetworkMember::setId(const QString &newId) {
|
||||
_id = newId;
|
||||
}
|
||||
|
||||
QString AbstractNetworkMember::table() const {
|
||||
return "NetworkMembers";
|
||||
}
|
||||
|
||||
int AbstractNetworkMember::trust() const {
|
||||
return _trust;
|
||||
}
|
||||
|
@ -79,6 +79,7 @@ public:
|
||||
*/
|
||||
void setId(const QString &newId);
|
||||
|
||||
QString table() const override;
|
||||
protected:
|
||||
|
||||
// StreamBase interface
|
||||
|
@ -21,19 +21,14 @@
|
||||
namespace QH {
|
||||
namespace PKG {
|
||||
|
||||
DBObject::DBObject(const QString &tableName) {
|
||||
DBObject::DBObject() {
|
||||
DBObject::clear();
|
||||
_table = tableName;
|
||||
}
|
||||
|
||||
DBObject::~DBObject() {
|
||||
|
||||
}
|
||||
|
||||
QString DBObject::tableName() const {
|
||||
return _table;
|
||||
}
|
||||
|
||||
PrepareResult DBObject::prepareSelectQuery(QSqlQuery &q) const {
|
||||
|
||||
auto map = variantMap().keys();
|
||||
@ -244,7 +239,7 @@ bool DBObject::isInsertPrimaryKey() const {
|
||||
}
|
||||
|
||||
DbAddress DBObject::dbAddress() const {
|
||||
return {_table, primaryValue()};
|
||||
return {table(), primaryValue()};
|
||||
}
|
||||
|
||||
DBObject *DBObject::cloneRaw() const {
|
||||
|
@ -102,11 +102,7 @@ class HEARTSHARED_EXPORT DBObject : public AbstractData, public ISubscribableDat
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief DBObject This is default constructor.Before using this class you need set the table name and primary key of this object.
|
||||
* @param tableName This is table name.
|
||||
*/
|
||||
DBObject(const QString& tableName);
|
||||
DBObject();
|
||||
|
||||
~DBObject() override;
|
||||
|
||||
@ -135,12 +131,6 @@ public:
|
||||
*/
|
||||
virtual void clear();
|
||||
|
||||
/**
|
||||
* @brief tableName This method return a table name of the database object.
|
||||
* @return string value if the table name.
|
||||
*/
|
||||
QString tableName() const;
|
||||
|
||||
/**
|
||||
* @brief createDBObject This method should be create a object with the some type as the object called this method.
|
||||
* Example of override:
|
||||
@ -213,7 +203,7 @@ public:
|
||||
QString queryString = "INSERT INTO %0(%1) VALUES (%2) ";
|
||||
|
||||
|
||||
queryString = queryString.arg(tableName());
|
||||
queryString = queryString.arg(table());
|
||||
QString tableInsertHeader = "";
|
||||
QString tableInsertValues = "";
|
||||
|
||||
@ -267,7 +257,7 @@ public:
|
||||
|
||||
QString queryString = "UPDATE %0 SET %1 WHERE %2";
|
||||
|
||||
queryString = queryString.arg(tableName());
|
||||
queryString = queryString.arg(table());
|
||||
QString tableUpdateValues = "";
|
||||
QString tableUpdateRules = QString("%0 = :%0").
|
||||
arg(primaryKey());
|
||||
@ -465,6 +455,12 @@ protected:
|
||||
*/
|
||||
virtual QString primaryValue() const = 0;
|
||||
|
||||
/**
|
||||
* @brief table This method should be return name of the database table that should be contains objects with this type.
|
||||
* @return table name that contains object with this type.
|
||||
*/
|
||||
virtual QString table() const = 0;
|
||||
|
||||
/**
|
||||
* @brief isInsertPrimaryKey This method check primaryKeys type.
|
||||
* If the primary key have a type MemberType::Insert then return true.
|
||||
@ -475,7 +471,6 @@ protected:
|
||||
private:
|
||||
QString getWhereBlock() const;
|
||||
bool _printError = true;
|
||||
QString _table;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -155,7 +155,8 @@ bool SingleClient::removeUser() {
|
||||
|
||||
|
||||
QH::PKG::DeleteObject request;
|
||||
request.copyFrom(&getMember());
|
||||
request.setAddress(getMember().dbAddress());
|
||||
|
||||
if (!sendData(&request, realServerAddress())) {
|
||||
return false;
|
||||
};
|
||||
|
@ -391,7 +391,9 @@ bool SqlDBWriter::selectQuery(const DBObject& requestObject,
|
||||
|
||||
while (q.next()) {
|
||||
if (!newObject->fromSqlRecord(q.record())) {
|
||||
QuasarAppUtils::Params::log("Init sql object error.",
|
||||
QuasarAppUtils::Params::log("Select query finished successful but, "
|
||||
"the fromSqlRecord method return false." +
|
||||
newObject->toString(),
|
||||
QuasarAppUtils::Error);
|
||||
return false;
|
||||
}
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "testutils.h"
|
||||
|
||||
#include <abstractnode.h>
|
||||
#include <keystorage.h>
|
||||
#include <ping.h>
|
||||
|
||||
#define LOCAL_TEST_PORT TEST_PORT + 1
|
||||
|
@ -12,7 +12,6 @@
|
||||
|
||||
#include <databasenode.h>
|
||||
#include <hostaddress.h>
|
||||
#include <keystorage.h>
|
||||
#include <ping.h>
|
||||
|
||||
#define LOCAL_TEST_PORT TEST_PORT + 2
|
||||
|
@ -96,7 +96,7 @@ protected:
|
||||
|
||||
// create request for get all objects from database.
|
||||
QH::PKG::DBObjectsRequest<WorkType> setRequest(
|
||||
testObjec->tableName(), "");
|
||||
testObjec->table(), "");
|
||||
|
||||
auto list = BASE::db()->getObject(setRequest);
|
||||
QVERIFY(list);
|
||||
|
Loading…
x
Reference in New Issue
Block a user