package jess import ( "errors" "fmt" "regexp" "strings" ) // Keywords and Prefixes for the export text format. const ( ExportSenderKeyword = "sender" ExportSenderPrefix = "sender:" ExportRecipientKeyword = "recipient" ExportRecipientPrefix = "recipient:" ExportKeyKeyword = "secret" ExportKeyPrefix = "secret:" ExportEnvelopeKeyword = "envelope" ExportEnvelopePrefix = "envelope:" ) // Export exports the public part of a signet in text format. func (signet *Signet) Export(short bool) (textFormat string, err error) { // Make public if needed. if !signet.Public { signet, err = signet.AsRecipient() if err != nil { return "", err } } // Transform to text format. return signet.toTextFormat(short) } // Backup exports the private part of a signet in text format. func (signet *Signet) Backup(short bool) (textFormat string, err error) { // Abprt if public. if signet.Public { return "", errors.New("cannot backup (only export) a recipient") } // Transform to text format. return signet.toTextFormat(short) } func (signet *Signet) toTextFormat(short bool) (textFormat string, err error) { // Serialize to base58. base58data, err := signet.ToBase58() if err != nil { return "", err } // Define keywords. var keyword, typeComment string switch { case signet.Scheme == SignetSchemePassword: return "", errors.New("cannot backup or export passwords") case signet.Scheme == SignetSchemeKey: // Check if the signet is marked as "public". if signet.Public { return "", errors.New("cannot export keys") } keyword = ExportKeyKeyword typeComment = "symmetric-key" case signet.Public: keyword = ExportRecipientKeyword typeComment = fmt.Sprintf( "public-%s-key", toTextFormatString(signet.Scheme), ) default: keyword = ExportSenderKeyword typeComment = fmt.Sprintf( "private-%s-key", toTextFormatString(signet.Scheme), ) } // Transform to text format. if short { return fmt.Sprintf( "%s:%s", keyword, base58data, ), nil } return fmt.Sprintf( "%s:%s:%s:%s", keyword, typeComment, toTextFormatString(signet.Info.Name), base58data, ), nil } // Export exports the envelope in text format. func (e *Envelope) Export(short bool) (textFormat string, err error) { // Remove and key data. e.CleanSignets() // Serialize to base58. base58data, err := e.ToBase58() if err != nil { return "", err } // Transform to text format. if short { return fmt.Sprintf( "%s:%s", ExportEnvelopeKeyword, base58data, ), nil } return fmt.Sprintf( "%s:%s:%s:%s", ExportEnvelopeKeyword, e.SuiteID, e.Name, base58data, ), nil } // KeyFromTextFormat loads a secret key from the text format. func KeyFromTextFormat(textFormat string) (*Signet, error) { // Check the identifier. if !strings.HasPrefix(textFormat, ExportKeyPrefix) { return nil, errors.New("not a secret") } // Parse the data section. splitted := strings.Split(textFormat, ":") if len(splitted) < 2 { return nil, errors.New("invalid format") } return SignetFromBase58(splitted[len(splitted)-1]) } // SenderFromTextFormat loads a sender (private key) from the text format. func SenderFromTextFormat(textFormat string) (*Signet, error) { // Check the identifier. if !strings.HasPrefix(textFormat, ExportSenderPrefix) { return nil, errors.New("not a sender") } // Parse the data section. splitted := strings.Split(textFormat, ":") if len(splitted) < 2 { return nil, errors.New("invalid format") } return SignetFromBase58(splitted[len(splitted)-1]) } // RecipientFromTextFormat loads a recipient (public key) from the text format. func RecipientFromTextFormat(textFormat string) (*Signet, error) { // Check the identifier. if !strings.HasPrefix(textFormat, ExportRecipientPrefix) { return nil, errors.New("not a recipient") } // Parse the data section. splitted := strings.Split(textFormat, ":") if len(splitted) < 2 { return nil, errors.New("invalid format") } return SignetFromBase58(splitted[len(splitted)-1]) } // EnvelopeFromTextFormat loads an envelope from the text format. func EnvelopeFromTextFormat(textFormat string) (*Envelope, error) { // Check the identifier. if !strings.HasPrefix(textFormat, ExportEnvelopePrefix) { return nil, errors.New("not an envelope") } // Parse the data section. splitted := strings.Split(textFormat, ":") if len(splitted) < 2 { return nil, errors.New("invalid format") } return EnvelopeFromBase58(splitted[len(splitted)-1]) } var replaceForTextFormatMatcher = regexp.MustCompile(`[^A-Za-z0-9]+`) // toTextFormatString makes a string compatible with the text format. func toTextFormatString(s string) string { return strings.ToLower( strings.Trim( replaceForTextFormatMatcher.ReplaceAllString(s, "-"), "-", ), ) }