Security
Security architecture and best practices for GSign.
Security Layers
┌─────────────────────────────────────────┐
│ Client (Browser) │
│ • HTTPS only │
│ • CSP headers │
│ • XSS protection │
└─────────────────┬───────────────────────┘
│
┌─────────────────▼───────────────────────┐
│ NGINX │
│ • SSL/TLS termination │
│ • Rate limiting │
│ • Security headers │
└─────────────────┬───────────────────────┘
│
┌─────────────────▼───────────────────────┐
│ API Gateway │
│ • JWT validation │
│ • API key authentication │
│ • Request validation │
│ • Audit logging │
└─────────────────┬───────────────────────┘
│
┌─────────────────▼───────────────────────┐
│ Service Layer │
│ • Authorization (RBAC) │
│ • Input sanitization │
│ • Business logic validation │
└─────────────────┬───────────────────────┘
│
┌─────────────────▼───────────────────────┐
│ Data Layer │
│ • Encrypted at rest │
│ • Parameterized queries │
│ • Tenant isolation │
└─────────────────────────────────────────┘Authentication
JWT Tokens
go
// Token structure
type Claims struct {
UserID string `json:"user_id"`
OrganizationID string `json:"org_id"`
Role string `json:"role"`
jwt.RegisteredClaims
}
// Token settings
Access Token: 15 minutes
Refresh Token: 7 days
Algorithm: HS256 or RS256Password Security
| Setting | Value |
|---|---|
| Algorithm | bcrypt |
| Cost Factor | 12 |
| Min Length | 8 characters |
| Requirements | Upper, lower, number, special |
API Keys
go
// API key format
gsign_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
gsign_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// Storage
Hashed with SHA-256, stored in databaseAuthorization (RBAC)
Roles
| Role | Permissions |
|---|---|
| Super Admin | All platform operations |
| Org Admin | Organization settings, users, billing |
| Team Admin | Team settings, documents |
| User | Own documents, sign |
| API User | API access only |
Permission Checks
go
// Middleware example
func RequireRole(roles ...string) fiber.Handler {
return func(c *fiber.Ctx) error {
user := c.Locals("user").(User)
for _, role := range roles {
if user.Role == role {
return c.Next()
}
}
return c.Status(403).JSON(...)
}
}Data Protection
Encryption at Rest
| Data Type | Encryption |
|---|---|
| Documents (S3) | AES-256-GCM |
| Database fields | AES-256-GCM |
| Certificates | PKCS#12 + password |
| Backups | GPG encryption |
Encryption in Transit
- TLS 1.2+ required
- Strong cipher suites
- HSTS enabled
- Certificate pinning (mobile)
Security Headers
nginx
# NGINX configuration
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'" always;
add_header Permissions-Policy "geolocation=(), microphone=()" always;Input Validation
API Validation
go
type CreateDocumentRequest struct {
Name string `json:"name" validate:"required,min=1,max=255"`
Tags []string `json:"tags" validate:"max=10,dive,max=50"`
}
func (h *Handler) CreateDocument(c *fiber.Ctx) error {
var req CreateDocumentRequest
if err := c.BodyParser(&req); err != nil {
return c.Status(400).JSON(...)
}
if err := h.validator.Struct(req); err != nil {
return c.Status(422).JSON(...)
}
// ...
}File Upload Validation
| Check | Implementation |
|---|---|
| File type | Magic bytes + extension |
| File size | Max 25MB |
| Malware scan | ClamAV integration |
| PDF validation | pdfcpu validation |
Rate Limiting
go
// Fiber rate limiter
limiter.New(limiter.Config{
Max: 100, // requests
Expiration: time.Hour, // per hour
KeyGenerator: func(c *fiber.Ctx) string {
return c.IP()
},
})| Resource | Limit |
|---|---|
| IP address | 100/hour |
| API key (free) | 100/hour |
| API key (paid) | 1,000/hour |
| Login attempts | 5/15min |
Audit Trail
Logged Events
- User login/logout
- Document upload/download
- Envelope creation/signing
- Certificate operations
- Admin actions
- API access
Audit Record
go
type AuditEvent struct {
UserID string `bson:"user_id"`
Action string `bson:"action"`
ResourceType string `bson:"resource_type"`
ResourceID string `bson:"resource_id"`
IPAddress string `bson:"ip_address"`
UserAgent string `bson:"user_agent"`
Timestamp time.Time `bson:"timestamp"`
Metadata bson.M `bson:"metadata"`
}PKI Security
Certificate Storage
- Private keys encrypted with AES-256
- HSM backend for production
- Key encryption key (KEK) in environment
Signing Process
- User selects certificate
- User enters PIN
- Request sent to HSM
- HSM performs signing
- Signed document returned
- Audit log recorded
Compliance
Standards
| Standard | Status |
|---|---|
| eIDAS | ✅ Compliant |
| ESIGN Act | ✅ Compliant |
| UETA | ✅ Compliant |
| GDPR | ✅ Ready |
| SOC 2 | 🔄 In Progress |
Data Retention
| Data Type | Retention |
|---|---|
| Documents | 7 years (configurable) |
| Audit logs | 7 years |
| Session data | 30 days |
| Deleted accounts | 30 days (then purged) |
Security Checklist
- [x] HTTPS only (HSTS)
- [x] Strong password policy
- [x] JWT with short expiry
- [x] Rate limiting
- [x] Input validation
- [x] SQL injection prevention
- [x] XSS protection
- [x] CSRF protection
- [x] Security headers
- [x] Audit logging
- [x] Encryption at rest
- [x] Encryption in transit
- [x] Tenant isolation
- [ ] Penetration testing
- [ ] Security audit
- [ ] SOC 2 certification