1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
|
package element
import (
"fmt"
"time"
"github.com/mitch000001/go-hbci/domain"
)
const (
// SecurityHolderMessageSender represents the MessageSender as security holder
SecurityHolderMessageSender = "MS"
// SecurityHolderMessageReceiver represents the MessageReceiver as security holder
SecurityHolderMessageReceiver = "MR"
)
// NewRDHSecurityIdentification returns a new SecurityIdentificationDataElement
func NewRDHSecurityIdentification(securityHolder, clientSystemID string) *SecurityIdentificationDataElement {
var holder string
if securityHolder == SecurityHolderMessageSender {
holder = "1"
} else if securityHolder == SecurityHolderMessageReceiver {
holder = "2"
} else {
panic(fmt.Errorf("SecurityHolder must be 'MS' or 'MR'"))
}
s := &SecurityIdentificationDataElement{
SecurityHolder: NewAlphaNumeric(holder, 3),
ClientSystemID: NewIdentification(clientSystemID),
}
s.DataElement = NewDataElementGroup(securityIdentificationDEG, 3, s)
return s
}
// SecurityIdentificationDataElement represents a security method for wire transfer
type SecurityIdentificationDataElement struct {
DataElement
// Bezeichner für Sicherheitspartei
SecurityHolder *AlphaNumericDataElement
CID *BinaryDataElement
ClientSystemID *IdentificationDataElement
}
// UnmarshalHBCI unmarshals value into the DataElement
func (s *SecurityIdentificationDataElement) UnmarshalHBCI(value []byte) error {
elements, err := ExtractElements(value)
if err != nil {
return err
}
if len(elements) < 3 {
return fmt.Errorf("Malformed marshaled value")
}
s.DataElement = NewDataElementGroup(securityIdentificationDEG, 3, s)
if len(elements) > 0 && len(elements[0]) > 0 {
s.SecurityHolder = &AlphaNumericDataElement{}
err = s.SecurityHolder.UnmarshalHBCI(elements[0])
if err != nil {
return err
}
}
if len(elements) > 1 && len(elements[1]) > 0 {
s.CID = &BinaryDataElement{}
err = s.CID.UnmarshalHBCI(elements[1])
if err != nil {
return err
}
}
if len(elements) > 2 && len(elements[2]) > 0 {
s.ClientSystemID = &IdentificationDataElement{}
err = s.ClientSystemID.UnmarshalHBCI(elements[2])
if err != nil {
return err
}
}
return nil
}
// GroupDataElements returns the grouped DataElements
func (s *SecurityIdentificationDataElement) GroupDataElements() []DataElement {
return []DataElement{
s.SecurityHolder,
s.CID,
s.ClientSystemID,
}
}
const (
// SecurityTimestamp defines the type of the SecurityDate
SecurityTimestamp = "STS"
// CertificateRevocationTime defines the type of the SecurityDate
CertificateRevocationTime = "CRT"
)
// NewSecurityDate creates a new SecurityDate for the given type
func NewSecurityDate(dateID string, date time.Time) *SecurityDateDataElement {
var id string
if dateID == SecurityTimestamp {
id = "1"
} else if dateID == CertificateRevocationTime {
id = "6"
} else {
panic(fmt.Errorf("DateIdentifier must be 'STS' or 'CRT'"))
}
s := &SecurityDateDataElement{
DateIdentifier: NewAlphaNumeric(id, 3),
Date: NewDate(date),
Time: NewTime(date),
}
s.DataElement = NewDataElementGroup(securityDateDEG, 3, s)
return s
}
// SecurityDateDataElement represents a date with a context type
type SecurityDateDataElement struct {
DataElement
DateIdentifier *AlphaNumericDataElement
Date *DateDataElement
Time *TimeDataElement
}
// GroupDataElements returns the grouped DataElements
func (s *SecurityDateDataElement) GroupDataElements() []DataElement {
return []DataElement{
s.DateIdentifier,
s.Date,
s.Time,
}
}
// NewDefaultHashAlgorithm creates a default HashAlgorithmDataElement with
// values ready to use for initial dialog comm
func NewDefaultHashAlgorithm() *HashAlgorithmDataElement {
h := &HashAlgorithmDataElement{
Usage: NewAlphaNumeric("1", 3),
Algorithm: NewAlphaNumeric("999", 3),
AlgorithmParamID: NewAlphaNumeric("1", 3),
}
h.DataElement = NewDataElementGroup(hashAlgorithmDEG, 4, h)
return h
}
// HashAlgorithmDataElement defines a hash algorithm
type HashAlgorithmDataElement struct {
DataElement
// "1" for OHA, Owner Hashing
Usage *AlphaNumericDataElement
// "999" for ZZZ (RIPEMD-160)
Algorithm *AlphaNumericDataElement
// "1" for IVC, Initialization value, clear text
AlgorithmParamID *AlphaNumericDataElement
// may not be used in versions 2.20 and below
AlgorithmParamValue *BinaryDataElement
}
// GroupDataElements returns the grouped DataElements
func (h *HashAlgorithmDataElement) GroupDataElements() []DataElement {
return []DataElement{
h.Usage,
h.Algorithm,
h.AlgorithmParamID,
h.AlgorithmParamValue,
}
}
// NewRDHSignatureAlgorithm creates a SignatureAlgorithm ready to use for RDH
func NewRDHSignatureAlgorithm() *SignatureAlgorithmDataElement {
s := &SignatureAlgorithmDataElement{
Usage: NewAlphaNumeric("6", 3),
Algorithm: NewAlphaNumeric("10", 3),
OperationMode: NewAlphaNumeric("16", 3),
}
s.DataElement = NewDataElementGroup(signatureAlgorithmDEG, 3, s)
return s
}
// A SignatureAlgorithmDataElement represents a signature algorithm
type SignatureAlgorithmDataElement struct {
DataElement
// "1" for OSG, Owner Signing
Usage *AlphaNumericDataElement
// "1" for DES (DDV)
// "10" for RSA (RDH)
Algorithm *AlphaNumericDataElement
// "16" for DSMR, Digital Signature Scheme giving Message Recovery: ISO 9796 (RDH)
// "999" for ZZZ (DDV)
OperationMode *AlphaNumericDataElement
}
// GroupDataElements returns the grouped DataElements
func (s *SignatureAlgorithmDataElement) GroupDataElements() []DataElement {
return []DataElement{
s.Usage,
s.Algorithm,
s.OperationMode,
}
}
// NewKeyName creates a new KeyNameDataElement for keyName
func NewKeyName(keyName domain.KeyName) *KeyNameDataElement {
a := &KeyNameDataElement{
Bank: NewBankIdentification(keyName.BankID),
UserID: NewIdentification(keyName.UserID),
KeyType: NewAlphaNumeric(string(keyName.KeyType), 1),
KeyNumber: NewNumber(keyName.KeyNumber, 3),
KeyVersion: NewNumber(keyName.KeyVersion, 3),
}
a.DataElement = NewDataElementGroup(keyNameDEG, 5, a)
return a
}
// KeyNameDataElement represents metadata for keys
type KeyNameDataElement struct {
DataElement
Bank *BankIdentificationDataElement
UserID *IdentificationDataElement
// "S" for Signing key
// "V" for Encryption key
KeyType *AlphaNumericDataElement
KeyNumber *NumberDataElement
KeyVersion *NumberDataElement
}
// Val returns the KeyName as domain.KeyName
func (k *KeyNameDataElement) Val() domain.KeyName {
return domain.KeyName{
BankID: domain.BankID{
CountryCode: k.Bank.CountryCode.Val(),
ID: k.Bank.BankID.Val()},
UserID: k.UserID.Val(),
KeyType: domain.KeyType(k.KeyType.Val()),
KeyNumber: k.KeyNumber.Val(),
KeyVersion: k.KeyVersion.Val(),
}
}
// GroupDataElements returns the grouped DataElements
func (k *KeyNameDataElement) GroupDataElements() []DataElement {
return []DataElement{
k.Bank,
k.UserID,
k.KeyType,
k.KeyNumber,
k.KeyVersion,
}
}
// NewCertificate embodies a certificate into a DataElement
func NewCertificate(typ int, certificate []byte) *CertificateDataElement {
c := &CertificateDataElement{
CertificateType: NewNumber(typ, 1),
Content: NewBinary(certificate, 2048),
}
c.DataElement = NewDataElementGroup(certificateDEG, 2, c)
return c
}
// CertificateDataElement embodies certificate bytes into a DataElement
type CertificateDataElement struct {
DataElement
// "1" for ZKA
// "2" for UN/EDIFACT
// "3" for X.509
CertificateType *NumberDataElement
Content *BinaryDataElement
}
// GroupDataElements returns the grouped DataElements
func (c *CertificateDataElement) GroupDataElements() []DataElement {
return []DataElement{
c.CertificateType,
c.Content,
}
}
|