big changes to cheat card app

This commit is contained in:
Andrei Yankovich 2022-04-03 17:54:36 +03:00
parent 7bea1e32c5
commit 332acbdf7b
27 changed files with 529 additions and 2774 deletions

View File

@ -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

View File

@ -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>

View File

@ -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"

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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());
}
}

View File

@ -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

View 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

View 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

View File

@ -11,8 +11,4 @@
namespace QH {
ICrypto::ICrypto() = default;
ICrypto::~ICrypto() = default;
}

View 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

View File

@ -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

View File

@ -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());
}
}

View File

@ -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

View File

@ -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"
)

View File

@ -20,7 +20,6 @@
#include <websocketcontroller.h>
#include <QCoreApplication>
#include <ping.h>
#include <keystorage.h>
#include <basenodeinfo.h>
#include <abstractnetworkmember.h>
#include <memberpermisionobject.h>

View File

@ -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;
}

View File

@ -79,6 +79,7 @@ public:
*/
void setId(const QString &newId);
QString table() const override;
protected:
// StreamBase interface

View File

@ -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 {

View File

@ -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;
};
}
}

View File

@ -155,7 +155,8 @@ bool SingleClient::removeUser() {
QH::PKG::DeleteObject request;
request.copyFrom(&getMember());
request.setAddress(getMember().dbAddress());
if (!sendData(&request, realServerAddress())) {
return false;
};

View File

@ -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;
}

View File

@ -10,7 +10,6 @@
#include "testutils.h"
#include <abstractnode.h>
#include <keystorage.h>
#include <ping.h>
#define LOCAL_TEST_PORT TEST_PORT + 1

View File

@ -12,7 +12,6 @@
#include <databasenode.h>
#include <hostaddress.h>
#include <keystorage.h>
#include <ping.h>
#define LOCAL_TEST_PORT TEST_PORT + 2

View File

@ -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);