Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
@identity.com/credential-commons
Advanced tools
Warning: this still is a working in progress and is not ready for usage yet. Please feel free to explore the code but don't integrate yet. We expect API changes before the 1st release.
This Javascript Library provides functionality around Verifiable Credentials (VC), a W3C standard. Enables Validators to issue, Credential Wallets to verify, filter and Requesters to verify credentials.
[![npm][npm]][npm-url]
npm i
here: https://github.com/bitwiseshiftleft/sjcl/wiki/Getting-Startedgit clone git@github.com:masonicGIT/sjcl-cli.git
cd sjcl-cli
npm install
node src/index.js decrypt
Credential commons is an open-source library that has its binary package published on NPM.
Projects that depend on credential-commons must install the dependency following this way:
npm install --save @identity.com/credential-commons
All versions follow SemVer (https://semver.org/)
npm run lint
- run an ESLint checknpm run coverage
- run code coverage and generate report in the coverage
foldernpm test
- run all testsnpm run test:watch
- run all tests in watch modenpm run generate-schema
- run the CLI command and generate all schemasThis library depends on some configuration settings to work properly. The configuration is made in three different ways that override each other:
There is an utility on cli folder, the configuration.js, just run it:
node cli/configuration.js
And it will store the file like below:
const CCC = require('credential-commons-js');
const ccc = new CCC({
sipSecurityService: "",
attestationService: "",
clientConfig: {
id: "",
signingKeys: {
hexpub: "",
hexsec: "",
},
},
passphrase: "",
keychain: { prv: "" },
})
If you are not sure how to get those informations, see the tutorial down below.
A "User Collectable Attribute" is a unit of user-related data (attribute or knowledge) with a specific identifier that can be captured from the user normally during mobile app. A Claim once verified can be part of a Credential as Claim with the same identifier.
Just add a new definition entry with the format on the definitions file
Claim definitions are packed inside this library but also are available for public consumption at the Claim Registry to export new defined Claims just run:
npm run export-definitions
Claim(identifier, value, version)
Example
const name = new Claim('claim-cvc:Identity.address-v1', {
street: 'Alameda dos Anjos',
unit: '102',
city: 'Belo Horizonte',
zipCode: '94103345',
state: 'Minas Gerais',
county: 'Sao Bento',
country: 'Brazil',
}, '1');
Or use the shorthand
const name = new Claim.IdentityAddress({
street: 'Alameda dos Anjos',
unit: '102',
city: 'Belo Horizonte',
zipCode: '94103345',
state: 'Minas Gerais',
county: 'Sao Bento',
country: 'Brazil',
});
values can be:
{
"street": "Alameda dos Anjos",
"unit": "102",
"city": "Belo Horizonte",
"zipCode": "94103345",
"state": "Minas Gerais",
"county": "Sao Bento",
"country": "Brazil",
}
{
"attestableValue": "urn:city:508e6c84091b405587f755eb5e0d9dbd15f4f7f69642adc18d2d2d8fe9c93366:Belo Horizonte|urn:country:f53c0e02620611705f5dfab2abe8320679f183f7eaa01b50340b6f0f0579638f:Brazil|urn:county:a9d100b24769843e15d8fff52efc5d15f57150e1c252d99c0ea7f8d6ed740e4a:Sao Bento|urn:state:73d0477e24c5b3498addf6877c52ae5916b7cf9fbcaea2e2d440167e4745fab2:Minas Gerais|urn:street:71cb22a895ee6264ed2f0cc851a9e17c5326f70bfd94e945e319d03f361d47d9:Alameda dos Anjos|urn:unit:887eb71750da1837101eb64c821f0a0a58e7ab3254eeed1b6bf2cec72b7a4174:102|urn:zipCode:dc671959502dfa65de57a0a8176da15437493c37497670445268e286a035bea8:94103345|"
}
JSON String
{
"id": null,
"issuer": "did:ethr:0x1ddcbae835c47c8d9159756c167994931a5f01e8",
"issuanceDate": "2018-09-25T21:51:56.511Z",
"identifier": "cvc:Credential:Address",
"expirationDate": "+132017-07-11T05:51:56.512Z",
"version": "1",
"type": [
"Credential",
"cvc:Credential:Address"
],
"claim": {
"type": {
"address": {
"city": "Belo Horizonte",
"country": "Brazil",
"county": "Sao Bento",
"state": "Minas Gerais",
"street": "Alameda dos Anjos",
"unit": "102",
"zipCode": "94103345"
}
}
},
"proof": {
"type": "CivicMerkleProof2018",
"merkleRoot": "c81c5b22438916f2bd75e2966df989b9302ce65887813dd1661f9f24407c5dfe",
"anchor": {
"subject": {
"pub": "xpub:dummy",
"label": "cvc:Credential:Address",
"data": "c81c5b22438916f2bd75e2966df989b9302ce65887813dd1661f9f24407c5dfe",
"signature": "signed:dummy"
},
"walletId": "none",
"cosigners": [
{
"pub": "xpub:dummy"
},
{
"pub": "xpub:dummy"
}
],
"authority": {
"pub": "xpub:dummy",
"path": "/"
},
"coin": "dummycoin",
"tx": {},
"network": "dummynet",
"type": "permanent",
"civicAsPrimary": false,
"schema": "dummy-20180201",
"value": {}
},
"leaves": [
{
"identifier": "claim-cvc:Identity.address-v1",
"value": "urn:city:508e6c84091b405587f755eb5e0d9dbd15f4f7f69642adc18d2d2d8fe9c93366:Belo Horizonte|urn:country:f53c0e02620611705f5dfab2abe8320679f183f7eaa01b50340b6f0f0579638f:Brazil|urn:county:a9d100b24769843e15d8fff52efc5d15f57150e1c252d99c0ea7f8d6ed740e4a:Sao Bento|urn:state:73d0477e24c5b3498addf6877c52ae5916b7cf9fbcaea2e2d440167e4745fab2:Minas Gerais|urn:street:71cb22a895ee6264ed2f0cc851a9e17c5326f70bfd94e945e319d03f361d47d9:Alameda dos Anjos|urn:unit:887eb71750da1837101eb64c821f0a0a58e7ab3254eeed1b6bf2cec72b7a4174:102|urn:zipCode:dc671959502dfa65de57a0a8176da15437493c37497670445268e286a035bea8:94103345|",
"claimPath": "type.address",
"targetHash": "c1b096d40d2ac94c095ebea67af8d2ffb6788a9d0367ffef0010e0c40dd5157d",
"node": [
{
"right": "f97fe9f193a485120e2eef5ee57132b05d7b9c02c53fcf7617663d99b9b6d482"
},
{
"right": "e0dbcf542838280f07d49c2b7c9a4bf9e681b43fc6a55ff7db1973d17b44c37c"
},
{
"right": "207f569aa16908c29cd1bf590f5e3745d6a433119cf31f024e8c1cbb680d4e41"
},
{
"right": "9a09e4b79ec54507896892ac23d8b5d707786b075ead58a69d51c4376805e9c1"
}
]
},
{
"identifier": "cvc:Meta:issuer",
"value": "urn:issuer:a68ed1b5f92ee8ce1e142b232dcb4ca0e2733f51f9893383e6adc3c53887e2fd:did:ethr:0x1ddcbae835c47c8d9159756c167994931a5f01e8",
"claimPath": "meta.issuer",
"targetHash": "f97fe9f193a485120e2eef5ee57132b05d7b9c02c53fcf7617663d99b9b6d482",
"node": [
{
"left": "c1b096d40d2ac94c095ebea67af8d2ffb6788a9d0367ffef0010e0c40dd5157d"
},
{
"right": "e0dbcf542838280f07d49c2b7c9a4bf9e681b43fc6a55ff7db1973d17b44c37c"
},
{
"right": "207f569aa16908c29cd1bf590f5e3745d6a433119cf31f024e8c1cbb680d4e41"
},
{
"right": "9a09e4b79ec54507896892ac23d8b5d707786b075ead58a69d51c4376805e9c1"
}
]
},
{
"identifier": "cvc:Meta:issuanceDate",
"value": "urn:issuanceDate:c3b9798fe98020b041b4bd20027eee5c2895ff47b3fb0c5a4e8d1d061ae2733d:2018-09-25T21:51:56.511Z",
"claimPath": "meta.issuanceDate",
"targetHash": "d3706f4891c1fbfcfa208e7b662858460a992bc547141ee69f7c778681eeab08",
"node": [
{
"right": "5bb75bfee07b5ed5ead3d96ae21d420ce3f8419c8b2ca287eca358507f834312"
},
{
"left": "9dbba3ce114413f76478581417768af3d2f2e6517513c5257b6c5313824f6e68"
},
{
"right": "207f569aa16908c29cd1bf590f5e3745d6a433119cf31f024e8c1cbb680d4e41"
},
{
"right": "9a09e4b79ec54507896892ac23d8b5d707786b075ead58a69d51c4376805e9c1"
}
]
},
{
"identifier": "cvc:Meta:expirationDate",
"value": "urn:expirationDate:7388ed27d10476f47cd9c68a732a9b9eccfd44598cdcb2f785f5131c33991f5b:+132017-07-11T05:51:56.512Z",
"claimPath": "meta.expirationDate",
"targetHash": "5bb75bfee07b5ed5ead3d96ae21d420ce3f8419c8b2ca287eca358507f834312",
"node": [
{
"left": "d3706f4891c1fbfcfa208e7b662858460a992bc547141ee69f7c778681eeab08"
},
{
"left": "9dbba3ce114413f76478581417768af3d2f2e6517513c5257b6c5313824f6e68"
},
{
"right": "207f569aa16908c29cd1bf590f5e3745d6a433119cf31f024e8c1cbb680d4e41"
},
{
"right": "9a09e4b79ec54507896892ac23d8b5d707786b075ead58a69d51c4376805e9c1"
}
]
}
]
}
}
A Credential with an associated Proof. Every consumer of a verifiable Credentials must be able to verify those independently. Holders of Credentials (aka Mobile Phones) are creating "Verifiable Credentials" for Inspectors (aka Requesters).
Just add a new definition entry with the format on the definitions file
Credentials definitions are packed inside this library but also are available for public consumption at the Credential Registry to export new defined Credentials
npm run export-definitions
To construct a new VC you need first to get instances of all Claim dependencies
const name = new Claim.IdentityName({ first: 'Joao', middle: 'Barbosa', last: 'Santos' });
const dob = new Claim.IdentityDateOfBirth({ day: 20, month: 3, year: 1978 });
const cred = new VC('cvc:cred:Test', 'jest:test', [name, dob]);
To construct a new VC you need first to get instances of all Claim dependencies
const name = new Claim.IdentityName({ first: 'Joao', middle: 'Barbosa', last: 'Santos' });
const dob = new Claim.IdentityDateOfBirth({ day: 20, month: 3, year: 1978 });
const cred = new VC('cvc:cred:Test', 'jest:test', [name, dob]);
cred.requestAnchor().then(() => {
//The original instance is updated
})
To construct a new VC you need first to get instances of all Claim dependencies
const name = new Claim.IdentityName({ first: 'Joao', middle: 'Barbosa', last: 'Santos' });
const dob = new Claim.IdentityDateOfBirth({ day: 20, month: 3, year: 1978 });
const cred = new VC('cvc:cred:Test', 'jest:test', [name, dob]);
cred.updateAnchor().then(() => {
//The original instance is updated
})
{
"id": null,
"issuer": "did:ethr:0x1ddcbae835c47c8d9159756c167994931a5f01e8",
"issuanceDate": "2018-09-25T21:51:56.511Z",
"identifier": "cvc:Credential:Address",
"expirationDate": "+132017-07-11T05:51:56.512Z",
"version": "1",
"type": [
"Credential",
"cvc:Credential:Address"
],
"claim": {
"type": {
"address": {
"city": "Belo Horizonte",
"country": "Brazil",
"county": "Sao Bento",
"state": "Minas Gerais",
"street": "Alameda dos Anjos",
"unit": "102",
"zipCode": "94103345"
}
}
},
"proof": {
"type": "CivicMerkleProof2018",
"merkleRoot": "c81c5b22438916f2bd75e2966df989b9302ce65887813dd1661f9f24407c5dfe",
"anchor": {
"subject": {
"pub": "xpub:dummy",
"label": "cvc:Credential:Address",
"data": "c81c5b22438916f2bd75e2966df989b9302ce65887813dd1661f9f24407c5dfe",
"signature": "signed:dummy"
},
"walletId": "none",
"cosigners": [
{
"pub": "xpub:dummy"
},
{
"pub": "xpub:dummy"
}
],
"authority": {
"pub": "xpub:dummy",
"path": "/"
},
"coin": "dummycoin",
"tx": {},
"network": "dummynet",
"type": "permanent",
"civicAsPrimary": false,
"schema": "dummy-20180201",
"value": {}
},
"leaves": [
{
"identifier": "claim-cvc:Identity.address-v1",
"value": "urn:city:508e6c84091b405587f755eb5e0d9dbd15f4f7f69642adc18d2d2d8fe9c93366:Belo Horizonte|urn:country:f53c0e02620611705f5dfab2abe8320679f183f7eaa01b50340b6f0f0579638f:Brazil|urn:county:a9d100b24769843e15d8fff52efc5d15f57150e1c252d99c0ea7f8d6ed740e4a:Sao Bento|urn:state:73d0477e24c5b3498addf6877c52ae5916b7cf9fbcaea2e2d440167e4745fab2:Minas Gerais|urn:street:71cb22a895ee6264ed2f0cc851a9e17c5326f70bfd94e945e319d03f361d47d9:Alameda dos Anjos|urn:unit:887eb71750da1837101eb64c821f0a0a58e7ab3254eeed1b6bf2cec72b7a4174:102|urn:zipCode:dc671959502dfa65de57a0a8176da15437493c37497670445268e286a035bea8:94103345|",
"claimPath": "type.address",
"targetHash": "c1b096d40d2ac94c095ebea67af8d2ffb6788a9d0367ffef0010e0c40dd5157d",
"node": [
{
"right": "f97fe9f193a485120e2eef5ee57132b05d7b9c02c53fcf7617663d99b9b6d482"
},
{
"right": "e0dbcf542838280f07d49c2b7c9a4bf9e681b43fc6a55ff7db1973d17b44c37c"
},
{
"right": "207f569aa16908c29cd1bf590f5e3745d6a433119cf31f024e8c1cbb680d4e41"
},
{
"right": "9a09e4b79ec54507896892ac23d8b5d707786b075ead58a69d51c4376805e9c1"
}
]
},
{
"identifier": "cvc:Meta:issuer",
"value": "urn:issuer:a68ed1b5f92ee8ce1e142b232dcb4ca0e2733f51f9893383e6adc3c53887e2fd:did:ethr:0x1ddcbae835c47c8d9159756c167994931a5f01e8",
"claimPath": "meta.issuer",
"targetHash": "f97fe9f193a485120e2eef5ee57132b05d7b9c02c53fcf7617663d99b9b6d482",
"node": [
{
"left": "c1b096d40d2ac94c095ebea67af8d2ffb6788a9d0367ffef0010e0c40dd5157d"
},
{
"right": "e0dbcf542838280f07d49c2b7c9a4bf9e681b43fc6a55ff7db1973d17b44c37c"
},
{
"right": "207f569aa16908c29cd1bf590f5e3745d6a433119cf31f024e8c1cbb680d4e41"
},
{
"right": "9a09e4b79ec54507896892ac23d8b5d707786b075ead58a69d51c4376805e9c1"
}
]
},
{
"identifier": "cvc:Meta:issuanceDate",
"value": "urn:issuanceDate:c3b9798fe98020b041b4bd20027eee5c2895ff47b3fb0c5a4e8d1d061ae2733d:2018-09-25T21:51:56.511Z",
"claimPath": "meta.issuanceDate",
"targetHash": "d3706f4891c1fbfcfa208e7b662858460a992bc547141ee69f7c778681eeab08",
"node": [
{
"right": "5bb75bfee07b5ed5ead3d96ae21d420ce3f8419c8b2ca287eca358507f834312"
},
{
"left": "9dbba3ce114413f76478581417768af3d2f2e6517513c5257b6c5313824f6e68"
},
{
"right": "207f569aa16908c29cd1bf590f5e3745d6a433119cf31f024e8c1cbb680d4e41"
},
{
"right": "9a09e4b79ec54507896892ac23d8b5d707786b075ead58a69d51c4376805e9c1"
}
]
},
{
"identifier": "cvc:Meta:expirationDate",
"value": "urn:expirationDate:7388ed27d10476f47cd9c68a732a9b9eccfd44598cdcb2f785f5131c33991f5b:+132017-07-11T05:51:56.512Z",
"claimPath": "meta.expirationDate",
"targetHash": "5bb75bfee07b5ed5ead3d96ae21d420ce3f8419c8b2ca287eca358507f834312",
"node": [
{
"left": "d3706f4891c1fbfcfa208e7b662858460a992bc547141ee69f7c778681eeab08"
},
{
"left": "9dbba3ce114413f76478581417768af3d2f2e6517513c5257b6c5313824f6e68"
},
{
"right": "207f569aa16908c29cd1bf590f5e3745d6a433119cf31f024e8c1cbb680d4e41"
},
{
"right": "9a09e4b79ec54507896892ac23d8b5d707786b075ead58a69d51c4376805e9c1"
}
]
}
]
}
}
To construct a new VC given a JSON, just use the .fromJSON
method:
const credJSon = require('./ACred.json');
const cred = VC.fromJSON(credJSon);
Now you can access any method of a cred
instance, like .updateAnchor()
or .verify()
Remember to check the section about configuration or else this part will fail.
To verify a credential JSON, you can construct a VC using .fromJSON
and call .verify()
method:
const credJSon = require('./ACred.json');
const cred = VC.fromJSON(credJSon);
const verifiedLevel = cred.verify();
The .verify()
method return the hiest level verified, follow the VC.VERIFY_LEVELS
constant:
VERIFY_LEVELS = {
INVALID: -1, // Credential structure and/or signature proofs is not valid, or credential is expired
PROOFS: 0, // Credential structure and/or signature proofs are valid, including the expiry
ANCHOR: 1, // Anchor struture is valid
BLOCKCHAIN: 2, // Attestation was validated on blockchain
};
The json schema generator will get a previous definition and build a sample JSON (with random values).
On top of the sample data and combining the identifier properties it will infer an JSON Schema for validating the data.
A identifier like this:
Example
const name = new Claim('claim-cvc:Identity.name-v1', {
first: 'Joao',
middle: 'Barbosa',
last: 'Santos'
})
Will generate a JSON like this:
{
first: 'Joao',
middle: 'Barbosa',
last: 'Santos'
}
The schema generator will generate an json schema like this:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "claim-cvc:Identity.name-v1.first",
"type": "object",
"properties": {
"first": {
"type": "string"
}
},
"required": [
"first"
],
"additionalProperties": false
}
-We use draft 7 for json schema generation
-Values that can have null, must have type : ['null','string']
or else they fail validation if you only send null or if you send an value
-All simple objects String, Number are required as default
-Accepted json schema keywords on identifiers: pattern, maximum, minimum, exclusiveMinimum, exclusiveMaximum, required
-If an identifier has a pattern it must be an Javascript Regex, the generated value will generate the random value using this
-Additional properties are not enabled by default
The project structure is made like this:
|_ __tests__
|_ __integration__
|_ src
|_ dist
|__ cjs
|__ es
|__ browser
|_ reports
|__ coverage
The released browser version is minified.
The main entry point targets CJS, all legacy code should work with this.
Sip-hosted-api is tested with this and it works right out of the box, without any other configuration.
Browser projects should bundle the dependencies, so we are not bundling it here.
The browser transpiled version only guarantees the profile we want to target and not leave this task to the user, since any other different transpilation, could result in bugs.
But as pointed out before, if the target project is ES6 compliant, the pkg.module will point out to the ES version.
Put this in your webpack config under plugins if you are running an Webpack Node App
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: 'production',
APP_ENV: false
}
})
If you are on a React app add this:
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: false,
APP_ENV: 'browser'
}
})
With that you can check if you're running in a browser or not this way:
if (process.env.APP_ENV === 'browser') {
const doSomething = require('./browser-only-js');
doSomething();
} else {
const somethingServer = require('./server-only-js');
somethingServer();
}
if (process.env.APP_ENV !== 'browser') {
const somethingServer = require('./server-only-js');
somethingServer();
}
Because these environment variables get replaced during the build, Webpack will not include resources that are server-only. You should always do these kinds of things in an easy way, with a simple, direct compare. Uglify will remove all dead code.
Since you used a function before and the function is not evaluated during build, Webpack wasn't able to know what requires it could skip.
(The NODE_ENV-variable should always be set to production in production mode, since many libraries including React use it for optimisations.)
This is used on this library on src/services/config.js
The release process is fully automated and started by Civic members when it's created a tag on Github following the pattern ^release\..*$. E.g.: release.1
.
After the creation of the tag, Circle Ci will trigger a job to:
build source files run unit tests increase version number on package.json create the stable version and tag it. E.g: v0.2.29 remove the release.N tag deploy the binary file to NPM
FAQs
Verifiable Credential and Attestation Library
The npm package @identity.com/credential-commons receives a total of 208 weekly downloads. As such, @identity.com/credential-commons popularity was classified as not popular.
We found that @identity.com/credential-commons demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 13 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.