Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
V
Vereign Client Library
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Code
Vereign Client Library
Commits
1ff7b3c5
Commit
1ff7b3c5
authored
5 years ago
by
Damyan Mitev
Browse files
Options
Downloads
Patches
Plain Diff
add some checks and some cleanup
parent
57ca4538
Branches
Branches containing commit
Tags
Tags containing commit
1 merge request
!56
Resolve "Email integrity check"
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
javascript/src/utilities/emailUtilities.js
+6
-7
6 additions, 7 deletions
javascript/src/utilities/emailUtilities.js
javascript/src/utilities/signingUtilities.js
+102
-47
102 additions, 47 deletions
javascript/src/utilities/signingUtilities.js
with
108 additions
and
54 deletions
javascript/src/utilities/emailUtilities.js
+
6
−
7
View file @
1ff7b3c5
...
...
@@ -61,11 +61,13 @@ export const parseSMIME = smimeString => {
});
}
let
signedData
;
//TODO remove from here, move inside if block
let
certificateChain
;
if
(
signatureBase64
)
{
signedData
=
parseSignedData
(
signatureBase64
);
certificateChain
=
getCertificateChain
(
signedData
);
const
signedData
=
parseSignedData
(
signatureBase64
);
if
(
signedData
)
{
//TODO revise and use signedData's generation of cert chain (per signer)
certificateChain
=
getCertificateChain
(
signedData
);
}
}
const
from
=
splitParticipants
(
getGlobalHeaderValue
(
"
from
"
,
parts
));
...
...
@@ -80,10 +82,7 @@ export const parseSMIME = smimeString => {
html
:
extractHtmlBodyFromString
(
html
),
plain
,
attachments
,
certificateChain
,
signedData
,
//TODO remove
fixedSMIME
:
emailString
,
//TODO remove
parts
//TODO remove
certificateChain
};
resolve
(
message
);
...
...
This diff is collapsed.
Click to expand it.
javascript/src/utilities/signingUtilities.js
+
102
−
47
View file @
1ff7b3c5
...
...
@@ -4,7 +4,11 @@ import {
getTimeLeftInLocalStorage
,
makeid
}
from
"
./appUtility
"
;
import
{
bufferToHexCodes
,
stringToArrayBuffer
}
from
"
pvutils
"
;
import
{
bufferToHexCodes
,
stringToArrayBuffer
,
isEqualBuffer
}
from
"
pvutils
"
;
import
{
fromBER
}
from
"
asn1js
"
;
import
{
ContentInfo
,
SignedData
}
from
"
pkijs
"
;
import
{
algomap
,
rdnmap
}
from
"
../constants/certificates
"
;
...
...
@@ -1020,18 +1024,6 @@ function makeBoundary() {
return
"
W0RyLiBEYW15YW4gTWl0ZXZd--
"
+
makeid
(
len
);
}
function
hexString
(
buffer
)
{
//TODO remove
const
byteArray
=
new
Uint8Array
(
buffer
);
const
hexCodes
=
[...
byteArray
].
map
(
value
=>
{
const
hexCode
=
value
.
toString
(
16
);
const
paddedHexCode
=
hexCode
.
padStart
(
2
,
'
0
'
);
return
paddedHexCode
;
});
return
hexCodes
.
join
(
''
);
}
export
const
parseSignedData
=
signatureBase64
=>
{
try
{
const
certificateDecoded
=
atob
(
signatureBase64
);
...
...
@@ -1042,20 +1034,13 @@ export const parseSignedData = signatureBase64 => {
const
signedData
=
new
SignedData
({
schema
:
contentInfo
.
content
});
return
signedData
;
}
catch
(
e
)
{
console
.
error
(
"
Error parsing signed data
"
,
e
);
return
null
;
//TODO implement proper error handling
console
.
error
(
"
Error parsing signed data
:
"
,
e
);
return
null
;
}
};
export
const
parseCertificates
=
signedData
=>
{
try
{
//TODO remove block
console
.
log
(
"
ParseCerts
"
,
signedData
.
signerInfos
);
console
.
log
(
"
DigestAttrib
"
,
signedData
.
signerInfos
[
0
].
signedAttrs
.
attributes
[
2
]);
const
digest
=
signedData
.
signerInfos
[
0
].
signedAttrs
.
attributes
[
2
].
values
[
0
].
valueBlock
.
valueHex
;
const
digestStr
=
hexString
(
digest
);
console
.
log
(
"
DigestAttrib
"
,
digestStr
);
return
signedData
.
certificates
.
map
((
certificate
,
index
)
=>
{
const
certificateData
=
{
issuer
:
{},
subject
:
{},
validity
:
{}
};
const
serialNumber
=
bufferToHexCodes
(
...
...
@@ -1129,52 +1114,87 @@ export const getCertificateChain = signedData => {
return
certificateChain
;
};
const
isVereignSignature
=
(
signerInfo
,
signerVerificationResult
)
=>
{
const
signerCert
=
signerVerificationResult
.
signerCertificate
;
for
(
const
typeAndValue
of
signerCert
.
subject
.
typesAndValues
)
{
try
{
if
(
typeAndValue
.
type
===
"
2.5.4.10
"
&&
typeAndValue
.
value
.
valueBlock
.
value
===
"
Vereign AG
"
)
{
return
true
;
}
}
catch
(
ignore
)
{}
}
return
false
;
};
export
const
verifySMIME
=
(
smimeString
,
rootCaPem
)
=>
{
return
new
Promise
(
resolve
=>
{
setTimeout
(
async
()
=>
{
const
emailString
=
fixNewLines
(
smimeString
);
const
parts
=
parseMIME
(
emailString
);
//const rawAttachments = getAttachments(emailString, parts);
//const attachments = [];
let
signatureBase64
;
let
signatureBoundary
;
for
(
const
part
of
parts
)
{
let
contentType
=
getHeaderValue
(
"
content-type
"
,
part
);
if
(
contentType
===
null
||
contentType
===
undefined
)
{
if
(
!
contentType
)
{
continue
;
}
contentType
=
contentType
[
0
];
if
(
contentType
.
startsWith
(
SIGNATURE_CONTENT_TYPE
))
{
if
(
contentType
&&
contentType
.
startsWith
(
SIGNATURE_CONTENT_TYPE
))
{
signatureBase64
=
getAttachment
(
emailString
,
part
).
base64
;
signatureBoundary
=
part
.
boundary
;
break
;
}
}
let
verificationResult
=
false
;
let
signedData
;
const
verificationResult
=
{
verified
:
false
,
message
:
""
,
vereignSignatures
:
0
,
nonVereignSignatures
:
0
};
if
(
signatureBase64
)
{
const
dataPart
=
parts
[
0
]
;
if
(
dataPart
.
boundary
!==
signatureBoundary
)
{
throw
new
Error
(
`Invalid SMIME format: wrong boundary on first MIME part`
)
;
}
if
(
!
signatureBase64
)
{
verificationResult
.
message
=
"
Not a signed MIME
"
;
resolve
(
verificationResult
);
return
;
}
const
data
=
emailString
.
slice
(
dataPart
.
indices
.
from
,
dataPart
.
indices
.
to
);
const
dataBuffer
=
stringToArrayBuffer
(
data
);
const
dataPart
=
parts
[
0
];
if
(
dataPart
.
boundary
!==
signatureBoundary
)
{
verificationResult
.
message
=
"
Invalid SMIME format: wrong boundary on first MIME part
"
;
resolve
(
verificationResult
);
return
;
}
const
data
=
emailString
.
slice
(
dataPart
.
indices
.
from
,
dataPart
.
indices
.
to
);
const
dataBuffer
=
stringToArrayBuffer
(
data
);
const
rootCa
=
parseCertificate
(
rootCaPem
);
const
rootCa
=
parseCertificate
(
rootCaPem
);
if
(
rootCa
.
tbs
.
byteLength
===
0
)
{
rootCa
.
tbs
=
rootCa
.
encodeTBS
();
}
const
signedData
=
parseSignedData
(
signatureBase64
);
if
(
!
signedData
)
{
verificationResult
.
message
=
"
Corrupt SMIME signature
"
;
resolve
(
verificationResult
);
return
;
}
signedData
=
parseS
ignedData
(
sign
atureBase64
);
for
(
let
i
=
0
;
i
<
signedData
.
signerInfos
.
length
;
i
++
)
{
console
.
log
(
`Validating message for signer
${
i
}
`
);
const
r
esult
=
await
signedData
.
verify
({
for
(
let
i
=
0
;
i
<
s
ignedData
.
sign
erInfos
.
length
;
i
++
)
{
let
signerResult
;
try
{
signerR
esult
=
await
signedData
.
verify
({
signer
:
i
,
data
:
dataBuffer
,
trustedCerts
:
[
rootCa
],
...
...
@@ -1183,16 +1203,51 @@ export const verifySMIME = (smimeString, rootCaPem) => {
extendedMode
:
true
,
passedWhenNotRevValues
:
false
});
console
.
log
(
`Result for signer
${
i
}
:`
,
result
);
if
(
!
result
)
{
verificationResult
=
false
;
}
catch
(
e
)
{
verificationResult
.
message
=
e
.
message
;
resolve
(
verificationResult
);
return
;
}
const
signerVerified
=
!!
signerResult
.
signatureVerified
&&
!!
signerResult
.
signerCertificateVerified
;
if
(
!
signerVerified
)
{
if
(
signerResult
.
message
)
{
verificationResult
.
message
=
signerResult
.
message
;
}
else
{
verificationResult
.
message
=
"
Message integrity is compromised
"
;
}
resolve
(
verificationResult
);
return
;
}
if
(
isVereignSignature
(
signedData
.
signerInfos
[
i
],
signerResult
))
{
const
signerPath
=
signerResult
.
certificatePath
;
const
signerRoot
=
signerPath
[
signerPath
.
length
-
1
];
if
(
signerRoot
.
tbs
.
byteLength
===
0
)
{
signerRoot
.
tbs
=
signerRoot
.
encodeTBS
();
}
if
(
!
isEqualBuffer
(
signerRoot
.
tbs
,
rootCa
.
tbs
))
{
verificationResult
.
message
=
`Vereign signature
${
i
}
has root certificate, different from Vereign root CA`
;
resolve
(
verificationResult
);
return
;
}
verificationResult
.
vereignSignatures
++
;
}
else
{
verificationResult
.
nonVereignSignatures
++
;
}
}
verificationResult
=
true
;
if
(
signedData
.
signerInfos
.
length
===
0
)
{
verificationResult
.
message
=
"
No signatures found
"
;
}
else
if
(
verificationResult
.
vereignSignatures
===
0
)
{
verificationResult
.
message
=
"
Verified succesfully, but no Vereign signatures found
"
;
}
else
{
verificationResult
.
message
=
"
Verified succesfully
"
;
}
verificationResult
.
verified
=
true
;
resolve
(
verificationResult
);
},
50
);
});
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment