aap-agent-core 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,92 @@
1
+ # @aap/core
2
+
3
+ Core cryptographic utilities for Agent Attestation Protocol.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @aap/core
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Cryptographic Functions
14
+
15
+ ```javascript
16
+ import { generateKeyPair, sign, verify, generateNonce, derivePublicId } from '@aap/core';
17
+
18
+ // Generate a new key pair
19
+ const { publicKey, privateKey } = generateKeyPair();
20
+
21
+ // Derive public ID
22
+ const publicId = derivePublicId(publicKey);
23
+
24
+ // Sign data
25
+ const signature = sign('Hello, World!', privateKey);
26
+
27
+ // Verify signature
28
+ const isValid = verify('Hello, World!', signature, publicKey);
29
+
30
+ // Generate nonce
31
+ const nonce = generateNonce(); // 32-char hex string
32
+ ```
33
+
34
+ ### Identity Management
35
+
36
+ ```javascript
37
+ import { Identity } from '@aap/core';
38
+
39
+ // Create identity manager
40
+ const identity = new Identity({
41
+ storagePath: '/path/to/identity.json' // optional
42
+ });
43
+
44
+ // Initialize (loads or generates)
45
+ const publicInfo = identity.init();
46
+ console.log(publicInfo.publicId);
47
+
48
+ // Sign with identity
49
+ const signature = identity.sign('data to sign');
50
+
51
+ // Get public info (safe to share)
52
+ const pub = identity.getPublic();
53
+ ```
54
+
55
+ ### Constants
56
+
57
+ ```javascript
58
+ import {
59
+ PROTOCOL_VERSION,
60
+ DEFAULT_CHALLENGE_EXPIRY_MS,
61
+ DEFAULT_MAX_RESPONSE_TIME_MS,
62
+ CHALLENGE_TYPES
63
+ } from '@aap/core';
64
+ ```
65
+
66
+ ## API Reference
67
+
68
+ ### Crypto Functions
69
+
70
+ | Function | Description |
71
+ |----------|-------------|
72
+ | `generateKeyPair()` | Generate secp256k1 key pair |
73
+ | `derivePublicId(publicKey)` | Derive 20-char hex ID from public key |
74
+ | `sign(data, privateKey)` | Sign data, return Base64 signature |
75
+ | `verify(data, signature, publicKey)` | Verify signature |
76
+ | `generateNonce(bytes?)` | Generate random hex nonce |
77
+ | `safeCompare(a, b)` | Timing-safe string comparison |
78
+ | `createProofData({...})` | Create canonical proof JSON |
79
+
80
+ ### Identity Class
81
+
82
+ | Method | Description |
83
+ |--------|-------------|
84
+ | `init()` | Initialize identity (load/generate) |
85
+ | `getPublic()` | Get public identity info |
86
+ | `sign(data)` | Sign data with identity key |
87
+ | `exists()` | Check if identity file exists |
88
+ | `Identity.verify(...)` | Static: verify any signature |
89
+
90
+ ## License
91
+
92
+ MIT
package/crypto.js ADDED
@@ -0,0 +1,130 @@
1
+ /**
2
+ * @aap/core - Cryptographic utilities
3
+ *
4
+ * Core cryptographic functions for Agent Attestation Protocol.
5
+ * Uses secp256k1 (same as Bitcoin/Ethereum) for compatibility.
6
+ */
7
+
8
+ import {
9
+ generateKeyPairSync,
10
+ createSign,
11
+ createVerify,
12
+ createHash,
13
+ randomBytes,
14
+ timingSafeEqual
15
+ } from 'node:crypto';
16
+
17
+ /**
18
+ * Generate a new secp256k1 key pair
19
+ * @returns {Object} { publicKey, privateKey } in PEM format
20
+ */
21
+ export function generateKeyPair() {
22
+ const { publicKey, privateKey } = generateKeyPairSync('ec', {
23
+ namedCurve: 'secp256k1',
24
+ publicKeyEncoding: {
25
+ type: 'spki',
26
+ format: 'pem'
27
+ },
28
+ privateKeyEncoding: {
29
+ type: 'pkcs8',
30
+ format: 'pem'
31
+ }
32
+ });
33
+
34
+ return { publicKey, privateKey };
35
+ }
36
+
37
+ /**
38
+ * Derive a short public ID from a public key
39
+ * @param {string} publicKey - PEM-encoded public key
40
+ * @returns {string} 20-character hex identifier
41
+ */
42
+ export function derivePublicId(publicKey) {
43
+ const hash = createHash('sha256').update(publicKey).digest('hex');
44
+ return hash.slice(0, 20);
45
+ }
46
+
47
+ /**
48
+ * Sign data with a private key
49
+ * @param {string} data - Data to sign
50
+ * @param {string} privateKey - PEM-encoded private key
51
+ * @returns {string} Base64-encoded signature
52
+ */
53
+ export function sign(data, privateKey) {
54
+ const signer = createSign('SHA256');
55
+ signer.update(data);
56
+ signer.end();
57
+ return signer.sign(privateKey, 'base64');
58
+ }
59
+
60
+ /**
61
+ * Verify a signature
62
+ * @param {string} data - Original data
63
+ * @param {string} signature - Base64-encoded signature
64
+ * @param {string} publicKey - PEM-encoded public key
65
+ * @returns {boolean} True if valid
66
+ */
67
+ export function verify(data, signature, publicKey) {
68
+ try {
69
+ const verifier = createVerify('SHA256');
70
+ verifier.update(data);
71
+ verifier.end();
72
+ return verifier.verify(publicKey, signature, 'base64');
73
+ } catch (error) {
74
+ return false;
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Generate a cryptographically secure nonce
80
+ * @param {number} [bytes=16] - Number of random bytes
81
+ * @returns {string} Hex-encoded nonce
82
+ */
83
+ export function generateNonce(bytes = 16) {
84
+ return randomBytes(bytes).toString('hex');
85
+ }
86
+
87
+ /**
88
+ * Timing-safe comparison of two strings
89
+ * Prevents timing attacks on token comparison
90
+ * @param {string} a - First string
91
+ * @param {string} b - Second string
92
+ * @returns {boolean} True if equal
93
+ */
94
+ export function safeCompare(a, b) {
95
+ if (typeof a !== 'string' || typeof b !== 'string') {
96
+ return false;
97
+ }
98
+
99
+ const bufA = Buffer.from(a);
100
+ const bufB = Buffer.from(b);
101
+
102
+ if (bufA.length !== bufB.length) {
103
+ return false;
104
+ }
105
+
106
+ return timingSafeEqual(bufA, bufB);
107
+ }
108
+
109
+ /**
110
+ * Create the canonical proof data object for signing/verification
111
+ * @param {Object} params
112
+ * @param {string} params.nonce - Challenge nonce
113
+ * @param {string} params.solution - Agent's solution
114
+ * @param {string} params.publicId - Agent's public ID
115
+ * @param {number} params.timestamp - Unix timestamp in ms
116
+ * @returns {string} JSON string for signing
117
+ */
118
+ export function createProofData({ nonce, solution, publicId, timestamp }) {
119
+ return JSON.stringify({ nonce, solution, publicId, timestamp });
120
+ }
121
+
122
+ export default {
123
+ generateKeyPair,
124
+ derivePublicId,
125
+ sign,
126
+ verify,
127
+ generateNonce,
128
+ safeCompare,
129
+ createProofData
130
+ };
package/identity.js ADDED
@@ -0,0 +1,144 @@
1
+ /**
2
+ * @aap/core - Identity Management
3
+ *
4
+ * Manages agent identity (key generation, storage, signing).
5
+ */
6
+
7
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
8
+ import { homedir } from 'node:os';
9
+ import { join, dirname } from 'node:path';
10
+ import { generateKeyPair, derivePublicId, sign as cryptoSign, verify as cryptoVerify } from './crypto.js';
11
+
12
+ /**
13
+ * Identity manager class
14
+ */
15
+ export class Identity {
16
+ constructor(options = {}) {
17
+ this.storagePath = options.storagePath || join(homedir(), '.aap', 'identity.json');
18
+ this.identity = null;
19
+ }
20
+
21
+ /**
22
+ * Initialize identity (load existing or generate new)
23
+ * @returns {Object} Public identity info
24
+ */
25
+ init() {
26
+ if (this.identity) {
27
+ return this.getPublic();
28
+ }
29
+
30
+ // Ensure directory exists
31
+ const dir = dirname(this.storagePath);
32
+ if (!existsSync(dir)) {
33
+ mkdirSync(dir, { recursive: true });
34
+ }
35
+
36
+ // Load existing identity
37
+ if (existsSync(this.storagePath)) {
38
+ try {
39
+ const data = readFileSync(this.storagePath, 'utf8');
40
+ this.identity = JSON.parse(data);
41
+ return this.getPublic();
42
+ } catch (error) {
43
+ console.error('[AAP] Failed to load identity:', error.message);
44
+ }
45
+ }
46
+
47
+ // Generate new identity
48
+ const { publicKey, privateKey } = generateKeyPair();
49
+ const publicId = derivePublicId(publicKey);
50
+
51
+ this.identity = {
52
+ publicKey,
53
+ privateKey,
54
+ publicId,
55
+ createdAt: new Date().toISOString(),
56
+ protocol: 'AAP',
57
+ version: '1.0.0'
58
+ };
59
+
60
+ // Save to file with secure permissions
61
+ writeFileSync(this.storagePath, JSON.stringify(this.identity, null, 2), {
62
+ mode: 0o600
63
+ });
64
+
65
+ return this.getPublic();
66
+ }
67
+
68
+ /**
69
+ * Get public identity (safe to share)
70
+ * @returns {Object} Public identity without private key
71
+ */
72
+ getPublic() {
73
+ if (!this.identity) {
74
+ this.init();
75
+ }
76
+
77
+ return {
78
+ publicKey: this.identity.publicKey,
79
+ publicId: this.identity.publicId,
80
+ createdAt: this.identity.createdAt,
81
+ protocol: this.identity.protocol,
82
+ version: this.identity.version
83
+ };
84
+ }
85
+
86
+ /**
87
+ * Sign data with the identity's private key
88
+ * @param {string} data - Data to sign
89
+ * @returns {string} Base64-encoded signature
90
+ */
91
+ sign(data) {
92
+ if (!this.identity) {
93
+ this.init();
94
+ }
95
+ return cryptoSign(data, this.identity.privateKey);
96
+ }
97
+
98
+ /**
99
+ * Verify a signature (static method for verifying others)
100
+ * @param {string} data - Original data
101
+ * @param {string} signature - Signature to verify
102
+ * @param {string} publicKey - Public key of signer
103
+ * @returns {boolean} True if valid
104
+ */
105
+ static verify(data, signature, publicKey) {
106
+ return cryptoVerify(data, signature, publicKey);
107
+ }
108
+
109
+ /**
110
+ * Check if identity exists
111
+ * @returns {boolean}
112
+ */
113
+ exists() {
114
+ return existsSync(this.storagePath);
115
+ }
116
+
117
+ /**
118
+ * Delete identity (for testing)
119
+ */
120
+ delete() {
121
+ if (existsSync(this.storagePath)) {
122
+ const { unlinkSync } = require('node:fs');
123
+ unlinkSync(this.storagePath);
124
+ }
125
+ this.identity = null;
126
+ }
127
+ }
128
+
129
+ // Default instance
130
+ let defaultIdentity = null;
131
+
132
+ /**
133
+ * Get or create the default identity instance
134
+ * @param {Object} [options] - Options for new instance
135
+ * @returns {Identity}
136
+ */
137
+ export function getDefaultIdentity(options) {
138
+ if (!defaultIdentity) {
139
+ defaultIdentity = new Identity(options);
140
+ }
141
+ return defaultIdentity;
142
+ }
143
+
144
+ export default { Identity, getDefaultIdentity };
package/index.js ADDED
@@ -0,0 +1,34 @@
1
+ /**
2
+ * @aap/core
3
+ *
4
+ * Core utilities for Agent Attestation Protocol.
5
+ * Provides cryptographic primitives and identity management.
6
+ */
7
+
8
+ export * from './crypto.js';
9
+ export * from './identity.js';
10
+
11
+ // Re-export defaults
12
+ import crypto from './crypto.js';
13
+ import identity from './identity.js';
14
+
15
+ export { crypto, identity };
16
+
17
+ // Protocol constants
18
+ export const PROTOCOL_VERSION = '1.0.0';
19
+ export const DEFAULT_CHALLENGE_EXPIRY_MS = 30000;
20
+ export const DEFAULT_MAX_RESPONSE_TIME_MS = 1500;
21
+ export const NONCE_BYTES = 16;
22
+
23
+ // Challenge types
24
+ export const CHALLENGE_TYPES = ['poem', 'math', 'reverse', 'wordplay', 'description'];
25
+
26
+ export default {
27
+ ...crypto,
28
+ ...identity,
29
+ PROTOCOL_VERSION,
30
+ DEFAULT_CHALLENGE_EXPIRY_MS,
31
+ DEFAULT_MAX_RESPONSE_TIME_MS,
32
+ NONCE_BYTES,
33
+ CHALLENGE_TYPES
34
+ };
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "aap-agent-core",
3
+ "version": "2.0.0",
4
+ "description": "Core cryptographic utilities for Agent Attestation Protocol",
5
+ "main": "index.js",
6
+ "types": "index.d.ts",
7
+ "type": "module",
8
+ "exports": {
9
+ ".": "./index.js",
10
+ "./identity": "./identity.js",
11
+ "./crypto": "./crypto.js"
12
+ },
13
+ "files": ["*.js", "README.md"],
14
+ "keywords": ["aap", "agent", "attestation", "crypto", "secp256k1", "ai", "verification"],
15
+ "author": "ira-hash",
16
+ "license": "MIT",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "https://github.com/ira-hash/agent-attestation-protocol.git",
20
+ "directory": "packages/core"
21
+ },
22
+ "homepage": "https://github.com/ira-hash/agent-attestation-protocol#readme",
23
+ "bugs": {
24
+ "url": "https://github.com/ira-hash/agent-attestation-protocol/issues"
25
+ },
26
+ "engines": {
27
+ "node": ">=18.0.0"
28
+ }
29
+ }