github.com/algorand/go-algorand-sdk@v1.24.0/crypto/crypto.go (about) 1 package crypto 2 3 import ( 4 "bytes" 5 "crypto/rand" 6 "crypto/sha256" 7 "crypto/sha512" 8 "encoding/base32" 9 "encoding/base64" 10 "encoding/binary" 11 "fmt" 12 13 "golang.org/x/crypto/ed25519" 14 15 "github.com/algorand/go-algorand-sdk/encoding/msgpack" 16 "github.com/algorand/go-algorand-sdk/types" 17 ) 18 19 // txidPrefix is prepended to a transaction when computing its txid 20 var txidPrefix = []byte("TX") 21 22 // tgidPrefix is prepended to a transaction group when computing the group ID 23 var tgidPrefix = []byte("TG") 24 25 // bidPrefix is prepended to a bid when signing it 26 var bidPrefix = []byte("aB") 27 28 // bytesPrefix is prepended to a message when signing 29 var bytesPrefix = []byte("MX") 30 31 // programPrefix is prepended to a logic program when computing a hash 32 var programPrefix = []byte("Program") 33 34 // programDataPrefix is prepended to teal sign data 35 var programDataPrefix = []byte("ProgData") 36 37 // appIDPrefix is prepended to application IDs in order to compute addresses 38 var appIDPrefix = []byte("appID") 39 40 // StateProofMessagePrefix is prepended to the canonical msgpack encoded state proof message when computing its hash. 41 var StateProofMessagePrefix = []byte("spm") 42 43 // LightBlockHeaderPrefix is prepended to the canonical msgpack encoded light block header when computing its vector commitment leaf. 44 var LightBlockHeaderPrefix = []byte("B256") 45 46 // RandomBytes fills the passed slice with randomness, and panics if it is 47 // unable to do so 48 func RandomBytes(s []byte) { 49 _, err := rand.Read(s) 50 if err != nil { 51 panic(err) 52 } 53 } 54 55 // GenerateAddressFromSK take a secret key and returns the corresponding Address 56 func GenerateAddressFromSK(sk []byte) (types.Address, error) { 57 edsk := ed25519.PrivateKey(sk) 58 59 var a types.Address 60 pk := edsk.Public() 61 n := copy(a[:], []byte(pk.(ed25519.PublicKey))) 62 if n != ed25519.PublicKeySize { 63 return [32]byte{}, fmt.Errorf("generated public key has the wrong size, expected %d, got %d", ed25519.PublicKeySize, n) 64 } 65 return a, nil 66 } 67 68 func GetTxID(tx types.Transaction) string { 69 rawTx := rawTransactionBytesToSign(tx) 70 return txIDFromRawTxnBytesToSign(rawTx) 71 } 72 73 // SignTransaction accepts a private key and a transaction, and returns the 74 // bytes of a signed transaction ready to be broadcasted to the network 75 // If the SK's corresponding address is different than the txn sender's, the SK's 76 // corresponding address will be assigned as AuthAddr 77 func SignTransaction(sk ed25519.PrivateKey, tx types.Transaction) (txid string, stxBytes []byte, err error) { 78 s, txid, err := rawSignTransaction(sk, tx) 79 if err != nil { 80 return 81 } 82 // Construct the SignedTxn 83 stx := types.SignedTxn{ 84 Sig: s, 85 Txn: tx, 86 } 87 88 a, err := GenerateAddressFromSK(sk) 89 if err != nil { 90 return 91 } 92 93 if stx.Txn.Sender != a { 94 stx.AuthAddr = a 95 } 96 97 // Encode the SignedTxn 98 stxBytes = msgpack.Encode(stx) 99 return 100 } 101 102 // rawTransactionBytesToSign returns the byte form of the tx that we actually sign 103 // and compute txID from. 104 func rawTransactionBytesToSign(tx types.Transaction) []byte { 105 // Encode the transaction as msgpack 106 encodedTx := msgpack.Encode(tx) 107 108 // Prepend the hashable prefix 109 msgParts := [][]byte{txidPrefix, encodedTx} 110 return bytes.Join(msgParts, nil) 111 } 112 113 // txID computes a transaction id base32 string from raw transaction bytes 114 func txIDFromRawTxnBytesToSign(toBeSigned []byte) (txid string) { 115 txidBytes := sha512.Sum512_256(toBeSigned) 116 txid = base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(txidBytes[:]) 117 return 118 } 119 120 // txIDFromTransaction is a convenience function for generating txID from txn 121 func txIDFromTransaction(tx types.Transaction) (txid string) { 122 txidBytes := TransactionID(tx) 123 txid = base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(txidBytes[:]) 124 return 125 } 126 127 // TransactionID is the unique identifier for a Transaction in progress 128 func TransactionID(tx types.Transaction) (txid []byte) { 129 toBeSigned := rawTransactionBytesToSign(tx) 130 txid32 := sha512.Sum512_256(toBeSigned) 131 txid = txid32[:] 132 return 133 } 134 135 // TransactionIDString is a base32 representation of a TransactionID 136 func TransactionIDString(tx types.Transaction) (txid string) { 137 txid = base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(TransactionID(tx)) 138 return 139 } 140 141 // rawSignTransaction signs the msgpack-encoded tx (with prepended "TX" prefix), and returns the sig and txid 142 func rawSignTransaction(sk ed25519.PrivateKey, tx types.Transaction) (s types.Signature, txid string, err error) { 143 toBeSigned := rawTransactionBytesToSign(tx) 144 145 // Sign the encoded transaction 146 signature := ed25519.Sign(sk, toBeSigned) 147 148 // Copy the resulting signature into a Signature, and check that it's 149 // the expected length 150 n := copy(s[:], signature) 151 if n != len(s) { 152 err = errInvalidSignatureReturned 153 return 154 } 155 // Populate txID 156 txid = txIDFromRawTxnBytesToSign(toBeSigned) 157 return 158 } 159 160 // SignBytes signs the bytes and returns the signature 161 func SignBytes(sk ed25519.PrivateKey, bytesToSign []byte) (signature []byte, err error) { 162 // prepend the prefix for signing bytes 163 toBeSigned := bytes.Join([][]byte{bytesPrefix, bytesToSign}, nil) 164 165 // sign the bytes 166 signature = ed25519.Sign(sk, toBeSigned) 167 return 168 } 169 170 // VerifyBytes verifies that the signature is valid 171 func VerifyBytes(pk ed25519.PublicKey, message, signature []byte) bool { 172 msgParts := [][]byte{bytesPrefix, message} 173 toBeVerified := bytes.Join(msgParts, nil) 174 return ed25519.Verify(pk, toBeVerified, signature) 175 } 176 177 // SignBid accepts a private key and a bid, and returns the signature of the 178 // bid under that key 179 func SignBid(sk ed25519.PrivateKey, bid types.Bid) (signedBid []byte, err error) { 180 // Encode the bid as msgpack 181 encodedBid := msgpack.Encode(bid) 182 183 // Prepend the hashable prefix 184 msgParts := [][]byte{bidPrefix, encodedBid} 185 toBeSigned := bytes.Join(msgParts, nil) 186 187 // Sign the encoded bid 188 sig := ed25519.Sign(sk, toBeSigned) 189 190 var s types.Signature 191 n := copy(s[:], sig) 192 if n != len(s) { 193 err = errInvalidSignatureReturned 194 return 195 } 196 197 sb := types.SignedBid{ 198 Bid: bid, 199 Sig: s, 200 } 201 202 nf := types.NoteField{ 203 Type: types.NoteBid, 204 SignedBid: sb, 205 } 206 207 signedBid = msgpack.Encode(nf) 208 return 209 } 210 211 /* Multisig Support */ 212 213 type signer func() (signature types.Signature, err error) 214 215 // Service function to make a single signature in Multisig 216 func multisigSingle(sk ed25519.PrivateKey, ma MultisigAccount, customSigner signer) (msig types.MultisigSig, myIndex int, err error) { 217 // check that sk.pk exists in the list of public keys in MultisigAccount ma 218 myIndex = len(ma.Pks) 219 myPublicKey := sk.Public().(ed25519.PublicKey) 220 for i := 0; i < len(ma.Pks); i++ { 221 if bytes.Equal(myPublicKey, ma.Pks[i]) { 222 myIndex = i 223 } 224 } 225 if myIndex == len(ma.Pks) { 226 err = errMsigInvalidSecretKey 227 return 228 } 229 230 // now, create the signed transaction 231 msig.Version = ma.Version 232 msig.Threshold = ma.Threshold 233 msig.Subsigs = make([]types.MultisigSubsig, len(ma.Pks)) 234 for i := 0; i < len(ma.Pks); i++ { 235 c := make([]byte, len(ma.Pks[i])) 236 copy(c, ma.Pks[i]) 237 msig.Subsigs[i].Key = c 238 } 239 rawSig, err := customSigner() 240 if err != nil { 241 return 242 } 243 msig.Subsigs[myIndex].Sig = rawSig 244 return 245 } 246 247 // SignMultisigTransaction signs the given transaction, and multisig preimage, with the 248 // private key, returning the bytes of a signed transaction with the multisig field 249 // partially populated, ready to be passed to other multisig signers to sign or broadcast. 250 func SignMultisigTransaction(sk ed25519.PrivateKey, ma MultisigAccount, tx types.Transaction) (txid string, stxBytes []byte, err error) { 251 err = ma.Validate() 252 if err != nil { 253 return 254 } 255 256 // this signer signs a transaction and sets txid from the closure 257 customSigner := func() (rawSig types.Signature, err error) { 258 rawSig, txid, err = rawSignTransaction(sk, tx) 259 return rawSig, err 260 } 261 262 sig, _, err := multisigSingle(sk, ma, customSigner) 263 if err != nil { 264 return 265 } 266 267 // Encode the signedTxn 268 stx := types.SignedTxn{ 269 Msig: sig, 270 Txn: tx, 271 } 272 273 maAddress, err := ma.Address() 274 if err != nil { 275 return 276 } 277 278 if stx.Txn.Sender != maAddress { 279 stx.AuthAddr = maAddress 280 } 281 282 stxBytes = msgpack.Encode(stx) 283 return 284 } 285 286 // MergeMultisigTransactions merges the given (partially) signed multisig transactions, and 287 // returns an encoded signed multisig transaction with the component signatures. 288 func MergeMultisigTransactions(stxsBytes ...[]byte) (txid string, stxBytes []byte, err error) { 289 if len(stxsBytes) < 2 { 290 err = errMsigMergeLessThanTwo 291 return 292 } 293 var sig types.MultisigSig 294 var refAddr *types.Address 295 var refTx types.Transaction 296 var refAuthAddr types.Address 297 for _, partStxBytes := range stxsBytes { 298 partStx := types.SignedTxn{} 299 err = msgpack.Decode(partStxBytes, &partStx) 300 if err != nil { 301 return 302 } 303 // check that multisig parameters match 304 partMa, innerErr := MultisigAccountFromSig(partStx.Msig) 305 if innerErr != nil { 306 err = innerErr 307 return 308 } 309 partAddr, innerErr := partMa.Address() 310 if innerErr != nil { 311 err = innerErr 312 return 313 } 314 if refAddr == nil { 315 refAddr = &partAddr 316 // add parameters to new merged txn 317 sig.Version = partStx.Msig.Version 318 sig.Threshold = partStx.Msig.Threshold 319 sig.Subsigs = make([]types.MultisigSubsig, len(partStx.Msig.Subsigs)) 320 for i := 0; i < len(sig.Subsigs); i++ { 321 c := make([]byte, len(partStx.Msig.Subsigs[i].Key)) 322 copy(c, partStx.Msig.Subsigs[i].Key) 323 sig.Subsigs[i].Key = c 324 } 325 refTx = partStx.Txn 326 refAuthAddr = partStx.AuthAddr 327 } 328 329 if partAddr != *refAddr { 330 err = errMsigMergeKeysMismatch 331 return 332 } 333 334 if partStx.AuthAddr != refAuthAddr { 335 err = errMsigMergeAuthAddrMismatch 336 return 337 } 338 339 // now, add subsignatures appropriately 340 zeroSig := types.Signature{} 341 for i := 0; i < len(sig.Subsigs); i++ { 342 mSubsig := partStx.Msig.Subsigs[i] 343 if mSubsig.Sig != zeroSig { 344 if sig.Subsigs[i].Sig == zeroSig { 345 sig.Subsigs[i].Sig = mSubsig.Sig 346 } else if sig.Subsigs[i].Sig != mSubsig.Sig { 347 err = errMsigMergeInvalidDups 348 return 349 } 350 } 351 } 352 } 353 // Encode the signedTxn 354 stx := types.SignedTxn{ 355 Msig: sig, 356 Txn: refTx, 357 AuthAddr: refAuthAddr, 358 } 359 stxBytes = msgpack.Encode(stx) 360 // let's also compute the txid. 361 txid = txIDFromTransaction(refTx) 362 return 363 } 364 365 // AppendMultisigTransaction appends the signature corresponding to the given private key, 366 // returning an encoded signed multisig transaction including the signature. 367 // While we could compute the multisig preimage from the multisig blob, we ask the caller 368 // to pass it back in, to explicitly check that they know who they are signing as. 369 func AppendMultisigTransaction(sk ed25519.PrivateKey, ma MultisigAccount, preStxBytes []byte) (txid string, stxBytes []byte, err error) { 370 preStx := types.SignedTxn{} 371 err = msgpack.Decode(preStxBytes, &preStx) 372 if err != nil { 373 return 374 } 375 _, partStxBytes, err := SignMultisigTransaction(sk, ma, preStx.Txn) 376 if err != nil { 377 return 378 } 379 txid, stxBytes, err = MergeMultisigTransactions(partStxBytes, preStxBytes) 380 return 381 } 382 383 // VerifyMultisig verifies an assembled MultisigSig 384 // 385 // addr is the address of the Multisig account 386 // message is the bytes there were signed 387 // msig is the Multisig signature to verify 388 func VerifyMultisig(addr types.Address, message []byte, msig types.MultisigSig) bool { 389 msigAccount, err := MultisigAccountFromSig(msig) 390 if err != nil { 391 return false 392 } 393 394 if msigAddress, err := msigAccount.Address(); err != nil || msigAddress != addr { 395 return false 396 } 397 398 // check that we don't have too many multisig subsigs 399 if len(msig.Subsigs) > 255 { 400 return false 401 } 402 403 // check that we don't have too few multisig subsigs 404 if len(msig.Subsigs) < int(msig.Threshold) { 405 return false 406 } 407 408 // checks the number of non-blank signatures is no less than threshold 409 var counter int 410 for _, subsigi := range msig.Subsigs { 411 if (subsigi.Sig != types.Signature{}) { 412 counter++ 413 } 414 } 415 if counter < int(msig.Threshold) { 416 return false 417 } 418 419 // checks individual signature verifies 420 var verifiedCount uint8 421 for _, subsigi := range msig.Subsigs { 422 if (subsigi.Sig != types.Signature{}) { 423 if !ed25519.Verify(subsigi.Key, message, subsigi.Sig[:]) { 424 return false 425 } 426 verifiedCount++ 427 } 428 } 429 430 if verifiedCount < msig.Threshold { 431 return false 432 } 433 434 return true 435 } 436 437 // ComputeGroupID returns group ID for a group of transactions 438 func ComputeGroupID(txgroup []types.Transaction) (gid types.Digest, err error) { 439 if len(txgroup) > types.MaxTxGroupSize { 440 err = fmt.Errorf("txgroup too large, %v > max size %v", len(txgroup), types.MaxTxGroupSize) 441 return 442 } 443 var group types.TxGroup 444 empty := types.Digest{} 445 for _, tx := range txgroup { 446 if tx.Group != empty { 447 err = fmt.Errorf("transaction %v already has a group %v", tx, tx.Group) 448 return 449 } 450 451 txID := sha512.Sum512_256(rawTransactionBytesToSign(tx)) 452 group.TxGroupHashes = append(group.TxGroupHashes, txID) 453 } 454 455 encoded := msgpack.Encode(group) 456 457 // Prepend the hashable prefix and hash it 458 msgParts := [][]byte{tgidPrefix, encoded} 459 return sha512.Sum512_256(bytes.Join(msgParts, nil)), nil 460 } 461 462 /* LogicSig support */ 463 464 func isAsciiPrintableByte(symbol byte) bool { 465 isBreakLine := symbol == '\n' 466 isStdPrintable := symbol >= ' ' && symbol <= '~' 467 return isBreakLine || isStdPrintable 468 } 469 470 func isAsciiPrintable(program []byte) bool { 471 for _, b := range program { 472 if !isAsciiPrintableByte(b) { 473 return false 474 } 475 } 476 return true 477 } 478 479 // sanityCheckProgram performs heuristic program validation: 480 // check if passed in bytes are Algorand address or is B64 encoded, rather than Teal bytes 481 func sanityCheckProgram(program []byte) error { 482 if len(program) == 0 { 483 return fmt.Errorf("empty program") 484 } 485 if isAsciiPrintable(program) { 486 if _, err := types.DecodeAddress(string(program)); err == nil { 487 return fmt.Errorf("requesting program bytes, get Algorand address") 488 } 489 if _, err := base64.StdEncoding.DecodeString(string(program)); err == nil { 490 return fmt.Errorf("program should not be b64 encoded") 491 } 492 return fmt.Errorf("program bytes are all ASCII printable characters, not looking like Teal byte code") 493 } 494 return nil 495 } 496 497 // VerifyLogicSig verifies that a LogicSig contains a valid program and, if a 498 // delegated signature is present, that the signature is valid. 499 // 500 // The singleSigner argument is only used in the case of a delegated LogicSig 501 // whose delegating account is backed by a single private key (i.e. not a 502 // multsig account). In that case, it should be the address of the delegating 503 // account. 504 func VerifyLogicSig(lsig types.LogicSig, singleSigner types.Address) (result bool) { 505 if err := sanityCheckProgram(lsig.Logic); err != nil { 506 return false 507 } 508 509 hasSig := lsig.Sig != (types.Signature{}) 510 hasMsig := !lsig.Msig.Blank() 511 512 // require only one or zero sig 513 if hasSig && hasMsig { 514 return false 515 } 516 517 toBeSigned := programToSign(lsig.Logic) 518 519 if hasSig { 520 return ed25519.Verify(singleSigner[:], toBeSigned, lsig.Sig[:]) 521 } 522 523 if hasMsig { 524 msigAccount, err := MultisigAccountFromSig(lsig.Msig) 525 if err != nil { 526 return false 527 } 528 addr, err := msigAccount.Address() 529 if err != nil { 530 return false 531 } 532 return VerifyMultisig(addr, toBeSigned, lsig.Msig) 533 } 534 535 // the lsig account is the hash of its program bytes, nothing left to verify 536 return true 537 } 538 539 // signLogicSigTransactionWithAddress signs a transaction with a LogicSig. 540 // 541 // lsigAddress is the address of the account that the LogicSig represents. 542 func signLogicSigTransactionWithAddress(lsig types.LogicSig, lsigAddress types.Address, tx types.Transaction) (txid string, stxBytes []byte, err error) { 543 544 if !VerifyLogicSig(lsig, lsigAddress) { 545 err = errLsigInvalidSignature 546 return 547 } 548 549 txid = txIDFromTransaction(tx) 550 // Construct the SignedTxn 551 stx := types.SignedTxn{ 552 Lsig: lsig, 553 Txn: tx, 554 } 555 556 if stx.Txn.Sender != lsigAddress { 557 stx.AuthAddr = lsigAddress 558 } 559 560 // Encode the SignedTxn 561 stxBytes = msgpack.Encode(stx) 562 return 563 } 564 565 // SignLogicSigAccountTransaction signs a transaction with a LogicSigAccount. It 566 // returns the TxID of the signed transaction and the raw bytes ready to be 567 // broadcast to the network. Note: any type of transaction can be signed by a 568 // LogicSig, but the network will reject the transaction if the LogicSig's 569 // program declines the transaction. 570 func SignLogicSigAccountTransaction(logicSigAccount LogicSigAccount, tx types.Transaction) (txid string, stxBytes []byte, err error) { 571 addr, err := logicSigAccount.Address() 572 if err != nil { 573 return 574 } 575 576 txid, stxBytes, err = signLogicSigTransactionWithAddress(logicSigAccount.Lsig, addr, tx) 577 return 578 } 579 580 // SignLogicsigTransaction takes LogicSig object and a transaction and returns the 581 // bytes of a signed transaction ready to be broadcasted to the network 582 // Note, LogicSig actually can be attached to any transaction and it is a 583 // program's responsibility to approve/decline the transaction 584 // 585 // This function supports signing transactions with a sender that differs from 586 // the LogicSig's address, EXCEPT IF the LogicSig is delegated to a non-multisig 587 // account. In order to properly handle that case, create a LogicSigAccount and 588 // use SignLogicSigAccountTransaction instead. 589 func SignLogicsigTransaction(lsig types.LogicSig, tx types.Transaction) (txid string, stxBytes []byte, err error) { 590 hasSig := lsig.Sig != (types.Signature{}) 591 hasMsig := !lsig.Msig.Blank() 592 593 // the address that the LogicSig represents 594 var lsigAddress types.Address 595 if hasSig { 596 // For a LogicSig with a non-multisig delegating account, we cannot derive 597 // the address of that account from only its signature, so assume the 598 // delegating account is the sender. If that's not the case, the signing 599 // will fail. 600 lsigAddress = tx.Header.Sender 601 } else if hasMsig { 602 var msigAccount MultisigAccount 603 msigAccount, err = MultisigAccountFromSig(lsig.Msig) 604 if err != nil { 605 return 606 } 607 lsigAddress, err = msigAccount.Address() 608 if err != nil { 609 return 610 } 611 } else { 612 lsigAddress = LogicSigAddress(lsig) 613 } 614 615 txid, stxBytes, err = signLogicSigTransactionWithAddress(lsig, lsigAddress, tx) 616 return 617 } 618 619 func programToSign(program []byte) []byte { 620 parts := [][]byte{programPrefix, program} 621 toBeSigned := bytes.Join(parts, nil) 622 return toBeSigned 623 } 624 625 func signProgram(sk ed25519.PrivateKey, program []byte) (sig types.Signature, err error) { 626 toBeSigned := programToSign(program) 627 rawSig := ed25519.Sign(sk, toBeSigned) 628 n := copy(sig[:], rawSig) 629 if n != len(sig) { 630 err = errInvalidSignatureReturned 631 return 632 } 633 return 634 } 635 636 // AddressFromProgram returns escrow account address derived from TEAL bytecode 637 func AddressFromProgram(program []byte) types.Address { 638 toBeHashed := programToSign(program) 639 hash := sha512.Sum512_256(toBeHashed) 640 return types.Address(hash) 641 } 642 643 // MakeLogicSig produces a new LogicSig signature. 644 // 645 // Deprecated: THIS FUNCTION IS DEPRECATED. 646 // It will be removed in v2 of this library. 647 // Use one of MakeLogicSigAccountEscrow, MakeLogicSigAccountDelegated, or 648 // MakeLogicSigAccountDelegatedMsig instead. 649 // 650 // The function can work in three modes: 651 // 1. If no sk and ma provided then it returns contract-only LogicSig 652 // 2. If no ma provides, it returns Sig delegated LogicSig 653 // 3. If both sk and ma specified the function returns Multisig delegated LogicSig 654 func MakeLogicSig(program []byte, args [][]byte, sk ed25519.PrivateKey, ma MultisigAccount) (lsig types.LogicSig, err error) { 655 if err = sanityCheckProgram(program); err != nil { 656 return 657 } 658 659 if sk == nil && ma.Blank() { 660 lsig.Logic = program 661 lsig.Args = args 662 return 663 } 664 665 if ma.Blank() { 666 var sig types.Signature 667 sig, err = signProgram(sk, program) 668 if err != nil { 669 return 670 } 671 672 lsig.Logic = program 673 lsig.Args = args 674 lsig.Sig = types.Signature(sig) 675 return 676 } 677 678 // Format Multisig 679 err = ma.Validate() 680 if err != nil { 681 return 682 } 683 684 // this signer signs a program 685 customSigner := func() (rawSig types.Signature, err error) { 686 return signProgram(sk, program) 687 } 688 689 msig, _, err := multisigSingle(sk, ma, customSigner) 690 if err != nil { 691 return 692 } 693 694 lsig.Logic = program 695 lsig.Args = args 696 lsig.Msig = msig 697 698 return 699 } 700 701 // AppendMultisigToLogicSig adds a new signature to multisigned LogicSig 702 func AppendMultisigToLogicSig(lsig *types.LogicSig, sk ed25519.PrivateKey) error { 703 if lsig.Msig.Blank() { 704 return errLsigEmptyMsig 705 } 706 707 ma, err := MultisigAccountFromSig(lsig.Msig) 708 if err != nil { 709 return err 710 } 711 712 customSigner := func() (rawSig types.Signature, err error) { 713 return signProgram(sk, lsig.Logic) 714 } 715 716 msig, idx, err := multisigSingle(sk, ma, customSigner) 717 if err != nil { 718 return err 719 } 720 721 lsig.Msig.Subsigs[idx] = msig.Subsigs[idx] 722 723 return nil 724 } 725 726 // TealSign creates a signature compatible with ed25519verify opcode from contract address 727 func TealSign(sk ed25519.PrivateKey, data []byte, contractAddress types.Address) (rawSig types.Signature, err error) { 728 msgParts := [][]byte{programDataPrefix, contractAddress[:], data} 729 toBeSigned := bytes.Join(msgParts, nil) 730 731 signature := ed25519.Sign(sk, toBeSigned) 732 // Copy the resulting signature into a Signature, and check that it's 733 // the expected length 734 n := copy(rawSig[:], signature) 735 if n != len(rawSig) { 736 err = errInvalidSignatureReturned 737 } 738 return 739 } 740 741 // TealSignFromProgram creates a signature compatible with ed25519verify opcode from raw program bytes 742 func TealSignFromProgram(sk ed25519.PrivateKey, data []byte, program []byte) (rawSig types.Signature, err error) { 743 addr := AddressFromProgram(program) 744 return TealSign(sk, data, addr) 745 } 746 747 // TealVerify verifies signatures generated by TealSign and TealSignFromProgram 748 func TealVerify(pk ed25519.PublicKey, data []byte, contractAddress types.Address, rawSig types.Signature) bool { 749 msgParts := [][]byte{programDataPrefix, contractAddress[:], data} 750 toBeVerified := bytes.Join(msgParts, nil) 751 752 return ed25519.Verify(pk, toBeVerified, rawSig[:]) 753 } 754 755 // GetApplicationAddress returns the address corresponding to an application's escrow account. 756 func GetApplicationAddress(appID uint64) types.Address { 757 encodedAppID := make([]byte, 8) 758 binary.BigEndian.PutUint64(encodedAppID, appID) 759 760 parts := [][]byte{appIDPrefix, encodedAppID} 761 toBeHashed := bytes.Join(parts, nil) 762 763 hash := sha512.Sum512_256(toBeHashed) 764 return types.Address(hash) 765 } 766 767 func HashStateProofMessage(stateProofMessage *types.Message) types.MessageHash { 768 msgPackedStateProofMessage := msgpack.Encode(stateProofMessage) 769 770 stateProofMessageData := make([]byte, 0, len(StateProofMessagePrefix)+len(msgPackedStateProofMessage)) 771 stateProofMessageData = append(stateProofMessageData, StateProofMessagePrefix...) 772 stateProofMessageData = append(stateProofMessageData, msgPackedStateProofMessage...) 773 774 return sha256.Sum256(stateProofMessageData) 775 } 776 777 func HashLightBlockHeader(lightBlockHeader types.LightBlockHeader) types.Digest { 778 msgPackedLightBlockHeader := msgpack.Encode(lightBlockHeader) 779 780 lightBlockHeaderData := make([]byte, 0, len(LightBlockHeaderPrefix)+len(msgPackedLightBlockHeader)) 781 lightBlockHeaderData = append(lightBlockHeaderData, LightBlockHeaderPrefix...) 782 lightBlockHeaderData = append(lightBlockHeaderData, msgpack.Encode(lightBlockHeader)...) 783 784 return sha256.Sum256(lightBlockHeaderData) 785 }